00001 
00060 #ifndef __IMPL_POLYGON_EXTRACTION__
00061 #define __IMPL_POLYGON_EXTRACTION__
00062 
00063 #include <cstring>
00064 #include <iostream>
00065 #include <cob_3d_segmentation/polygon_extraction/polygon_extraction.h>
00066 #include <cob_3d_segmentation/polygon_extraction/impl/poly2d.hpp>
00067 #include <cob_3d_segmentation/polygon_extraction/polygon_types.h>
00068 
00069 #include <cstdio>
00070 
00071 cob_3d_segmentation::PolygonExtraction::PolygonExtraction()
00072  : ch_(NULL),ch_size_(0)
00073  , outline_check_(NULL)
00074  , outline_check_size_(0)
00075 {
00076   Contour2D::generateSpline2D();
00077 }
00078 
00079 
00080 template <typename TPoint>
00081 int cob_3d_segmentation::PolygonExtraction::getPos(int *ch, const int xx, const int yy, const int w, const int h) {
00082   int p = 0;
00083   
00084   for(int x = -1; x <= 1; x++) {
00085     for(int y = -1; y <= 1; y++) {
00086       if( xx + x >= 0 && yy + y >= 0 && xx + x < w && yy + y < h && (x || y) && ch[xx + x + (yy + y ) * w] > 0)
00087       {
00088         p |= (1 << Contour2D::SplineMap[(y + 1) * 3 + x + 1]);
00089       }
00090     }
00091   }
00092   return p;
00093 }
00094 
00095 template<typename TPoint, typename TPolygon>
00096 void cob_3d_segmentation::PolygonExtraction::outline(const int w, const int h, std::vector<TPoint> out, TPolygon &poly)
00097 {
00098   
00099   std::sort(out.begin(), out.end());
00100   
00101   if(ch_size_ < w*h)
00102   {
00103     delete [] ch_;
00104     ch_ = new int[w*h];
00105     ch_size_=w*h;
00106     memset(ch_,0,sizeof(int)*ch_size_);
00107   }
00108 
00109   
00110   for(size_t j=0; j<out.size(); j++) {
00111     ch_[ out[j].x + out[j].y * w ] = 1;
00112   }
00113 
00114   
00115 
00116 
00117 
00118 
00119 
00120 
00121   
00122   
00123   for(int n = 0; n < (int)out.size(); n++)
00124   
00125   {
00126     
00127     
00128     
00129 
00130 
00131     int x = out[n].x;
00132     int y = out[n].y;
00133     if(ch_[ x + y * w ] < 1) continue;
00134     int bf = 8; 
00135     int v = 0;
00136     int start_x = x, start_y = y;
00137 
00138     poly.addPolygon();
00139     poly.addPoint(x,y);
00140     
00141     std::stack<std::pair<int,Contour2D::spline2D> > forked_states;
00142     std::stack<typename std::vector<TPoint>::size_type> forked_points;
00143     while(1)
00144     {
00145       
00146       if(x < 0 || y < 0 || x >= w || y >= h || ch_[ x + y * w ] < 1)
00147       {
00148         break;
00149       }
00150 
00151       int ch_old = ch_[ x+y*w ];
00152       
00153       ch_[ x+y*w ] = 0;
00154 
00155       int p = getPos<TPoint>(ch_, x, y, w, h);
00156 
00157       if(p == 0 || (!Contour2D::g_Splines[bf][p].x && !Contour2D::g_Splines[bf][p].y))
00158       {
00159         
00160         if (forked_states.size() == 0 || (std::abs(x-start_x)+std::abs(y-start_y)) <= 4) { break; }
00161         
00162         
00163         v = forked_states.top().second.v;
00164         x = forked_states.top().second.x;
00165         y = forked_states.top().second.y;
00166         
00167         bf = forked_states.top().second.bf;
00168         ch_ [ x+y*w ] = forked_states.top().first;
00169         forked_states.pop();
00170         
00171 
00172 
00173 
00174 
00175         poly.removeLastPoints(forked_points.top());
00176         
00177 
00178 
00179 
00180         forked_points.pop();
00181         continue;
00182       }
00183       
00184       if (hasMultiplePositions((unsigned int)p))
00185       {
00186         Contour2D::spline2D s = {v, x, y, bf};
00187         forked_states.push(std::pair<int,Contour2D::spline2D>(ch_old, s));
00188         forked_points.push(0);
00189       }
00190 
00191       v += v + Contour2D::g_Splines[bf][p].v;
00192       x += Contour2D::g_Splines[bf][p].x;
00193       y += Contour2D::g_Splines[bf][p].y;
00194       bf = Contour2D::g_Splines[bf][p].bf;
00195       
00196 
00197       if(std::abs(v) > 5)
00198       {
00199         v = 0;
00200         ++(forked_points.top());
00201         poly.addPoint(x,y);
00202         
00203 
00204 
00205 
00206       }
00207     }
00208 
00209     
00210     if(poly.polys_.back().size() < 4 || (std::abs(x - start_x) + std::abs(y - start_y)) > 4 )
00211     {
00212       poly.removePolygon();
00213       
00214       break;
00215     }
00216 
00217   }
00218 
00219   for(size_t j = 0; j < out.size(); j++) {
00220     ch_[ out[j].x + out[j].y * w ] = 0;
00221   }
00222 
00223 }
00224 
00225 void cob_3d_segmentation::PolygonExtraction::ppm(const char *fn, const int w, const int h, const int *ch) {
00226   
00227   FILE *fp = fopen(fn,"w");
00228 
00229   char buffer[128];
00230   sprintf(buffer,"P3\n%d %d\n255\n",h,w);
00231   fputs(buffer,fp);
00232 
00233   for(int x=0; x<w; x++) {
00234     for(int y=0; y<h; y++) {
00235       int v=0;
00236       if(ch[(x+w*y)])
00237         v=255;
00238 
00239       if(ch[(x+w*y)]<-1) {
00240         sprintf(buffer,"%d %d %d  ",0,255,0);
00241       }
00242       else if(ch[(x+w*y)]<0) {
00243         sprintf(buffer,"%d %d %d  ",255,0,0);
00244       }
00245       else
00246         sprintf(buffer,"%d %d %d  ",v,v,v);
00247       fputs(buffer,fp);
00248     }
00249   }
00250   fclose(fp);
00251 }
00252 
00253 
00254 
00255 template void cob_3d_segmentation::PolygonExtraction::outline<cob_3d_segmentation::PolygonPoint, cob_3d_segmentation::PolygonContours<cob_3d_segmentation::PolygonPoint> >(const int w, const int h, std::vector<cob_3d_segmentation::PolygonPoint> out, cob_3d_segmentation::PolygonContours<cob_3d_segmentation::PolygonPoint> &poly);
00256 
00257 template int cob_3d_segmentation::PolygonExtraction::getPos<cob_3d_segmentation::PolygonPoint>(int *ch, const int xx, const int yy, const int w, const int h);
00258 
00259 #endif