ConnectedComponentAnalyzer.cpp
Go to the documentation of this file.
00001 /*******************************************************************************
00002  *  ConnectedComponentAnalyzer.cpp
00003  *
00004  *  (C) 2007 AG Aktives Sehen <agas@uni-koblenz.de>
00005  *           Universitaet Koblenz-Landau
00006  *
00007  *  Additional information:  
00008  *  $Id: ConnectedComponentAnalyzer.cpp 44313 2011-04-06 22:46:28Z agas $ 
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   // Generate image with the connected components
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   //Extract segment sizes
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   //determine largest segment
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   //clear all segments except largest one
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   // binarize the image
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   // a simple erosion
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   //apply algorithm
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   //initialize variables
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   //Extract segments
00241   while(y<height) {
00242     while(x<width)
00243     {
00244       //start of line segment with label != 0 found in current line
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         //determine end of line segment
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   //expand & clip bounding boxes
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   //calculate centers & create ConnectedComponents
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) // TODO << " size: " << fixed << int(size[i])
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 }


or_libs
Author(s): Viktor Seib
autogenerated on Tue Jan 7 2014 11:24:03