/** * @file LFSegContour.cpp * @brief Local Features are connected components of a arbitrary segmentation * @author Erik Rodner * @date 01/21/2008 */ #include #ifdef NICE_USELIB_ICE #include #include #include #include "vislearning/features/localfeatures/LFSegContour.h" #include "vislearning/segmentation/SegLocal.h" #include #include using namespace OBJREC; using namespace std; using namespace NICE; LFSegContour::LFSegContour( const Config *conf, FeatureFactory *_fc ) { segmentation = new SegLocal ( conf ); fourier_coefficients = conf->gI ( "LFSegContour", "fourier_coefficients", 50 ); display_segmentation = conf->gB ( "LFSegContour", "display_segmentation", false); xsize = (size_t)conf->gI("FCGreyValues", "xsize", 11 ); ysize = (size_t)conf->gI("FCGreyValues", "ysize", 11 ); minArea = (size_t)conf->gI("LFSegContour", "min_area", 25 ); std::string descriptor_method_s = conf->gS ("LFSegContour", "descriptor_method" ); fc = _fc; if ( descriptor_method_s == "fourier" ) descriptor_method = DESCRIPTOR_METHOD_FOURIER; else if ( descriptor_method_s == "hu" ) descriptor_method = DESCRIPTOR_METHOD_HU; else if ( descriptor_method_s == "patch" ) { descriptor_method = DESCRIPTOR_METHOD_PATCH; if ( fc == NULL ) { fprintf (stderr, "LFSegContour: please specify a patch feature factory !\n"); exit(-1); } } else { fprintf (stderr, "LFSegContour: descriptor method not yet implemented !\n"); exit(-1); } } LFSegContour::~LFSegContour() { delete segmentation; } int LFSegContour::getDescSize () const { if ( descriptor_method == DESCRIPTOR_METHOD_FOURIER ) return 2*fourier_coefficients - 2; else if ( descriptor_method == DESCRIPTOR_METHOD_HU ) return 7; else { return xsize*ysize; } } int LFSegContour::calcContourDescriptorFourier ( const ice::Contur & c, NICE::Vector & f ) const { if ( (size_t)c.Number() < fourier_coefficients/2 ) return -1; ice::PointList pl1, pl2; double *r_feature = new double[fourier_coefficients]; double *i_feature = new double[fourier_coefficients]; double phi_1 = 0; pl1 = ice::ConturPointList (c, 1); pl2 = ice::NewPointList (pl1->lng); ice::FourierD (pl1->xptr, pl1->yptr, pl1->lng, NORMAL, pl2->xptr, pl2->yptr); if (fabs (pl2->xptr[1]) < 1.0e-12) { if (pl2->yptr[1] > 0) phi_1 = PI / 2.0; if (pl2->yptr[1] < 0) phi_1 = -PI / 2.0; if (fabs (pl2->yptr[1]) < 1.0e-12) { fprintf (stderr, "LFSegContour: numerical problems !!\n"); exit(-1); } } else { phi_1 = atan (pl2->yptr[1] / pl2->xptr[1]); } if (pl2->xptr[1] < 0 && pl2->yptr[1] < 0) phi_1 += M_PI; if (pl2->xptr[1] < 0 && pl2->yptr[1] > 0) phi_1 += M_PI; // die ersten 2*fd-2 Merkmale berechnen for (size_t i = 0; i < fourier_coefficients / 2; ++i) { double sinphi = sin (double (i + 1) * phi_1); double cosphi = cos (double (i + 1) * phi_1); r_feature[i] = pl2->xptr[i + 1] * cosphi + pl2->yptr[i + 1] * sinphi; i_feature[i] = pl2->yptr[i + 1] * cosphi - pl2->xptr[i + 1] * sinphi; } for (size_t i = fourier_coefficients / 2; i < fourier_coefficients; ++i) { double cosphi = cos (double (-i - 1 + fourier_coefficients / 2) * phi_1); double sinphi = sin (double (-i - 1 + fourier_coefficients / 2) * phi_1); r_feature[i] = pl2->xptr[pl2->lng - i - 1 + fourier_coefficients / 2] * cosphi + pl2->yptr[pl2->lng - i - 1 + fourier_coefficients / 2] * sinphi; i_feature[i] = pl2->yptr[pl2->lng - i - 1 + fourier_coefficients / 2] * cosphi - pl2->xptr[pl2->lng - i - 1 + fourier_coefficients / 2] * sinphi; } f.resize( 2*fourier_coefficients - 2 ); for (size_t i = 0; i < fourier_coefficients - 1; ++i) { f[i] = r_feature[i + 1] / sqrt (r_feature[0] * r_feature[0] + i_feature[0] * i_feature[0]); } for (size_t i = fourier_coefficients - 1; i < 2 * fourier_coefficients - 2; ++i) { f[i] = i_feature[i - fourier_coefficients + 2] / sqrt (r_feature[0] * r_feature[0] + i_feature[0] * i_feature[0]); } // aufräumen ice::FreePointList (pl1); ice::FreePointList (pl2); delete [] r_feature; delete [] i_feature; return 0; } int LFSegContour::calcContourDescriptorHU ( const ice::Contur & c, // refactor-nice.pl: check this substitution // old: Vector & f ) const NICE::Vector & f ) const { ice::Moments m ( c ); f = NICE::makeEVector ( m.AffineHuInvariants() ); return 0; } int LFSegContour::calcContourDescriptorPatch ( const NICE::Image & img, const ice::Contur & c, NICE::Vector & f ) const { int xi, yi, xa, ya; c.GetRect( xi, yi, xa, ya ); Rect r ( xi, yi, xa-xi+1, ya-yi+1 ); const NICE::Image *img_w = img.createSubImage ( r ); fc->convert ( *img_w, f ); delete img_w; return 0; } // refactor-nice.pl: check this substitution // old: int LFSegContour::extractFeatures ( const Image & img, VVector & features, int LFSegContour::extractFeatures ( const NICE::Image & img, VVector & features, VVector & positions ) const { std::vector contours; segmentation->getContours ( img, contours ); NICE::Vector x; int r; ice::Image mark; if ( display_segmentation ) { mark = ice::NewImg ( img.width(), img.height(), 30 ); ice::ClearImg(mark); } for ( vector::const_iterator i = contours.begin(); i != contours.end(); i++ ) { if ( display_segmentation ) ice::MarkContur ( *i, 1, mark ); int xi, yi, xa, ya; i->GetRect(xi, yi, xa, ya); if ( (xa-xi)*(ya-yi) < minArea ) continue; if ( descriptor_method == DESCRIPTOR_METHOD_FOURIER ) r = calcContourDescriptorFourier ( *i, x ); else if ( descriptor_method == DESCRIPTOR_METHOD_HU ) r = calcContourDescriptorHU ( *i, x ); else r = calcContourDescriptorPatch ( img, *i, x ); if ( r >= 0 ) { features.push_back ( x ); NICE::Vector p ( 4 ); p[0] = xi; p[1] = yi; p[2] = xa-xi; p[3] = ya-yi; positions.push_back ( p ); } } if ( display_segmentation ) { #ifndef NOVISUAL NICE::Image *mark_nice = NICE::createGrayImage ( mark ); showImageOverlay(img, *mark_nice); delete mark_nice; #else fprintf (stderr, "LFSegContour::extractFeatures: visualization disabled !\n"); #endif } return positions.size(); } void LFSegContour::visualizeFeatures ( NICE::Image & mark, const VVector & positions, size_t color ) const { for ( size_t i = 0 ; i < positions.size() ; i++ ) { const NICE::Vector & pos = positions[i]; int x = (int)pos[0]; int y = (int)pos[1]; int w = (int)pos[2]; int h = (int)pos[3]; RectangleT r ( Coord(x,y), Coord(x+w, y+w)); mark.draw ( r, color ); } } #endif