2010-11-14 07:28:41 +01:00
|
|
|
/*
|
|
|
|
* matching_test.cpp
|
|
|
|
*
|
|
|
|
* Created on: Oct 17, 2010
|
|
|
|
* Author: ethan
|
|
|
|
*/
|
2011-08-10 10:56:27 +02:00
|
|
|
#include "opencv2/core/core.hpp"
|
2011-05-21 20:32:34 +02:00
|
|
|
#include "opencv2/calib3d/calib3d.hpp"
|
|
|
|
#include "opencv2/features2d/features2d.hpp"
|
|
|
|
#include "opencv2/imgproc/imgproc.hpp"
|
|
|
|
#include "opencv2/highgui/highgui.hpp"
|
2010-11-14 07:28:41 +01:00
|
|
|
#include <vector>
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
using namespace cv;
|
2011-08-10 10:56:27 +02:00
|
|
|
using namespace std;
|
2010-11-24 03:35:10 +01:00
|
|
|
|
|
|
|
//Copy (x,y) location of descriptor matches found from KeyPoint data structures into Point2f vectors
|
2010-11-14 07:28:41 +01:00
|
|
|
void matches2points(const vector<DMatch>& matches, const vector<KeyPoint>& kpts_train,
|
|
|
|
const vector<KeyPoint>& kpts_query, vector<Point2f>& pts_train, vector<Point2f>& pts_query)
|
|
|
|
{
|
|
|
|
pts_train.clear();
|
|
|
|
pts_query.clear();
|
|
|
|
pts_train.reserve(matches.size());
|
|
|
|
pts_query.reserve(matches.size());
|
|
|
|
for (size_t i = 0; i < matches.size(); i++)
|
|
|
|
{
|
|
|
|
const DMatch& match = matches[i];
|
|
|
|
pts_query.push_back(kpts_query[match.queryIdx].pt);
|
|
|
|
pts_train.push_back(kpts_train[match.trainIdx].pt);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-12-21 12:37:08 +01:00
|
|
|
double match(const vector<KeyPoint>& /*kpts_train*/, const vector<KeyPoint>& /*kpts_query*/, DescriptorMatcher& matcher,
|
2010-11-14 07:28:41 +01:00
|
|
|
const Mat& train, const Mat& query, vector<DMatch>& matches)
|
|
|
|
{
|
|
|
|
|
2010-11-26 11:35:48 +01:00
|
|
|
double t = (double)getTickCount();
|
2010-11-24 03:35:10 +01:00
|
|
|
matcher.match(query, train, matches); //Using features2d
|
2010-11-14 07:28:41 +01:00
|
|
|
return ((double)getTickCount() - t) / getTickFrequency();
|
|
|
|
}
|
|
|
|
|
2011-08-10 10:56:27 +02:00
|
|
|
void help()
|
|
|
|
{
|
2011-08-10 11:43:44 +02:00
|
|
|
cout << "This program shows how to use BRIEF descriptor to match points in features2d" << endl <<
|
|
|
|
"It takes in two images, finds keypoints and matches them displaying matches and final homography warped results" << endl <<
|
|
|
|
"Usage: " << endl <<
|
|
|
|
"image1 image2 " << endl <<
|
|
|
|
"Example: " << endl <<
|
|
|
|
"box.png box_in_scene.png " << endl;
|
2011-08-10 10:56:27 +02:00
|
|
|
}
|
2010-11-24 03:35:10 +01:00
|
|
|
|
2011-08-10 10:56:27 +02:00
|
|
|
const char* keys =
|
|
|
|
{
|
|
|
|
"{1| |box.png |the first image}"
|
|
|
|
"{2| |box_in_scene.png|the second image}"
|
|
|
|
};
|
2010-11-24 03:35:10 +01:00
|
|
|
|
2011-08-10 10:56:27 +02:00
|
|
|
int main(int argc, const char ** argv)
|
2010-11-14 07:28:41 +01:00
|
|
|
{
|
2011-08-10 10:56:27 +02:00
|
|
|
|
|
|
|
help();
|
|
|
|
CommandLineParser parser(argc, argv, keys);
|
|
|
|
string im1_name = parser.get<string>("1");
|
|
|
|
string im2_name = parser.get<string>("2");
|
2010-11-14 07:28:41 +01:00
|
|
|
|
|
|
|
Mat im1 = imread(im1_name, CV_LOAD_IMAGE_GRAYSCALE);
|
|
|
|
Mat im2 = imread(im2_name, CV_LOAD_IMAGE_GRAYSCALE);
|
|
|
|
|
|
|
|
if (im1.empty() || im2.empty())
|
|
|
|
{
|
2011-08-10 11:43:44 +02:00
|
|
|
cout << "could not open one of the images..." << endl;
|
|
|
|
cout << "the cmd parameters have next current value: " << endl;
|
2011-08-10 10:56:27 +02:00
|
|
|
parser.printParams();
|
2010-11-14 07:28:41 +01:00
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
double t = (double)getTickCount();
|
|
|
|
|
|
|
|
FastFeatureDetector detector(50);
|
2010-11-24 03:35:10 +01:00
|
|
|
BriefDescriptorExtractor extractor(32); //this is really 32 x 8 matches since they are binary matches packed into bytes
|
2010-11-14 07:28:41 +01:00
|
|
|
|
|
|
|
vector<KeyPoint> kpts_1, kpts_2;
|
|
|
|
detector.detect(im1, kpts_1);
|
|
|
|
detector.detect(im2, kpts_2);
|
|
|
|
|
|
|
|
t = ((double)getTickCount() - t) / getTickFrequency();
|
|
|
|
|
|
|
|
cout << "found " << kpts_1.size() << " keypoints in " << im1_name << endl << "fount " << kpts_2.size()
|
|
|
|
<< " keypoints in " << im2_name << endl << "took " << t << " seconds." << endl;
|
|
|
|
|
|
|
|
Mat desc_1, desc_2;
|
|
|
|
|
|
|
|
cout << "computing descriptors..." << endl;
|
|
|
|
|
|
|
|
t = (double)getTickCount();
|
|
|
|
|
|
|
|
extractor.compute(im1, kpts_1, desc_1);
|
|
|
|
extractor.compute(im2, kpts_2, desc_2);
|
|
|
|
|
|
|
|
t = ((double)getTickCount() - t) / getTickFrequency();
|
|
|
|
|
|
|
|
cout << "done computing descriptors... took " << t << " seconds" << endl;
|
|
|
|
|
2011-10-11 17:13:53 +02:00
|
|
|
//Do matching using features2d
|
2010-11-14 07:28:41 +01:00
|
|
|
cout << "matching with BruteForceMatcher<Hamming>" << endl;
|
|
|
|
BruteForceMatcher<Hamming> matcher_popcount;
|
|
|
|
vector<DMatch> matches_popcount;
|
2010-11-26 19:25:30 +01:00
|
|
|
double pop_time = match(kpts_1, kpts_2, matcher_popcount, desc_1, desc_2, matches_popcount);
|
2010-11-14 07:28:41 +01:00
|
|
|
cout << "done BruteForceMatcher<Hamming> matching. took " << pop_time << " seconds" << endl;
|
|
|
|
|
|
|
|
vector<Point2f> mpts_1, mpts_2;
|
2010-11-24 03:35:10 +01:00
|
|
|
matches2points(matches_popcount, kpts_1, kpts_2, mpts_1, mpts_2); //Extract a list of the (x,y) location of the matches
|
2010-11-14 07:28:41 +01:00
|
|
|
vector<uchar> outlier_mask;
|
2011-04-18 17:14:32 +02:00
|
|
|
Mat H = findHomography(mpts_2, mpts_1, RANSAC, 1, outlier_mask);
|
2010-11-14 07:28:41 +01:00
|
|
|
|
|
|
|
Mat outimg;
|
|
|
|
drawMatches(im2, kpts_2, im1, kpts_1, matches_popcount, outimg, Scalar::all(-1), Scalar::all(-1),
|
|
|
|
reinterpret_cast<const vector<char>&> (outlier_mask));
|
|
|
|
imshow("matches - popcount - outliers removed", outimg);
|
|
|
|
|
|
|
|
Mat warped;
|
2011-05-03 12:56:20 +02:00
|
|
|
Mat diff;
|
2010-11-14 07:28:41 +01:00
|
|
|
warpPerspective(im2, warped, H, im1.size());
|
|
|
|
imshow("warped", warped);
|
2011-05-03 12:56:20 +02:00
|
|
|
absdiff(im1,warped,diff);
|
|
|
|
imshow("diff", diff);
|
2010-11-14 07:28:41 +01:00
|
|
|
waitKey();
|
|
|
|
return 0;
|
|
|
|
}
|