1 #include "opencv2/highgui/highgui.hpp"
2 #include "opencv2/core/core.hpp"
3 #include "opencv2/imgproc/imgproc.hpp"
4 #include "opencv2/features2d/features2d.hpp"
13 * Generates random perspective transform of image
15 void warpPerspectiveRand( const Mat& src, Mat& dst, Mat& H, RNG& rng )
17 H.create(3, 3, CV_32FC1);
18 H.at<float>(0,0) = rng.uniform( 0.8f, 1.2f);
19 H.at<float>(0,1) = rng.uniform(-0.1f, 0.1f);
20 H.at<float>(0,2) = rng.uniform(-0.1f, 0.1f)*src.cols;
21 H.at<float>(1,0) = rng.uniform(-0.1f, 0.1f);
22 H.at<float>(1,1) = rng.uniform( 0.8f, 1.2f);
23 H.at<float>(1,2) = rng.uniform(-0.1f, 0.1f)*src.rows;
24 H.at<float>(2,0) = rng.uniform( -1e-4f, 1e-4f);
25 H.at<float>(2,1) = rng.uniform( -1e-4f, 1e-4f);
26 H.at<float>(2,2) = rng.uniform( 0.8f, 1.2f);
28 warpPerspective( src, dst, H, src.size() );
32 * Trains Calonder classifier and writes trained classifier in file:
33 * imgFilename - name of .txt file which contains list of full filenames of train images,
34 * classifierFilename - name of binary file in which classifier will be written.
36 * To train Calonder classifier RTreeClassifier class need to be used.
38 void trainCalonderClassifier( const string& classifierFilename, const string& imgFilename )
41 ifstream is( imgFilename.c_str(), ifstream::in );
42 vector<Mat> trainImgs;
47 if (str.empty()) break;
48 Mat img = imread( str, CV_LOAD_IMAGE_GRAYSCALE );
50 trainImgs.push_back( img );
52 if( trainImgs.empty() )
54 cout << "All train images can not be read." << endl;
57 cout << trainImgs.size() << " train images were read." << endl;
59 // Extracts keypoints from train images
60 SurfFeatureDetector detector;
61 vector<BaseKeypoint> trainPoints;
62 vector<IplImage> iplTrainImgs(trainImgs.size());
63 for( size_t imgIdx = 0; imgIdx < trainImgs.size(); imgIdx++ )
65 iplTrainImgs[imgIdx] = trainImgs[imgIdx];
66 vector<KeyPoint> kps; detector.detect( trainImgs[imgIdx], kps );
68 for( size_t pointIdx = 0; pointIdx < kps.size(); pointIdx++ )
70 Point2f p = kps[pointIdx].pt;
71 trainPoints.push_back( BaseKeypoint(cvRound(p.x), cvRound(p.y), &iplTrainImgs[imgIdx]) );
75 // Trains Calonder classifier on extracted points
76 RTreeClassifier classifier;
77 classifier.train( trainPoints, theRNG(), 48, 9, 100 );
79 classifier.write( classifierFilename.c_str() );
83 * Test Calonder classifier to match keypoints on given image:
84 * classifierFilename - name of file from which classifier will be read,
85 * imgFilename - test image filename.
87 * To calculate keypoint descriptors you may use RTreeClassifier class (as to train),
88 * but it is convenient to use CalonderDescriptorExtractor class which is wrapper of
91 void testCalonderClassifier( const string& classifierFilename, const string& imgFilename )
93 Mat img1 = imread( imgFilename, CV_LOAD_IMAGE_GRAYSCALE ), img2, H12;
96 cout << "Test image can not be read." << endl;
99 warpPerspectiveRand( img1, img2, H12, theRNG() );
101 // Exstract keypoints from test images
102 SurfFeatureDetector detector;
103 vector<KeyPoint> keypoints1; detector.detect( img1, keypoints1 );
104 vector<KeyPoint> keypoints2; detector.detect( img2, keypoints2 );
106 // Compute descriptors
107 CalonderDescriptorExtractor<float> de( classifierFilename );
108 Mat descriptors1; de.compute( img1, keypoints1, descriptors1 );
109 Mat descriptors2; de.compute( img2, keypoints2, descriptors2 );
112 BruteForceMatcher<L1<float> > matcher;
113 vector<DMatch> matches;
114 matcher.match( descriptors1, descriptors2, matches );
116 // Prepare inlier mask
117 vector<char> matchesMask( matches.size(), 0 );
118 vector<Point2f> points1; KeyPoint::convert( keypoints1, points1 );
119 vector<Point2f> points2; KeyPoint::convert( keypoints2, points2 );
120 Mat points1t; perspectiveTransform(Mat(points1), points1t, H12);
121 for( size_t mi = 0; mi < matches.size(); mi++ )
123 if( norm(points2[matches[mi].trainIdx] - points1t.at<Point2f>(mi,0)) < 4 ) // inlier
129 drawMatches( img1, keypoints1, img2, keypoints2, matches, drawImg, CV_RGB(0, 255, 0), CV_RGB(0, 0, 255), matchesMask );
130 string winName = "Matches";
131 namedWindow( winName, WINDOW_AUTOSIZE );
132 imshow( winName, drawImg );
137 int main( int argc, char **argv )
139 if( argc != 4 && argc != 3 )
141 cout << "Format:" << endl <<
142 " classifier_file(to write) test_image file_with_train_images_filenames(txt)" <<
144 " classifier_file(to read) test_image" << endl;
149 trainCalonderClassifier( argv[1], argv[3] );
151 testCalonderClassifier( argv[1], argv[2] );