Mercurial > hg > octave-image
changeset 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 | 0219144c2c21 |
children | 5e256614c376 |
files | COPYING src/Makefile src/bwlabeln.cc src/conndef.cc src/conndef.h src/connectivity.cc src/connectivity.h |
diffstat | 6 files changed, 25 insertions(+), 496 deletions(-) [+] |
line wrap: on
line diff
--- a/COPYING +++ b/COPYING @@ -143,7 +143,8 @@ src/bwfill.cc GPLv3+ src/bwlabeln.cc GPLv3+ src/conndef.cc GPLv3+ -src/conndef.h GPLv3+ +src/connectivity.cc GPLv3+ +src/connectivity.h GPLv3+ src/__custom_gaussian_smoothing__.cc GPLv3+ src/graycomatrix.cc FreeBSD src/hough_line.cc FreeBSD
--- a/src/Makefile +++ b/src/Makefile @@ -1,25 +1,31 @@ MKOCTFILE ?= mkoctfile -Wall +## We can't link oct files, and Octave's package system does not handle +## shared libraries. Because of this, we need to create object files for +## our "shared" libraries and statically link to selected oct files. + +conn_dependent = conndef.oct bwlabeln.oct +strel_dependent = imerode.oct +libs = connectivity.o strel.o + all: __spatial_filtering__.oct __bilateral__.oct __custom_gaussian_smoothing__.oct \ __boundary__.oct bwfill.oct rotate_scale.oct hough_line.oct \ - graycomatrix.oct bwdist.oct nonmax_supress.oct bwlabeln.oct imerode.oct \ - conndef.oct + graycomatrix.oct bwdist.oct nonmax_supress.oct \ + $(strel_dependent) $(conn_dependent) + +%.o: %.cc + $(MKOCTFILE) -c $< + +## Actually, only bwlabeln needs c++0x +$(conn_dependent): %.oct: %.cc connectivity.o + CXXFLAGS=$$($(MKOCTFILE) -p CXXFLAGS)' -std=c++0x' $(MKOCTFILE) $^ + +$(strel_dependent): %.oct: %.cc strel.o + $(MKOCTFILE) $^ %.oct: %.cc $(MKOCTFILE) $< -bwlabeln.oct: bwlabeln.cc union-find.h++ - CXXFLAGS='-g -O2 -std=c++0x -Wall' $(MKOCTFILE) $< - -imerode.oct: imerode.cc strel.cc - $(MKOCTFILE) $^ -o $@ - -conndef.o: conndef.cc conndef.h - $(MKOCTFILE) $< - -conndef.oct: conndef.o - $(MKOCTFILE) $^ - clean: rm -f *.o octave-core core *.oct *~
--- a/src/bwlabeln.cc +++ b/src/bwlabeln.cc @@ -26,7 +26,7 @@ #include <algorithm> #include "union-find.h++" -#include "conndef.h" +#include "connectivity.h" using namespace octave::image; #include "config.h"
--- a/src/conndef.cc +++ b/src/conndef.cc @@ -15,230 +15,10 @@ // <http://www.gnu.org/licenses/>. #include <octave/oct.h> -#include "conndef.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; -} - - // The conndef() function is really really simple and could have easily // been a m file (actually it once was, check the hg log if it ever needs // to be recovered) but then it would be awkward to call it from oct @@ -339,7 +119,6 @@ return octave_value (NDArray (conn.mask)); } - /* %!assert (conndef (1, "minimal"), [1; 1; 1]); @@ -428,7 +207,6 @@ @end deftypefn") { const octave_idx_type nargin = args.length (); -// const octave_value rv = octave_value (); if (nargin < 3 || nargin > 4) {
copy from src/conndef.cc copy to src/connectivity.cc --- a/src/conndef.cc +++ b/src/connectivity.cc @@ -15,7 +15,7 @@ // <http://www.gnu.org/licenses/>. #include <octave/oct.h> -#include "conndef.h" +#include "connectivity.h" using namespace octave::image; @@ -238,259 +238,3 @@ return mask; } - -// The conndef() function is really really simple and could have easily -// been a m file (actually it once was, check the hg log if it ever needs -// to be recovered) but then it would be awkward to call it from oct -// functions so we made a C++ class for it. - -DEFUN_DLD(conndef, args, , "\ --*- texinfo -*-\n\ -@deftypefn {Loadable Function} {} conndef (@var{conn})\n\ -@deftypefnx {Loadable Function} {} conndef (@var{ndims}, @var{type})\n\ -Create connectivity array.\n\ -\n\ -Creates a matrix of for morphological operations, where elements with\n\ -a value of 1 are considered connected to the center element (a\n\ -connectivity array).\n\ -\n\ -It can be specified by the number of dimensions, @var{ndims}, and\n\ -@var{type} which must be one of the following strings:\n\ -\n\ -@table @asis\n\ -@item @qcode{\"minimal\"}\n\ -Neighbours touch the central element on a (@var{ndims}-1)-dimensional\n\ -surface.\n\ -\n\ -@item @qcode{\"maximal\"}\n\ -Neighbours touch the central element in any way. Equivalent to\n\ -@code{ones (repmat (3, 1, @var{ndims}))}.\n\ -\n\ -@end table\n\ -\n\ -or the number of connected elements to the center element, @var{conn},\n\ -in which case the following are valid:\n\ -\n\ -@table @asis\n\ -@item 4\n\ -Two-dimensional 4-connected neighborhood.\n\ -\n\ -@item 8\n\ -Two-dimensional 8-connected neighborhood.\n\ -\n\ -@item 6\n\ -Three-dimensional 6-connected neighborhood.\n\ -\n\ -@item 18\n\ -Three-dimensional 18-connected neighborhood.\n\ -\n\ -@item 26\n\ -Three-dimensional 26-connected neighborhood.\n\ -\n\ -@end table\n\ -\n\ -\n\ -@seealso{iptcheckconn, strel}\n\ -@end deftypefn") -{ - const octave_idx_type nargin = args.length (); - - if (nargin < 1 || nargin > 2) - { - print_usage (); - return octave_value (); - } - const octave_idx_type arg0 = args(0).idx_type_value (true); - if (error_state || arg0 < 1) - { - error ("conndef: NDIMS and CONN must be a positive integer"); - return octave_value (); - } - - connectivity conn; - if (nargin == 1) - { - try - {conn = connectivity (arg0);} - catch (invalid_connectivity& e) - { - error ("conndef: CONN %s", e.what ()); - return octave_value (); - } - } - else - { - const std::string type = args(1).string_value (); - if (error_state) - { - error ("conndef: TYPE must be a string"); - return octave_value (); - } - try - {conn = connectivity (arg0, type);} - catch (invalid_connectivity& e) - { - error ("conndef: TYPE %s", e.what ()); - return octave_value (); - } - } - - // we must return an array of class double - return octave_value (NDArray (conn.mask)); -} - - -/* - -%!assert (conndef (1, "minimal"), [1; 1; 1]); -%!assert (conndef (2, "minimal"), [0 1 0; 1 1 1; 0 1 0]); - -%!test -%! C = zeros (3, 3, 3); -%! C(:,2,2) = 1; -%! C(2,:,2) = 1; -%! C(2,2,:) = 1; -%! assert (conndef (3, "minimal"), C); - -%!test -%! C = zeros (3, 3, 3, 3); -%! C(:,:,2,1) = [0 0 0 -%! 0 1 0 -%! 0 0 0]; -%! C(:,:,1,2) = [0 0 0 -%! 0 1 0 -%! 0 0 0]; -%! C(:,:,2,2) = [0 1 0 -%! 1 1 1 -%! 0 1 0]; -%! C(:,:,3,2) = [0 0 0 -%! 0 1 0 -%! 0 0 0]; -%! C(:,:,2,3) = [0 0 0 -%! 0 1 0 -%! 0 0 0]; -%! assert (conndef (4, "minimal"), C); - -%!assert (conndef (1, "maximal"), ones (3, 1)); -%!assert (conndef (2, "maximal"), ones (3, 3)); -%!assert (conndef (3, "maximal"), ones (3, 3, 3)); -%!assert (conndef (4, "maximal"), ones (3, 3, 3, 3)); - -%!assert (nnz (conndef (3, "minimal")), 7) -%!assert (nnz (conndef (4, "minimal")), 9) -%!assert (nnz (conndef (5, "minimal")), 11) -%!assert (nnz (conndef (6, "minimal")), 13) - -%!assert (find (conndef (3, "minimal")), [5 11 13 14 15 17 23](:)) -%!assert (find (conndef (4, "minimal")), [14 32 38 40 41 42 44 50 68](:)) -%!assert (find (conndef (5, "minimal")), -%! [ 41 95 113 119 121 122 123 125 131 149 203](:)) -%!assert (find (conndef (6, "minimal")), -%! [ 122 284 338 356 362 364 365 366 368 374 392 446 608](:)) - -%!error conndef () -%!error <must be a positive integer> conndef (-2, "minimal") -%!error conndef (char (2), "minimal") -%!error conndef ("minimal", 3) -%!error <TYPE must be "maximal" or "minimal"> conndef (3, "invalid") -%!error <CONN must be in the set> conndef (10) - -%!assert (conndef (2, "minimal"), conndef (4)) -%!assert (conndef (2, "maximal"), conndef (8)) -%!assert (conndef (3, "minimal"), conndef (6)) -%!assert (conndef (3, "maximal"), conndef (26)) - -%!assert (conndef (18), reshape ([0 1 0 1 1 1 0 1 0 -%! 1 1 1 1 1 1 1 1 1 -%! 0 1 0 1 1 1 0 1 0], [3 3 3])) -*/ - -// PKG_ADD: autoload ("iptcheckconn", which ("conndef")); -// PKG_DEL: autoload ("iptcheckconn", which ("conndef"), "remove"); -DEFUN_DLD(iptcheckconn, args, , "\ --*- texinfo -*-\n\ -@deftypefn {Loadable Function} {} iptcheckconn (@var{conn}, @var{func}, @var{var})\n\ -@deftypefnx {Loadable Function} {} iptcheckconn (@var{conn}, @var{func}, @var{var}, @var{pos})\n\ -Check if argument is valid connectivity.\n\ -\n\ -If @var{conn} is not a valid connectivity argument, gives a properly\n\ -formatted error message. @var{func} is the name of the function to be\n\ -used on the error message, @var{var} the name of the argument being\n\ -checked (for the error message), and @var{pos} the position of the\n\ -argument in the input.\n\ -\n\ -A valid connectivity argument must be either double or logical. It must\n\ -also be either a scalar from set [4 6 8 18 26], or a symmetric matrix\n\ -with all dimensions of size 3, with only 0 or 1 as values, and 1 at its\n\ -center.\n\ -\n\ -@seealso{conndef}\n\ -@end deftypefn") -{ - const octave_idx_type nargin = args.length (); -// const octave_value rv = octave_value (); - - if (nargin < 3 || nargin > 4) - { - print_usage (); - return octave_value (); - } - - const std::string func = args(1).string_value (); - if (error_state) - { - error ("iptcheckconn: FUNC must be a string"); - return octave_value (); - } - const std::string var = args(2).string_value (); - if (error_state) - { - error ("iptcheckconn: VAR must be a string"); - return octave_value (); - } - octave_idx_type pos (0); - if (nargin > 3) - { - pos = args(3).idx_type_value (true); - if (error_state || pos < 1) - { - error ("iptcheckconn: POS must be a positive integer"); - return octave_value (); - } - } - - try - {const connectivity conn (args(0));} - catch (invalid_connectivity& e) - { - if (pos == 0) - error ("%s: %s %s", func.c_str (), var.c_str (), e.what ()); - else - error ("%s: %s, at pos %i, %s", - func.c_str (), var.c_str (), pos, e.what ()); - } - return octave_value (); -} - -/* -// the complete error message should be "expected error <.> but got none", -// but how to escape <> within the error message? - -%!error <expected error> fail ("iptcheckconn ( 4, 'func', 'var')"); -%!error <expected error> fail ("iptcheckconn ( 6, 'func', 'var')"); -%!error <expected error> fail ("iptcheckconn ( 8, 'func', 'var')"); -%!error <expected error> fail ("iptcheckconn (18, 'func', 'var')"); -%!error <expected error> fail ("iptcheckconn (26, 'func', 'var')"); - -%!error <expected error> fail ("iptcheckconn (1, 'func', 'var')"); -%!error <expected error> fail ("iptcheckconn (ones (3, 1), 'func', 'var')"); -%!error <expected error> fail ("iptcheckconn (ones (3, 3), 'func', 'var')"); -%!error <expected error> fail ("iptcheckconn (ones (3, 3, 3), 'func', 'var')"); -%!error <expected error> fail ("iptcheckconn (ones (3, 3, 3, 3), 'func', 'var')"); - -%!error <VAR must be logical or in> iptcheckconn (3, "func", "VAR"); -%!error <VAR center is not true> iptcheckconn ([1 1 1; 1 0 1; 1 1 1], "func", "VAR"); -%!error <VAR must be logical or in> iptcheckconn ([1 2 1; 1 1 1; 1 1 1], "func", "VAR"); -%!error <VAR is not symmetric relative to its center> iptcheckconn ([0 1 1; 1 1 1; 1 1 1], "func", "VAR"); -%!error <VAR is not 3x3x...x3> iptcheckconn (ones (3, 3, 3, 4), "func", "VAR"); -*/