Subversion Repositories OpenCV2-Cookbook

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
3 PointedEar 1
/*------------------------------------------------------------------------------------------*\
2
   This file contains material supporting chapter 9 of the cookbook:  
3
   Computer Vision Programming using the OpenCV Library.
4
   by Robert Laganiere, Packt Publishing, 2011.
5
 
6
   This program is free software; permission is hereby granted to use, copy, modify,
7
   and distribute this source code, or portions thereof, for any purpose, without fee,
8
   subject to the restriction that the copyright notice may not be removed
9
   or altered from any source or altered source distribution.
10
   The software is released on an as-is basis and without any warranties of any kind.
11
   In particular, the software is not guaranteed to be fault-tolerant or free from failure.
12
   The author disclaims all warranties with regard to this software, any use,
13
   and any consequent failure, is purely the responsibility of the user.
14
 
15
   Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name
16
\*------------------------------------------------------------------------------------------*/
17
 
18
#include <iostream>
19
#include <vector>
20
#include <opencv2/core/core.hpp>
21
#include <opencv2/imgproc/imgproc.hpp>
22
#include <opencv2/highgui/highgui.hpp>
23
#include <opencv2/features2d/features2d.hpp>
24
#include <opencv2/calib3d/calib3d.hpp>
25
 
26
int main()
27
{
28
        // Read input images
29
        cv::Mat image1= cv::imread("../church01.jpg",0);
30
        cv::Mat image2= cv::imread("../church03.jpg",0);
31
        if (!image1.data || !image2.data)
32
                return 0;
33
 
34
    // Display the images
35
        cv::namedWindow("Right Image");
36
        cv::imshow("Right Image",image1);
37
        cv::namedWindow("Left Image");
38
        cv::imshow("Left Image",image2);
39
 
40
        // vector of keypoints
41
        std::vector<cv::KeyPoint> keypoints1;
42
        std::vector<cv::KeyPoint> keypoints2;
43
 
44
        // Construction of the SURF feature detector 
45
        cv::SurfFeatureDetector surf(3000);
46
 
47
        // Detection of the SURF features
48
        surf.detect(image1,keypoints1);
49
        surf.detect(image2,keypoints2);
50
 
51
        std::cout << "Number of SURF points (1): " << keypoints1.size() << std::endl;
52
        std::cout << "Number of SURF points (2): " << keypoints2.size() << std::endl;
53
 
54
        // Draw the kepoints
55
        cv::Mat imageKP;
56
        cv::drawKeypoints(image1,keypoints1,imageKP,cv::Scalar(255,255,255),cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
57
        cv::namedWindow("Right SURF Features");
58
        cv::imshow("Right SURF Features",imageKP);
59
        cv::drawKeypoints(image2,keypoints2,imageKP,cv::Scalar(255,255,255),cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
60
        cv::namedWindow("Left SURF Features");
61
        cv::imshow("Left SURF Features",imageKP);
62
 
63
        // Construction of the SURF descriptor extractor 
64
        cv::SurfDescriptorExtractor surfDesc;
65
 
66
        // Extraction of the SURF descriptors
67
        cv::Mat descriptors1, descriptors2;
68
        surfDesc.compute(image1,keypoints1,descriptors1);
69
        surfDesc.compute(image2,keypoints2,descriptors2);
70
 
71
        std::cout << "descriptor matrix size: " << descriptors1.rows << " by " << descriptors1.cols << std::endl;
72
 
73
        // Construction of the matcher 
74
        cv::BruteForceMatcher<cv::L2<float>> matcher;
75
 
76
        // Match the two image descriptors
77
        std::vector<cv::DMatch> matches;
78
        matcher.match(descriptors1,descriptors2, matches);
79
 
80
        std::cout << "Number of matched points: " << matches.size() << std::endl;
81
 
82
        // Select few Matches  
83
        std::vector<cv::DMatch> selMatches;
84
        /*
85
        keypoints1.push_back(cv::KeyPoint(342.,615.,2));  
86
        keypoints2.push_back(cv::KeyPoint(410.,600.,2));
87
        selMatches.push_back(cv::DMatch(keypoints1.size()-1,keypoints2.size()-1,0)); // street light bulb
88
        selMatches.push_back(matches[6]);  // right tower
89
        selMatches.push_back(matches[60]);  // left bottom window
90
        selMatches.push_back(matches[139]);
91
        selMatches.push_back(matches[141]);  // middle window
92
        selMatches.push_back(matches[213]);
93
        selMatches.push_back(matches[273]);
94
 
95
        int kk=0;
96
        while (kk<matches.size()) {
97
                std::cout<<kk<<std::endl;
98
        selMatches.push_back(matches[kk++]);
99
        selMatches.pop_back();
100
        cv::waitKey();
101
        }
102
        */
103
 
104
        /* between church01 and church03 */
105
        selMatches.push_back(matches[14]);  
106
        selMatches.push_back(matches[16]);
107
        selMatches.push_back(matches[141]);  
108
        selMatches.push_back(matches[146]);
109
        selMatches.push_back(matches[235]);
110
        selMatches.push_back(matches[238]);
111
        selMatches.push_back(matches[274]);
112
 
113
        // Draw the selected matches
114
        cv::Mat imageMatches;
115
        cv::drawMatches(image1,keypoints1,  // 1st image and its keypoints
116
                            image2,keypoints2,  // 2nd image and its keypoints
117
//                                      selMatches,                     // the matches
118
                                        matches,                        // the matches
119
                                        imageMatches,           // the image produced
120
                                        cv::Scalar(255,255,255)); // color of the lines
121
        cv::namedWindow("Matches");
122
        cv::imshow("Matches",imageMatches);
123
 
124
        // Convert 1 vector of keypoints into
125
        // 2 vectors of Point2f
126
        std::vector<int> pointIndexes1;
127
        std::vector<int> pointIndexes2;
128
        for (std::vector<cv::DMatch>::const_iterator it= selMatches.begin();
129
                 it!= selMatches.end(); ++it) {
130
 
131
                         // Get the indexes of the selected matched keypoints
132
                         pointIndexes1.push_back(it->queryIdx);
133
                         pointIndexes2.push_back(it->trainIdx);
134
        }
135
 
136
        // Convert keypoints into Point2f
137
        std::vector<cv::Point2f> selPoints1, selPoints2;
138
        cv::KeyPoint::convert(keypoints1,selPoints1,pointIndexes1);
139
        cv::KeyPoint::convert(keypoints2,selPoints2,pointIndexes2);
140
 
141
        // check by drawing the points 
142
        std::vector<cv::Point2f>::const_iterator it= selPoints1.begin();
143
        while (it!=selPoints1.end()) {
144
 
145
                // draw a circle at each corner location
146
                cv::circle(image1,*it,3,cv::Scalar(255,255,255),2);
147
                ++it;
148
        }
149
 
150
        it= selPoints2.begin();
151
        while (it!=selPoints2.end()) {
152
 
153
                // draw a circle at each corner location
154
                cv::circle(image2,*it,3,cv::Scalar(255,255,255),2);
155
                ++it;
156
        }
157
 
158
        // Compute F matrix from 7 matches
159
        cv::Mat fundemental= cv::findFundamentalMat(
160
                cv::Mat(selPoints1), // points in first image
161
                cv::Mat(selPoints2), // points in second image
162
                CV_FM_7POINT);       // 7-point method
163
 
164
        std::cout << "F-Matrix size= " << fundemental.rows << "," << fundemental.cols << std::endl;  
165
 
166
        // draw the left points corresponding epipolar lines in right image 
167
        std::vector<cv::Vec3f> lines1;
168
        cv::computeCorrespondEpilines(
169
                cv::Mat(selPoints1), // image points 
170
                1,                   // in image 1 (can also be 2)
171
                fundemental, // F matrix
172
                lines1);     // vector of epipolar lines
173
 
174
        // for all epipolar lines
175
        for (vector<cv::Vec3f>::const_iterator it= lines1.begin();
176
                 it!=lines1.end(); ++it) {
177
 
178
                         // draw the epipolar line between first and last column
179
                         cv::line(image2,cv::Point(0,-(*it)[2]/(*it)[1]),
180
                                             cv::Point(image2.cols,-((*it)[2]+(*it)[0]*image2.cols)/(*it)[1]),
181
                                                         cv::Scalar(255,255,255));
182
        }
183
 
184
        // draw the left points corresponding epipolar lines in left image 
185
        std::vector<cv::Vec3f> lines2;
186
        cv::computeCorrespondEpilines(cv::Mat(selPoints2),2,fundemental,lines2);
187
        for (vector<cv::Vec3f>::const_iterator it= lines2.begin();
188
                 it!=lines2.end(); ++it) {
189
 
190
                         // draw the epipolar line between first and last column
191
                         cv::line(image1,cv::Point(0,-(*it)[2]/(*it)[1]),
192
                                             cv::Point(image1.cols,-((*it)[2]+(*it)[0]*image1.cols)/(*it)[1]),
193
                                                         cv::Scalar(255,255,255));
194
        }
195
 
196
    // Display the images with points and epipolar lines
197
        cv::namedWindow("Right Image Epilines");
198
        cv::imshow("Right Image Epilines",image1);
199
        cv::namedWindow("Left Image Epilines");
200
        cv::imshow("Left Image Epilines",image2);
201
 
202
        /*
203
        std::nth_element(matches.begin(),    // initial position
204
                             matches.begin()+matches.size()/2, // 50%
205
                                         matches.end());     // end position
206
        // remove all elements after the
207
        matches.erase(matches.begin()+matches.size()/2, matches.end());
208
*/
209
        // Convert keypoints into Point2f
210
        std::vector<cv::Point2f> points1, points2;
211
        for (std::vector<cv::DMatch>::const_iterator it= matches.begin();
212
                 it!= matches.end(); ++it) {
213
 
214
                         // Get the position of left keypoints
215
                         float x= keypoints1[it->queryIdx].pt.x;
216
                         float y= keypoints1[it->queryIdx].pt.y;
217
                         points1.push_back(cv::Point2f(x,y));
218
                         // Get the position of right keypoints
219
                         x= keypoints2[it->trainIdx].pt.x;
220
                         y= keypoints2[it->trainIdx].pt.y;
221
                         points2.push_back(cv::Point2f(x,y));
222
        }
223
 
224
        std::cout << points1.size() << " " << points2.size() << std::endl;
225
 
226
        // Compute F matrix using RANSAC
227
        std::vector<uchar> inliers(points1.size(),0);
228
        fundemental= cv::findFundamentalMat(
229
                cv::Mat(points1),cv::Mat(points2), // matching points
230
                inliers,      // match status (inlier ou outlier)  
231
                CV_FM_RANSAC, // RANSAC method
232
                1,            // distance to epipolar line
233
                0.98);        // confidence probability
234
 
235
        // Read input images
236
        image1= cv::imread("../church01.jpg",0);
237
        image2= cv::imread("../church03.jpg",0);
238
 
239
        // Draw the epipolar line of few points
240
        cv::computeCorrespondEpilines(cv::Mat(selPoints1),1,fundemental,lines1);
241
        for (vector<cv::Vec3f>::const_iterator it= lines1.begin();
242
                 it!=lines1.end(); ++it) {
243
 
244
                         cv::line(image2,cv::Point(0,-(*it)[2]/(*it)[1]),
245
                                             cv::Point(image2.cols,-((*it)[2]+(*it)[0]*image2.cols)/(*it)[1]),
246
                                                         cv::Scalar(255,255,255));
247
        }
248
 
249
        cv::computeCorrespondEpilines(cv::Mat(selPoints2),2,fundemental,lines2);
250
        for (vector<cv::Vec3f>::const_iterator it= lines2.begin();
251
                 it!=lines2.end(); ++it) {
252
 
253
                         cv::line(image1,cv::Point(0,-(*it)[2]/(*it)[1]),
254
                                             cv::Point(image1.cols,-((*it)[2]+(*it)[0]*image1.cols)/(*it)[1]),
255
                                                         cv::Scalar(255,255,255));
256
        }
257
 
258
        // Draw the inlier points
259
        std::vector<cv::Point2f> points1In, points2In;
260
        std::vector<cv::Point2f>::const_iterator itPts= points1.begin();
261
        std::vector<uchar>::const_iterator itIn= inliers.begin();
262
        while (itPts!=points1.end()) {
263
 
264
                // draw a circle at each inlier location
265
                if (*itIn) {
266
                        cv::circle(image1,*itPts,3,cv::Scalar(255,255,255),2);
267
                        points1In.push_back(*itPts);
268
                }
269
                ++itPts;
270
                ++itIn;
271
        }
272
 
273
        itPts= points2.begin();
274
        itIn= inliers.begin();
275
        while (itPts!=points2.end()) {
276
 
277
                // draw a circle at each inlier location
278
                if (*itIn) {
279
                        cv::circle(image2,*itPts,3,cv::Scalar(255,255,255),2);
280
                        points2In.push_back(*itPts);
281
                }
282
                ++itPts;
283
                ++itIn;
284
        }
285
 
286
    // Display the images with points
287
        cv::namedWindow("Right Image Epilines (RANSAC)");
288
        cv::imshow("Right Image Epilines (RANSAC)",image1);
289
        cv::namedWindow("Left Image Epilines (RANSAC)");
290
        cv::imshow("Left Image Epilines (RANSAC)",image2);
291
 
292
        cv::findHomography(cv::Mat(points1In),cv::Mat(points2In),inliers,CV_RANSAC,1.);
293
 
294
        // Read input images
295
        image1= cv::imread("../church01.jpg",0);
296
        image2= cv::imread("../church03.jpg",0);
297
 
298
        // Draw the inlier points
299
        itPts= points1In.begin();
300
        itIn= inliers.begin();
301
        while (itPts!=points1In.end()) {
302
 
303
                // draw a circle at each inlier location
304
                if (*itIn)
305
                        cv::circle(image1,*itPts,3,cv::Scalar(255,255,255),2);
306
 
307
                ++itPts;
308
                ++itIn;
309
        }
310
 
311
        itPts= points2In.begin();
312
        itIn= inliers.begin();
313
        while (itPts!=points2In.end()) {
314
 
315
                // draw a circle at each inlier location
316
                if (*itIn)
317
                        cv::circle(image2,*itPts,3,cv::Scalar(255,255,255),2);
318
 
319
                ++itPts;
320
                ++itIn;
321
        }
322
 
323
    // Display the images with points
324
        cv::namedWindow("Right Image Homography (RANSAC)");
325
        cv::imshow("Right Image Homography (RANSAC)",image1);
326
        cv::namedWindow("Left Image Homography (RANSAC)");
327
        cv::imshow("Left Image Homography (RANSAC)",image2);
328
 
329
        cv::waitKey();
330
        return 0;
331
        }