00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <cstring>
00011
00012 #include "ros/ros.h"
00013
00014 #include "ConnectedComponentAnalyzer.h"
00015 #include "ConnectedComponent.h"
00016 #include "ipcccf.h"
00017
00018 #include "Architecture/Singleton/Clock.h"
00019
00020 #define THIS ConnectedComponentAnalyzer
00021
00022 THIS::THIS()
00023 : m_LabelImage( 0 ), m_Width( 0 ), m_Height( 0 )
00024 {
00025 }
00026
00027 THIS::~THIS()
00028 {
00029 if ( m_LabelImage )
00030 {
00031 delete[] m_LabelImage;
00032 m_LabelImage = 0;
00033 }
00034 }
00035
00036 void THIS::isolateLargestSegment(unsigned char* binImage, unsigned width, unsigned height)
00037 {
00038
00039 unsigned *labelImage = new unsigned[ height * width ];
00040 ipcConnectedComponentFilter< unsigned char, unsigned > ccf8bit;
00041 ccf8bit.init( width, height );
00042
00043 unsigned maxLabel = ccf8bit.execute( binImage, labelImage );
00044
00045 std::vector<unsigned> numPixels;
00046 numPixels.assign( maxLabel+1, 0 );
00047
00048 unsigned offset=0;
00049 unsigned y=0;
00050 unsigned x=0;
00051 unsigned realMaxLabel=0;
00052
00053
00054 while(y<height) {
00055 while(x<width)
00056 {
00057 numPixels[ labelImage[offset] ]++;
00058 if (labelImage[offset] > realMaxLabel) { realMaxLabel=labelImage[offset]; }
00059 offset++;
00060 x++;
00061 }
00062 x=0;
00063 y++;
00064 }
00065
00066 unsigned maxNumPixels=0;
00067 unsigned largestSegment=0;
00068
00069
00070 for (unsigned i=1;i<=realMaxLabel;i++)
00071 {
00072 if( numPixels[i] > maxNumPixels )
00073 {
00074 maxNumPixels = numPixels[i];
00075 largestSegment = i;
00076 }
00077 }
00078
00079
00080 for (unsigned i=0; i<width*height; i++)
00081 {
00082 if ( labelImage[i] != largestSegment )
00083 {
00084 binImage[i]=0;
00085 }
00086 }
00087 delete[] labelImage;
00088 }
00089
00090
00091 std::vector< ConnectedComponent > THIS::segment(unsigned char* binImage, unsigned width, unsigned height, unsigned minSegmentSize, float minOccupiedArea, unsigned expandSegmentSize)
00092 {
00093 if ( m_LabelImage )
00094 {
00095 delete[] m_LabelImage;
00096 m_LabelImage = 0;
00097 }
00098 m_LabelImage = new unsigned[ height * width ];
00099 m_Width = width;
00100 m_Height = height;
00101
00102 ipcConnectedComponentFilter< unsigned char, unsigned > ccf8bit;
00103 ccf8bit.init( width, height );
00104 unsigned max_label = ccf8bit.execute( binImage, m_LabelImage );
00105
00106 #ifdef CLOCK_OUTPUT
00107 cout << "ccf8bit: " << Clock::getInstance()->getTimestamp()-time << " ms" << endl;
00108 cout << "max_label: " << max_label << endl;
00109 time=Clock::getInstance()->getTimestamp();
00110 #endif
00111
00112 return extractComponents( max_label, minSegmentSize, minOccupiedArea, expandSegmentSize );
00113 }
00114
00115 std::vector< ConnectedComponent > THIS::segment(const float* floatImage, unsigned width, unsigned height, float maxDistance,
00116 unsigned minSegmentSize, float minOccupiedArea, unsigned expandSegmentSize)
00117 {
00118 if ( m_LabelImage )
00119 {
00120 delete[] m_LabelImage;
00121 m_LabelImage = 0;
00122 }
00123 m_LabelImage = new unsigned[ height * width ];
00124 m_Width = width;
00125 m_Height = height;
00126
00127 ipcConnectedComponentFilterSim< float, unsigned, IntensitySimilarity<float> > ccf8bit;
00128 ccf8bit.init( width, height );
00129 unsigned max_label = ccf8bit.execute( floatImage, m_LabelImage, IntensitySimilarity<float>( maxDistance ));
00130
00131 #ifdef CLOCK_OUTPUT
00132 cout << "ccf8bit: " << Clock::getInstance()->getTimestamp()-time << " ms" << endl;
00133 cout << "max_label: " << max_label << endl;
00134 time=Clock::getInstance()->getTimestamp();
00135 #endif
00136
00137 return extractComponents( max_label, minSegmentSize, minOccupiedArea, expandSegmentSize );
00138 }
00139
00140 std::vector< ConnectedComponent > THIS::segment(const float* floatImage, const unsigned char* mask, unsigned width, unsigned height,
00141 float maxDistance, unsigned minSegmentSize, float minOccupiedArea,
00142 unsigned expandSegmentSize, int maxr)
00143 {
00144 if ( m_LabelImage )
00145 {
00146 delete[] m_LabelImage;
00147 m_LabelImage = 0;
00148 }
00149 m_LabelImage = new unsigned[ height * width ];
00150 m_Width = width;
00151 m_Height = height;
00152
00153 ipcConnectedComponentFilterSim< float, unsigned, IntensitySimilarity<float>, MaskVadility<unsigned char, float> > ccf8bit;
00154 ccf8bit.init( width, height );
00155 unsigned max_label = ccf8bit.execute( floatImage, m_LabelImage, IntensitySimilarity<float>( maxDistance ),
00156 MaskVadility<unsigned char, float>( 0, mask, width ), maxr );
00157
00158 #ifdef CLOCK_OUTPUT
00159 cout << "ccf8bit: " << Clock::getInstance()->getTimestamp()-time << " ms" << endl;
00160 cout << "max_label: " << max_label << endl;
00161 time=Clock::getInstance()->getTimestamp();
00162 #endif
00163
00164 return extractComponents( max_label, minSegmentSize, minOccupiedArea, expandSegmentSize );
00165 }
00166
00167 std::vector< ConnectedComponent > THIS::segmentByLimit( cv::Mat* pi_img, double pi_limit) {
00168 std::vector<ConnectedComponent> componentVec;
00169
00170 unsigned width = pi_img->cols;
00171 unsigned height = pi_img->rows;
00172
00173
00174 unsigned char* binImage = new unsigned char[ height * width ];
00175 for ( unsigned j = 0; j < height; j++ ) {
00176 for ( unsigned i = 0; i < width; i++ ) {
00177 binImage [j*width+i] = ( pi_img->at<unsigned char>(i, j) >= pi_limit ? 255 : 0 );
00178 }
00179 }
00180
00181 unsigned offset=0;
00182 unsigned char* bin2Image = new unsigned char[ height * width ];
00183 memcpy( bin2Image, binImage, height * width );
00184
00185
00186 for ( unsigned j = 1; j < height-1; j++ ) {
00187 for ( unsigned i = 1; i < width-1; i++ ) {
00188 offset=j*width+i;
00189 bin2Image [offset] = (
00190 binImage [ offset ] |
00191 binImage [ offset-width-1 ] | binImage [ offset-width+1 ] |
00192 binImage [ offset+width-1 ] | binImage [ offset+width+1 ] ) == 255 ? 255 : 0;
00193 }
00194 }
00195
00196
00197 componentVec = segment(bin2Image,pi_img->cols,pi_img->rows);
00198
00199 delete[] binImage;
00200 delete[] bin2Image;
00201
00202 return componentVec;
00203 }
00204
00205 std::vector< ConnectedComponent > THIS::extractComponents( unsigned max_label, unsigned minSegmentSize,
00206 float minOccupiedArea, unsigned expandSegmentSize )
00207 {
00208 std::vector<ConnectedComponent> componentVec;
00209 unsigned* labelImage = m_LabelImage;
00210 unsigned width = m_Width;
00211 unsigned height = m_Height;
00212
00213
00214 unsigned* minX=new unsigned[max_label+1];
00215 unsigned* maxX=new unsigned[max_label+1];
00216 unsigned* minY=new unsigned[max_label+1];
00217 unsigned* maxY=new unsigned[max_label+1];
00218 unsigned* size=new unsigned[max_label+1];
00219 unsigned* sumX=new unsigned[max_label+1];
00220 unsigned* sumY=new unsigned[max_label+1];
00221
00222 for (unsigned i=0;i<max_label+1;i++) {
00223 minX[i]=width-1;
00224 maxX[i]=0;
00225 minY[i]=height-1;
00226 maxY[i]=0;
00227 size[i]=0;
00228 sumX[i]=0;
00229 sumY[i]=0;
00230 }
00231
00232 unsigned offset=0;
00233 unsigned currentLabel;
00234 unsigned y=0;
00235 unsigned x=0;
00236 unsigned realMaxLabel=0;
00237 unsigned currentStartX=0;
00238 unsigned currentSegmentSize=0;
00239
00240
00241 while(y<height) {
00242 while(x<width)
00243 {
00244
00245 if (labelImage[offset]) {
00246 currentLabel=labelImage[offset];
00247 currentStartX=x;
00248 if (currentLabel > realMaxLabel) { realMaxLabel=currentLabel; }
00249 if (x<minX[currentLabel]) { minX[currentLabel]=x; }
00250 if (y<minY[currentLabel]) { minY[currentLabel]=y; }
00251 if (y>maxY[currentLabel]) { maxY[currentLabel]=y; }
00252
00253 do {
00254 x++;
00255 offset++;
00256 } while ( (x<width) && (labelImage[offset]==currentLabel) );
00257 currentSegmentSize=x-currentStartX;
00258 size[currentLabel]+=currentSegmentSize;
00259 sumY[currentLabel]+=currentSegmentSize*y;
00260 sumX[currentLabel]+=(x+currentStartX)*currentSegmentSize/2;
00261 x--;
00262 offset--;
00263 if (x>maxX[currentLabel]) { maxX[currentLabel]=x; }
00264 }
00265 offset++;
00266 x++;
00267 }
00268 x=0;
00269 y++;
00270 }
00271
00272
00273 for (unsigned i=1;i<=realMaxLabel;i++) {
00274 if (minX[i]<expandSegmentSize) { minX[i]=0; }
00275 else { minX[i]-=expandSegmentSize; }
00276 if (minY[i]<expandSegmentSize) { minY[i]=0; }
00277 else { minY[i]-=expandSegmentSize; }
00278 if (maxX[i]>width-expandSegmentSize-1) { maxX[i]=width-1; }
00279 else { maxX[i]+=expandSegmentSize; }
00280 if (maxY[i]>height-expandSegmentSize-1) { maxY[i]=height-1; }
00281 else { maxY[i]+=expandSegmentSize; }
00282 }
00283
00284 bool foundBoxes=false;
00285 std::ostringstream stream;
00286 stream << "Found bounding boxes:" << std::endl;
00287
00288 for (unsigned i=1;i<realMaxLabel+1;i++)
00289 {
00290 float boxPixels=(maxX[i]-minX[i]-2*expandSegmentSize)*(maxY[i]-minY[i]-2*expandSegmentSize);
00291 float occupiedArea=float(size[i]) / boxPixels;
00292
00293 if ( size[i]>minSegmentSize && occupiedArea>minOccupiedArea ) {
00294 foundBoxes=true;
00295 double cogX = double(sumX[i]) / double(size[i]);
00296 double cogY = double(sumY[i]) / double(size[i]);
00297 ConnectedComponent comp( i, minX[i], minY[i], maxX[i], maxY[i], cogX, cogY, size[i] );
00298 componentVec.push_back( comp );
00299 stream << i << ": " << minX[i] <<"-"<< maxX[i] <<" "<< minY[i] <<"-"<< maxY[i]
00300 << " center: " << int(cogX) << "," << int(cogY)
00301 << " width: " << (maxX[i]-minX[i]) << " height: " << (maxY[i]-minY[i])
00302 << " width x height: " << (maxX[i]-minX[i])*(maxY[i]-minY[i])
00303 << " occupied (%): " << int(occupiedArea*100.0) << std::endl;
00304 }
00305 }
00306
00307 if (foundBoxes) {
00308 ROS_DEBUG_STREAM( stream.str() );
00309 }
00310
00311 delete[] minX;
00312 delete[] maxX;
00313 delete[] minY;
00314 delete[] maxY;
00315 delete[] size;
00316 delete[] sumX;
00317 delete[] sumY;
00318
00319 #ifdef CLOCK_OUTPUT
00320 cout << "extract segments: " << Clock::getInstance()->getTimestamp()-time << " ms" << endl;
00321 time=Clock::getInstance()->getTimestamp();
00322 #endif
00323
00324 return componentVec;
00325 }