1 //Calonder descriptor sample
10 // Number of training points (set to -1 to use all points)
11 const int n_points = 30;
13 //Draw the border of projection of train image calculed by averaging detected correspondences
14 const bool draw_border = false;
16 void cvmSet6(CvMat* m, int row, int col, float val1, float val2, float val3, float val4, float val5, float val6)
18 cvmSet(m, row, col, val1);
19 cvmSet(m, row, col + 1, val2);
20 cvmSet(m, row, col + 2, val3);
21 cvmSet(m, row, col + 3, val4);
22 cvmSet(m, row, col + 4, val5);
23 cvmSet(m, row, col + 5, val6);
26 void FindAffineTransform(const vector<CvPoint>& p1, const vector<CvPoint>& p2, CvMat* affine)
28 int eq_num = 2*(int)p1.size();
29 CvMat* A = cvCreateMat(eq_num, 6, CV_32FC1);
30 CvMat* B = cvCreateMat(eq_num, 1, CV_32FC1);
31 CvMat* X = cvCreateMat(6, 1, CV_32FC1);
33 for(int i = 0; i < (int)p1.size(); i++)
35 cvmSet6(A, 2*i, 0, p1[i].x, p1[i].y, 1, 0, 0, 0);
36 cvmSet6(A, 2*i + 1, 0, 0, 0, 0, p1[i].x, p1[i].y, 1);
37 cvmSet(B, 2*i, 0, p2[i].x);
38 cvmSet(B, 2*i + 1, 0, p2[i].y);
41 cvSolve(A, B, X, CV_SVD);
43 cvmSet(affine, 0, 0, cvmGet(X, 0, 0));
44 cvmSet(affine, 0, 1, cvmGet(X, 1, 0));
45 cvmSet(affine, 0, 2, cvmGet(X, 2, 0));
46 cvmSet(affine, 1, 0, cvmGet(X, 3, 0));
47 cvmSet(affine, 1, 1, cvmGet(X, 4, 0));
48 cvmSet(affine, 1, 2, cvmGet(X, 5, 0));
55 void MapVectorAffine(const vector<CvPoint>& p1, vector<CvPoint>& p2, CvMat* transform)
57 float a = cvmGet(transform, 0, 0);
58 float b = cvmGet(transform, 0, 1);
59 float c = cvmGet(transform, 0, 2);
60 float d = cvmGet(transform, 1, 0);
61 float e = cvmGet(transform, 1, 1);
62 float f = cvmGet(transform, 1, 2);
64 for(int i = 0; i < (int)p1.size(); i++)
66 float x = a*p1[i].x + b*p1[i].y + c;
67 float y = d*p1[i].x + e*p1[i].y + f;
68 p2.push_back(cvPoint(x, y));
73 float CalcAffineReprojectionError(const vector<CvPoint>& p1, const vector<CvPoint>& p2, CvMat* transform)
75 vector<CvPoint> mapped_p1;
76 MapVectorAffine(p1, mapped_p1, transform);
78 for(int i = 0; i < (int)p2.size(); i++)
80 error += ((p2[i].x - mapped_p1[i].x)*(p2[i].x - mapped_p1[i].x)+(p2[i].y - mapped_p1[i].y)*(p2[i].y - mapped_p1[i].y));
89 int main( int argc, char** argv )
93 IplImage* train_image;
97 test_image = cvLoadImage("box_in_scene.png",0);
98 train_image = cvLoadImage("box.png ",0);
99 if (!test_image || !train_image)
101 printf("Usage: calonder_sample <train_image> <test_image>");
107 test_image = cvLoadImage(argv[2],0);
108 train_image = cvLoadImage(argv[1],0);
117 printf("Unable to load train image\n");
123 printf("Unable to load test image\n");
129 CvMemStorage* storage = cvCreateMemStorage(0);
130 CvSeq *objectKeypoints = 0, *objectDescriptors = 0;
131 CvSeq *imageKeypoints = 0, *imageDescriptors = 0;
132 CvSURFParams params = cvSURFParams(500, 1);
133 cvExtractSURF( test_image, 0, &imageKeypoints, &imageDescriptors, storage, params );
134 cvExtractSURF( train_image, 0, &objectKeypoints, &objectDescriptors, storage, params );
137 cv::RTreeClassifier detector;
138 int patch_width = cv::PATCH_SIZE;
139 int patch_height = cv::PATCH_SIZE;
140 vector<cv::BaseKeypoint> base_set;
145 for (i=0;i<(n_points > 0 ? n_points : objectKeypoints->total);i++)
147 point=(CvSURFPoint*)cvGetSeqElem(objectKeypoints,i);
148 base_set.push_back(cv::BaseKeypoint(point->pt.x,point->pt.y,train_image));
152 cv::RNG rng( cvGetTickCount() );
153 cv::PatchGenerator gen(0,255,2,false,0.7,1.3,-CV_PI/3,CV_PI/3,-CV_PI/3,CV_PI/3);
155 printf("RTree Classifier training...\n");
156 detector.train(base_set,rng,gen,24,cv::DEFAULT_DEPTH,2000,(int)base_set.size(),detector.DEFAULT_NUM_QUANT_BITS);
159 float* signature = new float[detector.original_num_classes()];
162 if (imageKeypoints->total > 0)
164 best_corr = new float[imageKeypoints->total];
165 best_corr_idx = new int[imageKeypoints->total];
168 for(i=0; i < imageKeypoints->total; i++)
170 point=(CvSURFPoint*)cvGetSeqElem(imageKeypoints,i);
175 CvRect roi = cvRect((int)(point->pt.x) - patch_width/2,(int)(point->pt.y) - patch_height/2, patch_width, patch_height);
176 cvSetImageROI(test_image, roi);
177 roi = cvGetImageROI(test_image);
178 if(roi.width != patch_width || roi.height != patch_height)
180 best_corr_idx[i] = part_idx;
185 cvSetImageROI(test_image, roi);
186 IplImage* roi_image = cvCreateImage(cvSize(roi.width, roi.height), test_image->depth, test_image->nChannels);
187 cvCopy(test_image,roi_image);
189 detector.getSignature(roi_image, signature);
192 for (int j = 0; j< detector.original_num_classes();j++)
194 if (prob < signature[j])
201 best_corr_idx[i] = part_idx;
206 cvReleaseImage(&roi_image);
208 cvResetImageROI(test_image);
211 float min_prob = 0.0f;
212 vector<CvPoint> object;
213 vector<CvPoint> features;
215 for (int j=0;j<objectKeypoints->total;j++)
219 for (i = 0; i<imageKeypoints->total;i++)
221 if ((best_corr_idx[i]!=j)||(best_corr[i] < min_prob))
224 if (best_corr[i] > prob)
232 point=(CvSURFPoint*)cvGetSeqElem(objectKeypoints,j);
233 object.push_back(cvPoint((int)point->pt.x,(int)point->pt.y));
234 point=(CvSURFPoint*)cvGetSeqElem(imageKeypoints,idx);
235 features.push_back(cvPoint((int)point->pt.x,(int)point->pt.y));
238 if ((int)object.size() > 3)
240 CvMat* affine = cvCreateMat(2, 3, CV_32FC1);
241 FindAffineTransform(object,features,affine);
243 vector<CvPoint> corners;
244 vector<CvPoint> mapped_corners;
245 corners.push_back(cvPoint(0,0));
246 corners.push_back(cvPoint(0,train_image->height));
247 corners.push_back(cvPoint(train_image->width,0));
248 corners.push_back(cvPoint(train_image->width,train_image->height));
249 MapVectorAffine(corners,mapped_corners,affine);
252 IplImage* result = cvCreateImage(cvSize(test_image->width > train_image->width ? test_image->width : train_image->width,
253 train_image->height + test_image->height),
254 test_image->depth, test_image->nChannels);
255 cvSetImageROI(result,cvRect(0,0,train_image->width, train_image->height));
256 cvCopy(train_image,result);
257 cvResetImageROI(result);
258 cvSetImageROI(result,cvRect(0,train_image->height,test_image->width, test_image->height));
259 cvCopy(test_image,result);
260 cvResetImageROI(result);
262 for (int i=0;i<(int)features.size();i++)
264 cvLine(result,object[i],cvPoint(features[i].x,features[i].y+train_image->height),cvScalar(255));
269 cvLine(result,cvPoint(mapped_corners[0].x, mapped_corners[0].y+train_image->height),
270 cvPoint(mapped_corners[1].x, mapped_corners[1].y+train_image->height),cvScalar(150),3);
271 cvLine(result,cvPoint(mapped_corners[0].x, mapped_corners[0].y+train_image->height),
272 cvPoint(mapped_corners[2].x, mapped_corners[2].y+train_image->height),cvScalar(150),3);
273 cvLine(result,cvPoint(mapped_corners[1].x, mapped_corners[1].y+train_image->height),
274 cvPoint(mapped_corners[3].x, mapped_corners[3].y+train_image->height),cvScalar(150),3);
275 cvLine(result,cvPoint(mapped_corners[2].x, mapped_corners[2].y+train_image->height),
276 cvPoint(mapped_corners[3].x, mapped_corners[3].y+train_image->height),cvScalar(150),3);
279 cvSaveImage("Result.jpg",result);
280 cvNamedWindow("Result",0);
281 cvShowImage("Result",result);
283 cvReleaseMat(&affine);
284 cvReleaseImage(&result);
288 printf("Unable to find correspondence\n");
298 cvReleaseMemStorage(&storage);
299 cvReleaseImage(&train_image);
300 cvReleaseImage(&test_image);