Mercurial > hg > octave-image
changeset 397:127b553dc8e4
Work on binary input
author | hauberg |
---|---|
date | Fri, 05 Mar 2010 02:48:41 +0000 |
parents | 39a521b5484e |
children | 52acbfa0695e |
files | src/bwlabel.cc |
diffstat | 1 files changed, 225 insertions(+), 156 deletions(-) [+] |
line wrap: on
line diff
--- a/src/bwlabel.cc +++ b/src/bwlabel.cc @@ -34,16 +34,47 @@ #define NO_OBJECT 0 #define MIN(x, y) (((x) < (y)) ? (x) : (y)) - - -static int find( int *, int ); +static int find (int set [], int x) +{ + int r = x; + while (set [r] != r) + r = set [r]; + return r; +} -static bool any_bad_argument( const octave_value_list& ); - +static bool any_bad_argument (const octave_value_list& args) +{ + const int nargin = args.length (); + if (nargin < 1 || nargin > 2) + { + print_usage (); + return true; + } + + if (!args (0).is_bool_matrix ()) + { + error ("bwlabel: first input argument must be a 'logical' matrix"); + return true; + } + + if (nargin == 2) + { + if (!args (1).is_real_scalar ()) + { + error ("bwlabel: second input argument must be a real scalar"); + return true; + } + const int n = args (1).int_value (); + if (n != 4 && n != 6 && n != 8) + { + error ("bwlabel: second input argument bust be either 4, 6 or 8"); + return true; + } + } + + return false; +} -/* -%!assert(bwlabel([0 1 0; 0 0 0; 1 0 1]),[0 1 0; 0 0 0; 2 0 3]); -*/ DEFUN_DLD(bwlabel, args, , "\ -*- texinfo -*-\n\ @deftypefn {Function File} {[@var{l}, @var{num}] =} bwlabel(@var{bw}, @var{n})\n\ @@ -62,174 +93,212 @@ @end deftypefn\n\ ") { - if ( any_bad_argument(args) ) - return octave_value_list(); + octave_value_list rval; + if (any_bad_argument (args)) + return rval; - // input arguments - Matrix BW = args(0).matrix_value(); // the input binary image - int n; - if ( args.length() < 2 ) n = 8; // n-hood connectivity - else n = args(1).int_value(); - int nr = args(0).rows(); - int nc = args(0).columns(); + // input arguments + boolMatrix BW = args (0).bool_matrix_value (); // the input binary image + int nr = BW.rows (); + int nc = BW.columns (); + + // n-hood connectivity + int n; + if (args.length () < 2) + n = 8; + else + n = args (1).int_value (); - // results - Matrix L( nr, nc ); // the label image - int nobj; // number of objects found in image + // results + Matrix L (nr, nc); // the label image + int nobj; // number of objects found in image - // other variables - int ntable; // number of elements in the component table/tree + // other variables + int ntable; // number of elements in the component table/tree + + OCTAVE_LOCAL_BUFFER (int, lset, nr * nc); // label table/tree + ntable = 0; + lset [0] = 0; - OCTAVE_LOCAL_BUFFER(int, lset, nr * nc); // label table/tree - ntable = 0; - lset[0] = 0; - - for( int r = 0; r < nr; r++ ) { - for( int c = 0; c < nc; c++ ) { - if ( BW.elem(r,c) ) { // if A is an object - // get the neighboring pixels B, C, D, and E - int B, C, D, E; - if ( c == 0 ) B = 0; else B = find( lset, (int)L.elem(r,c-1) ); - if ( r == 0 ) C = 0; else C = find( lset, (int)L.elem(r-1,c) ); - if ( r == 0 || c == 0 ) D = 0; else D = find( lset, (int)L.elem(r-1,c-1) ); - if ( r == 0 || c == nc - 1 ) E = 0; - else E = find( lset, (int)L.elem(r-1,c+1) ); + for (int r = 0; r < nr; r++) + { + for (int c = 0; c < nc; c++) + { + if (BW.elem (r, c)) // if A is an object + { + // get the neighboring pixels B, C, D, and E + int B, C, D, E; + if (c == 0) + B = 0; + else + B = find (lset, (int)L.elem (r, c-1)); + + if (r == 0) + C = 0; + else + C = find (lset, (int)L.elem (r-1, c)); + + if (r == 0 || c == 0) + D = 0; + else + D = find (lset, (int)L.elem (r-1, c-1)); + + if (r == 0 || c == nc - 1) + E = 0; + else + E = find (lset, (int)L.elem(r-1, c+1)); - if ( n == 4 ) { - // apply 4 connectedness - if ( B && C ) { // B and C are labeled - if ( B == C ) - L.elem(r,c) = B; - else { - lset[C] = B; - L.elem(r,c) = B; + if (n == 4) + { + // apply 4 connectedness + if (B && C) // B and C are labeled + { + if ( B == C ) + { + L.elem (r, c) = B; } - } else if ( B ) // B is object but C is not - L.elem(r,c) = B; - else if ( C ) // C is object but B is not - L.elem(r,c) = C; - else { // B, C, D not object - new object - // label and put into table - ntable++; - L.elem(r,c) = lset[ ntable ] = ntable; - } - } else if ( n == 6 ) { - // apply 6 connected ness - if ( D ) // D object, copy label and move on - L.elem(r,c) = D; - else if ( B && C ) { // B and C are labeled - if ( B == C ) - L.elem(r,c) = B; - else { - int tlabel = MIN(B,C); - lset[B] = tlabel; - lset[C] = tlabel; - L.elem(r,c) = tlabel; + else + { + lset [C] = B; + L.elem (r, c) = B; } - } else if ( B ) // B is object but C is not - L.elem(r,c) = B; - else if ( C ) // C is object but B is not - L.elem(r,c) = C; - else { // B, C, D not object - new object - // label and put into table - ntable++; - L.elem(r,c) = lset[ ntable ] = ntable; + } + else if (B) // B is object but C is not + { + L.elem (r, c) = B; + } + else if (C) // C is object but B is not + { + L.elem (r, c) = C; + } + else // B, C, D not object - new object + { + // label and put into table + ntable ++; + L.elem (r, c) = lset [ntable] = ntable; + } + } + else if (n == 6) + { + // apply 6 connected ness + if (D) // D object, copy label and move on + { + L.elem (r, c) = D; } - } else if ( n == 8 ) { - // apply 8 connectedness - if ( B || C || D || E ) { - int tlabel = B; - if ( B ) tlabel = B; - else if ( C ) tlabel = C; - else if ( D ) tlabel = D; - else if ( E ) tlabel = E; - L.elem(r,c) = tlabel; - if ( B && B != tlabel ) lset[B] = tlabel; - if ( C && C != tlabel ) lset[C] = tlabel; - if ( D && D != tlabel ) lset[D] = tlabel; - if ( E && E != tlabel ) lset[E] = tlabel; - } else { - // label and put into table - ntable++; - L.elem(r,c) = lset[ ntable ] = ntable; + else if (B && C) // B and C are labeled + { + if (B == C) + { + L.elem (r, c) = B; + } + else + { + int tlabel = MIN (B, C); + lset [B] = tlabel; + lset [C] = tlabel; + L.elem (r, c) = tlabel; + } + } + else if (B) // B is object but C is not + { + L.elem (r, c) = B; + } + else if (C) // C is object but B is not + { + L.elem (r, c) = C; + } + else // B, C, D not object - new object + { + // label and put into table + ntable ++; + L.elem (r, c) = lset [ntable] = ntable; } } - } else { - L.elem(r,c) = NO_OBJECT; // A is not an object so leave it + else if (n == 8) + { + // apply 8 connectedness + if (B || C || D || E) + { + int tlabel = B; + if (B) + { + tlabel = B; + } + else if (C) + { + tlabel = C; + } + else if (D) + { + tlabel = D; + } + else if (E) + { + tlabel = E; + } + + L.elem (r, c) = tlabel; + + if (B && B != tlabel) + lset [B] = tlabel; + if (C && C != tlabel) + lset [C] = tlabel; + if (D && D != tlabel) + lset [D] = tlabel; + if (E && E != tlabel) + lset [E] = tlabel; + } + else + { + // label and put into table + ntable ++; + L.elem (r, c) = lset [ntable] = ntable; + } + } + } + else + { + L.elem (r, c) = NO_OBJECT; // A is not an object so leave it } } } - // consolidate component table - for( int i = 0; i <= ntable; i++ ) - lset[i] = find( lset, i ); + // consolidate component table + for (int i = 0; i <= ntable; i++) + lset [i] = find (lset, i); - // run image through the look-up table - for( int r = 0; r < nr; r++ ) - for( int c = 0; c < nc; c++ ) - L.elem(r,c) = lset[ (int)L.elem(r,c) ]; + // run image through the look-up table + for (int r = 0; r < nr; r++) + for (int c = 0; c < nc; c++) + L.elem (r, c) = lset [(int)L.elem (r, c)]; - // count up the objects in the image - for( int i = 0; i <= ntable; i++ ) - lset[i] = 0; + // count up the objects in the image + for (int i = 0; i <= ntable; i++) + lset [i] = 0; - for( int r = 0; r < nr; r++ ) - for( int c = 0; c < nc; c++ ) - lset[ (int)L.elem(r,c) ]++; + for (int r = 0; r < nr; r++) + for (int c = 0; c < nc; c++) + lset [(int)L.elem (r, c)] ++; - // number the objects from 1 through n objects - nobj = 0; - lset[0] = 0; - for( int i = 1; i <= ntable; i++ ) - if ( lset[i] > 0 ) - lset[i] = ++nobj; + // number the objects from 1 through n objects + nobj = 0; + lset [0] = 0; + for (int i = 1; i <= ntable; i++) + if (lset [i] > 0) + lset [i] = ++nobj; - // run through the look-up table again - for( int r = 0; r < nr; r++ ) - for( int c = 0; c < nc; c++ ) - L.elem(r,c) = lset[ (int)L.elem(r,c) ]; + // run through the look-up table again + for (int r = 0; r < nr; r++) + for (int c = 0; c < nc; c++) + L.elem (r, c) = lset [(int)L.elem (r, c)]; - octave_value_list rval; - rval(0) = L; - rval(1) = (double)nobj; - return rval; + rval (0) = L; + rval (1) = (double)nobj; + return rval; } +/* +%!assert(bwlabel([0 1 0; 0 0 0; 1 0 1]),[0 1 0; 0 0 0; 2 0 3]); +*/ + -static bool any_bad_argument( const octave_value_list& args ) -{ - if ( args.length() < 1 || args.length() > 2 ) { - error( "bwlabel: number of arguments - expecting bwlabel(bw) or bwlabel(bw,n)" ); - return true; - } - - if ( !args(0).is_matrix_type() ) { - error( "bwlabel: matrix expected for first argument" ); - return true; - } - - if ( args.length() == 2 ) { - if ( !args(1).is_real_scalar() ) { - error( "bwlabel: expecting real scalar for second argument" ); - return true; - } - int n = args(1).int_value(); - if ( n != 4 && n != 6 && n != 8 ) { - error( "bwlabel: in bwlabel(BW,n) n must be in {4,6,8}" ); - return true; - } - } - - return false; - -} - - -static int find( int set[], int x ) -{ - int r = x; - while ( set[r] != r ) - r = set[r]; - return r; -} -