--- /dev/null
+/*
+ * matching_test.cpp
+ *
+ * Created on: Oct 17, 2010
+ * Author: ethan
+ */
+#include <opencv2/opencv.hpp>
+#include <vector>
+#include <iostream>
+
+using namespace cv;
+
+using std::cout;
+using std::cerr;
+using std::endl;
+using std::vector;
+
+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);
+ }
+
+}
+
+float match(const vector<KeyPoint>& kpts_train, const vector<KeyPoint>& kpts_query, DescriptorMatcher& matcher,
+ const Mat& train, const Mat& query, vector<DMatch>& matches)
+{
+
+ float t = (double)getTickCount();
+ matcher.match(query, train, matches);
+ return ((double)getTickCount() - t) / getTickFrequency();
+}
+
+int main(int ac, char ** av)
+{
+ if (ac != 3)
+ {
+ cerr << "usage: " << av[0] << " im1.jpg im2.jpg" << endl;
+ return 1;
+ }
+ string im1_name, im2_name;
+ im1_name = av[1];
+ im2_name = av[2];
+
+ Mat im1 = imread(im1_name, CV_LOAD_IMAGE_GRAYSCALE);
+ Mat im2 = imread(im2_name, CV_LOAD_IMAGE_GRAYSCALE);
+
+ if (im1.empty() || im2.empty())
+ {
+ cerr << "could not open one of the images..." << endl;
+ return 1;
+ }
+
+ double t = (double)getTickCount();
+
+ FastFeatureDetector detector(50);
+ BriefDescriptorExtractor extractor(32);
+
+ 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;
+
+ cout << "matching with BruteForceMatcher<HammingLUT>" << endl;
+ BruteForceMatcher<HammingLUT> matcher;
+ vector<DMatch> matches_lut;
+ float lut_time = match(kpts_1, kpts_2, matcher, desc_1, desc_2, matches_lut);
+ cout << "done BruteForceMatcher<HammingLUT> matching. took " << lut_time << " seconds" << endl;
+
+ cout << "matching with BruteForceMatcher<Hamming>" << endl;
+ BruteForceMatcher<Hamming> matcher_popcount;
+ vector<DMatch> matches_popcount;
+ float pop_time = match(kpts_1, kpts_2, matcher_popcount, desc_1, desc_2, matches_popcount);
+ cout << "done BruteForceMatcher<Hamming> matching. took " << pop_time << " seconds" << endl;
+
+ vector<Point2f> mpts_1, mpts_2;
+ matches2points(matches_popcount, kpts_1, kpts_2, mpts_1, mpts_2);
+ vector<uchar> outlier_mask;
+ Mat H = findHomography(Mat(mpts_2), Mat(mpts_1), outlier_mask, RANSAC, 1);
+
+ 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;
+ warpPerspective(im2, warped, H, im1.size());
+ imshow("warped", warped);
+ imshow("diff", im1 - warped);
+ waitKey();
+ return 0;
+}
--- /dev/null
+/*
+ * video_homography.cpp
+ *
+ * Created on: Oct 18, 2010
+ * Author: erublee
+ */
+
+#include <opencv2/opencv.hpp>
+#include <iostream>
+#include <list>
+#include <vector>
+
+using namespace std;
+using namespace cv;
+
+namespace
+{
+void drawMatchesRelative(const vector<KeyPoint>& train, const vector<KeyPoint>& query,
+ std::vector<cv::DMatch>& matches, Mat& img, const vector<unsigned char>& mask = vector<
+ unsigned char> ())
+{
+ for (int i = 0; i < (int)matches.size(); i++)
+ {
+ if (mask.empty() || mask[i])
+ {
+ Point2f pt_new = query[matches[i].queryIdx].pt;
+ Point2f pt_old = train[matches[i].trainIdx].pt;
+ Point2f dist = pt_new - pt_old;
+
+ cv::line(img, pt_new, pt_old, Scalar(125, 255, 125), 1);
+ cv::circle(img, pt_new, 2, Scalar(255, 0, 125), 1);
+
+ }
+ }
+}
+
+void keypoints2points(const vector<KeyPoint>& in, vector<Point2f>& out)
+{
+ out.clear();
+ out.reserve(in.size());
+ for (size_t i = 0; i < in.size(); ++i)
+ {
+ out.push_back(in[i].pt);
+ }
+}
+
+void points2keypoints(const vector<Point2f>& in, vector<KeyPoint>& out)
+{
+ out.clear();
+ out.reserve(in.size());
+ for (size_t i = 0; i < in.size(); ++i)
+ {
+ out.push_back(KeyPoint(in[i], 1));
+ }
+}
+
+void warpKeypoints(const Mat& H, const vector<KeyPoint>& in, vector<KeyPoint>& out)
+{
+ vector<Point2f> pts;
+ keypoints2points(in, pts);
+ vector<Point2f> pts_w(pts.size());
+ Mat m_pts_w(pts_w);
+ perspectiveTransform(Mat(pts), m_pts_w, H);
+ points2keypoints(pts_w, out);
+}
+
+void matches2points(const vector<KeyPoint>& train, const vector<KeyPoint>& query,
+ const std::vector<cv::DMatch>& matches, std::vector<cv::Point2f>& pts_train,
+ std::vector<Point2f>& pts_query)
+{
+
+ pts_train.clear();
+ pts_query.clear();
+ pts_train.reserve(matches.size());
+ pts_query.reserve(matches.size());
+
+ size_t i = 0;
+
+ for (; i < matches.size(); i++)
+ {
+
+ const DMatch & dmatch = matches[i];
+
+ pts_query.push_back(query[dmatch.queryIdx].pt);
+ pts_train.push_back(train[dmatch.trainIdx].pt);
+
+ }
+
+}
+
+void resetH(Mat&H)
+{
+ H = Mat::eye(3, 3, CV_32FC1);
+}
+}
+int main(int ac, char ** av)
+{
+
+ if (ac != 2)
+ {
+ cout << "usage: " << av[0] << " <video device number>" << endl;
+ return 1;
+ }
+
+ BriefDescriptorExtractor brief(32);
+
+ VideoCapture capture;
+ capture.open(atoi(av[1]));
+ if (!capture.isOpened())
+ {
+ cout << "capture device " << atoi(av[1]) << " failed to open!" << endl;
+ return 1;
+ }
+
+ cout << "following keys do stuff:" << endl;
+ cout << "t : grabs a reference frame to match against" << endl;
+ cout << "l : makes the reference frame new every frame" << endl;
+ cout << "q or escape: quit" << endl;
+
+ Mat frame;
+
+ vector<DMatch> matches;
+
+ BruteForceMatcher<Hamming> desc_matcher;
+
+ vector<Point2f> train_pts, query_pts;
+ vector<KeyPoint> train_kpts, query_kpts;
+ vector<unsigned char> match_mask;
+
+ Mat gray;
+
+ bool ref_live = true;
+
+ Mat train_desc, query_desc;
+ const int DESIRED_FTRS = 500;
+ GridAdaptedFeatureDetector detector(new FastFeatureDetector(10, true), DESIRED_FTRS, 4, 4);
+
+ Mat H_prev = Mat::eye(3, 3, CV_32FC1);
+ for (;;)
+ {
+ capture >> frame;
+ if (frame.empty())
+ continue;
+
+ cvtColor(frame, gray, CV_RGB2GRAY);
+
+ detector.detect(gray, query_kpts);
+
+ brief.compute(gray, query_kpts, query_desc);
+
+ if (!train_kpts.empty())
+ {
+
+ vector<KeyPoint> test_kpts;
+ warpKeypoints(H_prev.inv(), query_kpts, test_kpts);
+
+ Mat mask = windowedMatchingMask(test_kpts, train_kpts, 25, 25);
+ desc_matcher.match(query_desc, train_desc, matches, mask);
+ drawKeypoints(frame, test_kpts, frame, Scalar(255, 0, 0), DrawMatchesFlags::DRAW_OVER_OUTIMG);
+
+ matches2points(train_kpts, query_kpts, matches, train_pts, query_pts);
+
+ if (matches.size() > 5)
+ {
+ Mat H = findHomography(Mat(train_pts), Mat(query_pts), match_mask, RANSAC, 4);
+ if (countNonZero(Mat(match_mask)) > 15)
+ {
+ H_prev = H;
+ }
+ else
+ resetH(H_prev);
+ drawMatchesRelative(train_kpts, query_kpts, matches, frame, match_mask);
+ }
+ else
+ resetH(H_prev);
+
+ }
+ else
+ {
+ H_prev = Mat::eye(3, 3, CV_32FC1);
+ Mat out;
+ drawKeypoints(gray, query_kpts, out);
+ frame = out;
+ }
+
+ imshow("frame", frame);
+
+ if (ref_live)
+ {
+ train_kpts = query_kpts;
+ query_desc.copyTo(train_desc);
+ }
+ char key = waitKey(2);
+ switch (key)
+ {
+ case 'l':
+ ref_live = true;
+ resetH(H_prev);
+ break;
+ case 't':
+ ref_live = false;
+ train_kpts = query_kpts;
+ query_desc.copyTo(train_desc);
+ resetH(H_prev);
+ break;
+ case 27:
+ case 'q':
+ return 0;
+ break;
+ }
+
+ }
+ return 0;
+}