OpeCV的连通区域标记-bwlabel方法实现

类似于matlab中的bwlabel标记连通区域的c++版本实现,基于opencv,如下:

////////

////bwlabel.cpp

#include "cv.h" #include "highgui.h" #define NO_OBJECT 0 #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #define ELEM(img, r, c) (CV_IMAGE_ELEM(img, unsigned char, r, c)) #define ONETWO(L, r, c, col) (L[(r) * (col) + c]) int find( int set[], int x ) { int r = x; while ( set[r] != r ) r = set[r]; return r; } /* labeling scheme +-+-+-+ |D|C|E| +-+-+-+ |B|A| | +-+-+-+ | | | | +-+-+-+ A is the center pixel of a neighborhood. In the 3 versions of connectedness: 4: A connects to B and C 6: A connects to B, C, and D 8: A connects to B, C, D, and E */ ///////////////////////////// //by yysdsyl // //input:img -- gray image // n -- n connectedness // labels -- label of each pixel, labels[row * col] //output: number of connected regions // // //email:[email protected] int bwlabel(IplImage* img, int n, int* labels) { if(n != 4 && n != 8) n = 4; int nr = img->height; int nc = img->width; int total = nr * nc; // results memset(labels, 0, total * sizeof(int)); int nobj = 0; // number of objects found in image // other variables int* lset = new int[total]; // label table memset(lset, 0, total * sizeof(int)); int ntable = 0; for( int r = 0; r < nr; r++ ) { for( int c = 0; c < nc; c++ ) { if ( ELEM(img, 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, ONETWO(labels, r, c - 1, nc) ); if ( r == 0 ) C = 0; else C = find( lset, ONETWO(labels, r - 1, c, nc) ); if ( r == 0 || c == 0 ) D = 0; else D = find( lset, ONETWO(labels, r - 1, c - 1, nc) ); if ( r == 0 || c == nc - 1 ) E = 0; else E = find( lset, ONETWO(labels, r - 1, c + 1, nc) ); if ( n == 4 ) { // apply 4 connectedness if ( B && C ) { // B and C are labeled if ( B == C ) ONETWO(labels, r, c, nc) = B; else { lset[C] = B; ONETWO(labels, r, c, nc) = B; } } else if ( B ) // B is object but C is not ONETWO(labels, r, c, nc) = B; else if ( C ) // C is object but B is not ONETWO(labels, r, c, nc) = C; else { // B, C, D not object - new object // label and put into table ntable++; ONETWO(labels, r, c, nc) = lset[ ntable ] = ntable; } } else if ( n == 6 ) { // apply 6 connected ness if ( D ) // D object, copy label and move on ONETWO(labels, r, c, nc) = D; else if ( B && C ) { // B and C are labeled if ( B == C ) ONETWO(labels, r, c, nc) = B; else { int tlabel = MIN(B,C); lset[B] = tlabel; lset[C] = tlabel; ONETWO(labels, r, c, nc) = tlabel; } } else if ( B ) // B is object but C is not ONETWO(labels, r, c, nc) = B; else if ( C ) // C is object but B is not ONETWO(labels, r, c, nc) = C; else { // B, C, D not object - new object // label and put into table ntable++; ONETWO(labels, r, c, nc) = lset[ ntable ] = ntable; } } 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; ONETWO(labels, r, c, nc) = 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++; ONETWO(labels, r, c, nc) = lset[ ntable ] = ntable; } } } else { ONETWO(labels, r, c, nc) = 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 ); // run image through the look-up table for( int r = 0; r < nr; r++ ) for( int c = 0; c < nc; c++ ) ONETWO(labels, r, c, nc) = lset[ ONETWO(labels, r, c, nc) ]; // 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[ ONETWO(labels, r, c, nc) ]++; // 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++ ) ONETWO(labels, r, c, nc) = lset[ ONETWO(labels, r, c, nc) ]; // delete[] lset; return nobj; }

http://blog.csdn.net/yysdsyl/article/details/5343075

你可能感兴趣的:(OpeCV的连通区域标记-bwlabel方法实现)