Mercurial > hg > octave-image
view src/connectivity.cc @ 906:475a5a2a08cb
Fix make rules and handling of "shared" libraries.
* Makefile: we wanted to have shared libraries for strel.so and
connectivity.so but that's not really possible (Octave's pkg does not
have a system to handle this). So we create object files and statically
link them. This the closest we can do at the moment. Also change setting
CXXFLAGS to only add '-std=c++0x' rather than defining all the other options
again.
* conndef.h, connectivity.h: renamed the first as the later.
* conndef.cc: moved the definition of the connectivity class into its own
connectivity.cc file and include that. The idea is to then create a shared
library without Fconndef and Fiptcheckconn but that did not reallt happen yet.
* connectivity.cc: definition of the connectivity class, from conndef.cc.
* bwlabeln.cc: change the include for the name connectivity header file.
* COPYING: update license for the new files.
author | Carnë Draug <carandraug@octave.org> |
---|---|
date | Thu, 30 Oct 2014 21:34:55 +0000 |
parents | src/conndef.cc@f34897bc944f |
children | 5e256614c376 |
line wrap: on
line source
// Copyright (C) 2014 Carnë Draug <carandraug@octave.org> // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as // published by the Free Software Foundation; either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, but // WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, see // <http://www.gnu.org/licenses/>. #include <octave/oct.h> #include "connectivity.h" using namespace octave::image; connectivity::connectivity () { } connectivity::connectivity (const octave_value& val) { try { const double conn = double_value (val); if (error_state) throw invalid_connectivity ("must be in [4 6 8 18 26]"); ctor (conn); } catch (invalid_connectivity& e) { const boolNDArray mask = bool_array_value (val); if (error_state) throw invalid_connectivity ("must be logical or in [4 6 8 18 26]"); ctor (mask); } return; } connectivity::connectivity (const boolNDArray& mask) { ctor (mask); return; } void connectivity::ctor (const boolNDArray& mask) { // Must be 1x1, 3x1, or 3x3x3x...x3 const octave_idx_type numel = mask.numel (); const octave_idx_type ndims = mask.ndims (); const dim_vector dims = mask.dims (); if (ndims == 2) { // Don't forget 1x1, and 3x1 which are valid but arrays always // have at least 2d if ( (dims(1) != 3 && dims(2) != 3) && (dims(1) != 3 && dims(2) != 1) && (dims(1) != 1 && dims(2) != 1)) throw invalid_connectivity ("is not 1x1, 3x1, 3x3, or 3x3x...x3"); } else { for (octave_idx_type i = 0; i < ndims; i++) if (dims(i) != 3) throw invalid_connectivity ("is not 3x3x...x3"); } // Center must be true const octave_idx_type center = floor (numel /2); if (! mask(center)) throw invalid_connectivity ("center is not true"); // Must be symmetric relative to its center const bool* start = mask.fortran_vec (); const bool* end = mask.fortran_vec () + (numel -1); for (octave_idx_type i = 0; i < center; i++) if (start[i] != end[-i]) throw invalid_connectivity ("is not symmetric relative to its center"); this->mask = mask; return; } connectivity::connectivity (const octave_idx_type& conn) { ctor (conn); return; } void connectivity::ctor (const octave_idx_type& conn) { if (conn == 4) { mask = boolNDArray (dim_vector (3, 3), true); bool* md = mask.fortran_vec (); md[ 0] = false; md[ 2] = false; md[ 6] = false; md[ 8] = false; } else if (conn == 6) { mask = boolNDArray (dim_vector (3, 3, 3), false); bool* md = mask.fortran_vec (); md[ 4] = true; md[10] = true; md[12] = true; md[13] = true; md[14] = true; md[16] = true; md[22] = true; } else if (conn == 8) mask = boolNDArray (dim_vector (3, 3), true); else if (conn == 18) { mask = boolNDArray (dim_vector (3, 3, 3), true); bool* md = mask.fortran_vec (); md[ 0] = false; md[ 2] = false; md[ 6] = false; md[ 8] = false; md[18] = false; md[20] = false; md[24] = false; md[26] = false; } else if (conn == 26) mask = boolNDArray (dim_vector (3, 3, 3), true); else throw invalid_connectivity ("must be in the set [4 6 8 18 26]"); return; } connectivity::connectivity (const octave_idx_type& ndims, const std::string& type) { dim_vector size; if (ndims == 1) size = dim_vector (3, 1); else { size = dim_vector (3, 3); size.resize (ndims, 3); } if (type == "maximal") { mask = boolNDArray (size, true); } else if (type == "minimal") { mask = boolNDArray (size, false); bool* md = mask.fortran_vec (); md += int (floor (pow (3, ndims) /2)); // move to center md[0] = true; for (octave_idx_type dim = 0; dim < ndims; dim++) { const octave_idx_type stride = pow (3, dim); md[ stride] = true; md[-stride] = true; } } else throw invalid_connectivity ("must be \"maximal\" or \"minimal\""); return; } Array<octave_idx_type> connectivity::offsets (const dim_vector& size) const { const octave_idx_type nnz = mask.nnz (); const octave_idx_type ndims = mask.ndims (); const dim_vector dims = mask.dims (); Array<octave_idx_type> offsets (dim_vector (nnz, 1)); // retval const dim_vector cum_size = size.cumulative (); Array<octave_idx_type> diff (dim_vector (ndims, 1)); Array<octave_idx_type> sub (dim_vector (ndims, 1), 0); for (octave_idx_type ind = 0, found = 0; found < nnz; ind++, boolNDArray::increment_index (sub, dims)) { if (mask(ind)) { for (octave_idx_type i = 0; i < ndims; i++) diff(i) = 1 - sub(i); // 1 is center since conn is 3x3x...x3 octave_idx_type off = diff(0); for (octave_idx_type dim = 1; dim < ndims; dim++) off += (diff(dim) * cum_size(dim-1)); offsets(found) = off; found++; } } return offsets; } double connectivity::double_value (const octave_value& val) { error_state = 0; const double conn = val.double_value (); // Check is_scalar_type because the warning Octave:array-to-scalar // is off by default and we will get the first element only. if (error_state || ! val.is_scalar_type ()) error_state = 1; return conn; } boolNDArray connectivity::bool_array_value (const octave_value& val) { error_state = 0; const boolNDArray mask = val.bool_array_value (); // bool_array_value converts anything other than 0 to true, which will // then validate as conn array, hence any_element_not_one_or_zero() if (val.array_value ().any_element_not_one_or_zero ()) error_state = 1; return mask; }