$search
00001 /* 00002 * features.cpp 00003 * online_patch 00004 * 00005 * Created by Victor Eruhimov on 4/23/09. 00006 * Copyright 2009 Argus Corp. All rights reserved. 00007 * 00008 */ 00009 00010 #include "outlet_pose_estimation/detail/features.h" 00011 #include "outlet_pose_estimation/detail/outlet_model.h" 00012 #include <highgui.h> 00013 00014 using namespace std; 00015 00016 void GetSURFFeatures(IplImage* src, vector<feature_t>& features) 00017 { 00018 CvMemStorage* storage = cvCreateMemStorage(); 00019 CvSeq* surf_points = 0; 00020 cvExtractSURF(src, 0, &surf_points, 0, storage, cvSURFParams(512)); 00021 00022 features.clear(); 00023 for(int i = 0; i < surf_points->total; i++) 00024 { 00025 CvSURFPoint* point = (CvSURFPoint*)cvGetSeqElem(surf_points, i); 00026 CvPoint center = cvPoint(point->pt.x, point->pt.y); 00027 features.push_back(feature_t(center, (float)point->size)); 00028 } 00029 00030 cvReleaseMemStorage(&storage); 00031 } 00032 00033 void GetStarFeatures(IplImage* src, vector<feature_t>& features) 00034 { 00035 CvMemStorage* storage = cvCreateMemStorage(); 00036 CvSeq* star_points = cvGetStarKeypoints(src, storage, cvStarDetectorParams(45)); 00037 00038 features.clear(); 00039 for(int i = 0; i < star_points->total; i++) 00040 { 00041 CvStarKeypoint* keypoint = (CvStarKeypoint*)cvGetSeqElem(star_points, i); 00042 features.push_back(feature_t(keypoint->pt, (float)keypoint->size)); 00043 } 00044 00045 cvReleaseMemStorage(&storage); 00046 } 00047 00048 void GetHarrisFeatures(IplImage* src, vector<feature_t>& features) 00049 { 00050 IplImage* grey = src; 00051 if(src->nChannels > 1) 00052 { 00053 grey = cvCreateImage(cvSize(src->width, src->height), IPL_DEPTH_8U, 1); 00054 cvCvtColor(src, grey, CV_RGB2GRAY); 00055 } 00056 00057 00058 IplImage* eig_img = cvCreateImage(cvSize(src->width, src->height), IPL_DEPTH_32F, 1); 00059 IplImage* temp_img = cvCloneImage(eig_img); 00060 00061 int corner_count = 1024; 00062 CvPoint2D32f* corners = new CvPoint2D32f[corner_count]; 00063 cvGoodFeaturesToTrack(grey, eig_img, temp_img, corners, &corner_count, .5, 0);//, 0, 3, 1); 00064 00065 for(int i = 0; i < corner_count; i++) 00066 { 00067 features.push_back(feature_t(cvPoint(corners[i].x, corners[i].y), 1.0f)); 00068 } 00069 00070 if(src->nChannels > 1) 00071 { 00072 cvReleaseImage(&grey); 00073 } 00074 cvReleaseImage(&eig_img); 00075 cvReleaseImage(&temp_img); 00076 } 00077 00078 /*void GetHoleFeatures(IplImage* src, vector<feature_t>& features, float hole_contrast) 00079 { 00080 vector<outlet_feature_t> outlet_features; 00081 find_outlet_features_fast(src, outlet_features, hole_contrast, 0, 0); 00082 for(size_t i = 0; i < outlet_features.size(); i++) 00083 { 00084 features.push_back(feature_t(feature_center(outlet_features[i]), outlet_features[i].bbox.width)); 00085 } 00086 }*/ 00087 00088 void GetHoleFeatures(IplImage* src, vector<feature_t>& features, float hole_contrast) 00089 { 00090 vector<outlet_feature_t> outlet_features; 00091 find_outlet_features_fast(src, outlet_features, hole_contrast, 0, 0); 00092 for(size_t i = 0; i < outlet_features.size(); i++) 00093 { 00094 features.push_back(feature_t(feature_center(outlet_features[i]), outlet_features[i].bbox.width)); 00095 } 00096 } 00097 00098 void DrawFeatures(IplImage* img, const vector<feature_t>& features) 00099 { 00100 for(size_t i = 0; i < features.size(); i++) 00101 { 00102 cvCircle(img, features[i].pt, features[i].size, CV_RGB(255, 0, 0), 2); 00103 } 00104 } 00105 00106 void FilterFeatures(vector<feature_t>& features, float min_scale, float max_scale) 00107 { 00108 vector<feature_t> selected; 00109 for(size_t i = 0; i < features.size(); i++) 00110 { 00111 if(features[i].size >= min_scale && features[i].size <= max_scale) 00112 { 00113 selected.push_back(features[i]); 00114 } 00115 } 00116 00117 features = selected; 00118 } 00119 00120 void SelectNeighborFeatures(vector<feature_t>& features, const vector<feature_t>& voc) 00121 { 00122 const int max_dist = 10; 00123 vector<feature_t> filtered; 00124 for(int i = 0; i < (int)features.size(); i++) 00125 { 00126 for(int j = 0; j < (int)voc.size(); j++) 00127 { 00128 if(length(features[i].pt - voc[j].pt) < max_dist) 00129 { 00130 filtered.push_back(features[i]); 00131 } 00132 } 00133 } 00134 00135 features = filtered; 00136 } 00137 00138 int CalcFeatures(IplImage* image, vector<vector<feature_t> >& features, vector<IplImage*>& images) 00139 { 00140 size_t pyr_levels = features.size(); 00141 images.resize(pyr_levels); 00142 IplImage* image_features = cvCloneImage(image); 00143 00144 for(size_t i = 0; i < features.size(); i++) 00145 { 00146 images[i] = image_features; 00147 GetHoleFeatures(image_features, features[i]); 00148 IplImage* temp_image = cvCreateImage(cvSize(image_features->width/2, image_features->height/2), IPL_DEPTH_8U, 1); 00149 cvPyrDown(image_features, temp_image); 00150 image_features = temp_image; 00151 } 00152 cvReleaseImage(&image_features); 00153 00154 int feature_count = 0; 00155 00156 for(size_t i = 0; i < pyr_levels; i++) 00157 { 00158 feature_count += features[i].size(); 00159 } 00160 00161 cvReleaseImage(&image); 00162 00163 return feature_count; 00164 } 00165 00166 static const float template_gamma = 2.0f;//1.2f; 00167 int LoadFeatures(const char* filename, vector<vector<feature_t> >& features, vector<IplImage*>& images) 00168 { 00169 IplImage* image = loadImageRed(filename); 00170 ApplyGamma(image, template_gamma); 00171 00172 int feature_count = CalcFeatures(image, features, images); 00173 00174 return feature_count; 00175 } 00176 00177 IplImage* loadImageRed(const char* filename) 00178 { 00179 IplImage* temp = cvLoadImage(filename); 00180 IplImage* red = cvCreateImage(cvSize(temp->width, temp->height), IPL_DEPTH_8U, 1); 00181 cvSetImageCOI(temp, 3); 00182 cvCopy(temp, red); 00183 cvReleaseImage(&temp); 00184 00185 #if defined(_SCALE_IMAGE_2) 00186 IplImage* red2 = cvCreateImage(cvSize(red->width/2, red->height/2), IPL_DEPTH_8U, 1); 00187 cvResize(red, red2); 00188 cvReleaseImage(&red); 00189 red = red2; 00190 #endif //_SCALE_IMAGE_2 00191 00192 return red; 00193 } 00194 00195 void ReleaseImageVector(vector<IplImage*>& images) 00196 { 00197 for(size_t i = 0; i < images.size(); i++) 00198 { 00199 cvReleaseImage(&images[i]); 00200 } 00201 } 00202 00203 void LoadTrainingFeatures(CvOneWayDescriptorObject& descriptors, const char* train_image_filename_object, const char* train_image_filename_background) 00204 { 00205 #if defined(_RED) 00206 IplImage* train_image_object = loadImageRed(train_image_filename_object); 00207 IplImage* train_image_background = loadImageRed(train_image_filename_background); 00208 #else 00209 IplImage* train_image_object = cvLoadImage(train_image_filename_object, CV_LOAD_IMAGE_GRAYSCALE); 00210 IplImage* train_image_background = cvLoadImage(train_image_filename_background, CV_LOAD_IMAGE_GRAYSCALE); 00211 #endif 00212 00213 #if 1 00214 ApplyGamma(train_image_object, template_gamma); 00215 // ApplyGamma(train_image_background); 00216 #endif 00217 00218 #if 0 00219 IplImage* train_image_object_up = cvCreateImage(cvSize(train_image_object->width, train_image_object->height), IPL_DEPTH_8U, train_image_object->nChannels); 00220 cvPyrUp(train_image_object, train_image_object_up); 00221 #endif 00222 00223 vector<vector<feature_t> > object_features; 00224 object_features.resize(descriptors.GetPyrLevels()); 00225 vector<IplImage*> images; 00226 int object_feature_count = LoadFeatures(train_image_filename_object, object_features, images); 00227 00228 #if 0 00229 int max_object_features = 15; 00230 object_feature_count = 0; 00231 for (int i=0;i<(int)object_features.size();i++) 00232 { 00233 while ((int)object_features[i].size() > max_object_features) 00234 { 00235 object_features[i].pop_back(); 00236 } 00237 object_feature_count+=(int)object_features[i].size(); 00238 } 00239 #endif 00240 00241 vector<vector<feature_t> > background_features; 00242 vector<IplImage*> background_images; 00243 background_features.resize(1); 00244 int background_feature_count = LoadFeatures(train_image_filename_background, background_features, background_images); 00245 00246 #if 1 00247 //printf("Background features count: %d\n",background_feature_count); 00248 int max_background_features = 20; 00249 background_feature_count = 0; 00250 for (int i=0;i<(int)background_features.size();i++) 00251 { 00252 while ((int)background_features[i].size() > max_background_features) 00253 { 00254 background_features[i].pop_back(); 00255 } 00256 background_feature_count+=(int)background_features[i].size(); 00257 } 00258 #endif 00259 00260 int train_feature_count = object_feature_count + background_feature_count; 00261 // printf("Found %d train points...\n", train_feature_count); 00262 00263 descriptors.Allocate(train_feature_count, object_feature_count); 00264 00265 int descriptor_count = 0; 00266 for(int i = 0; i < descriptors.GetPyrLevels(); i++) 00267 { 00268 char feature_label[1024]; 00269 sprintf(feature_label, "%s_%d", train_image_filename_object, i); 00270 IplImage* img = images[i]; 00271 descriptors.InitializeObjectDescriptors(img, object_features[i], feature_label, descriptor_count, (float)(1<<i)); 00272 descriptor_count += object_features[i].size(); 00273 } 00274 00275 descriptors.InitializeObjectDescriptors(background_images[0], background_features[0], 00276 train_image_filename_background, object_feature_count, 1.0f, 1); 00277 #if defined(_KDTREE) 00278 descriptors.ConvertDescriptorsArrayToTree(); 00279 #endif 00280 cvReleaseImage(&train_image_object); 00281 cvReleaseImage(&train_image_background); 00282 00283 ReleaseImageVector(images); 00284 ReleaseImageVector(background_images); 00285 } 00286 00287 void ScaleFeatures(const vector<feature_t>& src, vector<feature_t>& dst, float scale) 00288 { 00289 dst.resize(src.size()); 00290 for(size_t i = 0; i < src.size(); i++) 00291 { 00292 dst[i] = feature_t(cvPoint(src[i].pt.x*scale, src[i].pt.y*scale), src[i].size, src[i].class_id); 00293 } 00294 } 00295 00296 void ApplyGamma(IplImage* img, float gamma) 00297 { 00298 IplImage* flt0 = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, 1); 00299 IplImage* flt = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, 1); 00300 IplImage* u8 = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1); 00301 00302 for(int i = 1; i <= img->nChannels; i++) 00303 { 00304 cvSetImageCOI(img, i); 00305 cvCopy(img, u8); 00306 cvConvertScale(u8, flt0); 00307 00308 // cvMul(flt0, flt0, flt); 00309 // cvMul(flt, flt0, flt); 00310 cvPow(flt0, flt, gamma); 00311 double maxval; 00312 cvMinMaxLoc(flt, 0, &maxval); 00313 00314 cvConvertScale(flt, u8, 255.0/maxval); 00315 cvCopy(u8, img); 00316 } 00317 00318 cvSetImageCOI(img, 0); 00319 00320 cvReleaseImage(&flt0); 00321 cvReleaseImage(&flt); 00322 cvReleaseImage(&u8); 00323 } 00324 00325 void FilterFeaturesOnEdges(const IplImage* img, const vector<feature_t>& src_features, vector<feature_t>& dst_features, int max_edge_dist, int min_contour_size) 00326 { 00327 printf("entered filterfeaturesonedges\n"); 00328 IplImage* gray = cvCreateImage(cvGetSize(img), 8, 1); 00329 if (img->nChannels > 1) 00330 cvCvtColor(img,gray,CV_BGR2GRAY); 00331 else 00332 cvCopy(img,gray); 00333 00334 IplImage* edges = cvCreateImage( cvGetSize(img), 8, 1 ); 00335 cvCanny( gray, edges, 100, 140, 3 ); 00336 00337 #if 0 00338 cvNamedWindow("1", 1); 00339 cvShowImage("1", edges); 00340 cvWaitKey(0); 00341 #endif 00342 00343 CvMemStorage* storage = cvCreateMemStorage(0); 00344 CvSeq* contours; 00345 cvFindContours(edges,storage,&contours); 00346 00347 00348 CvMemStorage* storage1 = cvCreateMemStorage(0); 00349 CvSeq* contours_filt = cvCreateSeq( 0, sizeof(CvSeq), sizeof(CvSeq*), storage1); 00350 00351 int n = 0; 00352 00353 IplImage* edges1 = cvCreateImage( cvGetSize(img), 8, 1 ); 00354 cvSet(edges1,cvScalar(0)); 00355 00356 for(CvSeq* contour = contours; contour; contour = contour->h_next) 00357 { 00358 CvRect rect = cvBoundingRect(contour); 00359 if ((rect.width < min_contour_size) || (rect.height < min_contour_size) ) 00360 { 00361 continue; 00362 } 00363 00364 CvSeq* poly = cvApproxPoly(contour, sizeof(CvContour), storage1, CV_POLY_APPROX_DP, 1.0); 00365 for(int i = 0; i < poly->total; i++) 00366 { 00367 CvPoint pt1 = *(CvPoint*)cvGetSeqElem(poly, i); 00368 CvPoint pt2 = *(CvPoint*)cvGetSeqElem(poly, i + 1); 00369 00370 const int min_segment_size = min_contour_size; 00371 if(abs(pt1.x - pt2.x) < min_segment_size || abs(pt1.y - pt2.y) < min_segment_size) continue; 00372 cvLine(edges1, pt1, pt2, cvScalar(255)); 00373 } 00374 // cvDrawContours(edges1, contour, cvScalar(255), cvScalar(255), 0, 1); 00375 } 00376 00377 for (int i=0;i<max_edge_dist;i++) 00378 { 00379 cvDilate(edges1,edges1); 00380 } 00381 00382 #if 0 00383 cvNamedWindow("1", 1); 00384 cvShowImage("1", edges1); 00385 cvWaitKey(0); 00386 #endif 00387 00388 dst_features.clear(); 00389 00390 for (int i=0;i<(int)src_features.size();i++) 00391 { 00392 if (edges1->imageData[(int)src_features[i].pt.x+(int)src_features[i].pt.y*edges1->widthStep] == 0) 00393 { 00394 dst_features.push_back(src_features[i]); 00395 } 00396 } 00397 00398 cvReleaseMemStorage(&storage); 00399 cvReleaseMemStorage(&storage1); 00400 cvReleaseImage(&edges); 00401 cvReleaseImage(&edges1); 00402 cvReleaseImage(&gray); 00403 } 00404