32 #include <opencv2/core/core.hpp>
33 #include <opencv2/highgui/highgui.hpp>
34 #include <opencv2/features2d/features2d.hpp>
35 #include <opencv2/calib3d/calib3d.hpp>
36 #include <opencv2/opencv_modules.hpp>
38 #ifdef HAVE_OPENCV_NONFREE
39 #if CV_MAJOR_VERSION == 2 && CV_MINOR_VERSION >=4
40 #include <opencv2/nonfree/gpu.hpp>
41 #include <opencv2/nonfree/features2d.hpp>
44 #ifdef HAVE_OPENCV_XFEATURES2D
45 #include <opencv2/xfeatures2d.hpp>
46 #include <opencv2/xfeatures2d/cuda.hpp>
53 "Return similarity between two images (the number of similar features between the images).\n"
55 " ./find_object-similarity [option] object.png scene.png\n"
57 " -inliers return inliers percentage : inliers / (inliers + outliers)\n"
58 " -quiet don't show messages\n");
65 int main(
int argc,
char * argv[])
71 printf(
"Two images required!\n");
76 for(
int i=1; i<argc-2; ++i)
78 if(std::string(argv[i]).compare(
"-inliers") == 0)
82 else if(std::string(argv[i]).compare(
"-quiet") == 0)
88 printf(
"Option %s not recognized!", argv[1]);
96 cv::Mat objectImg = cv::imread(argv[argc-2], cv::IMREAD_GRAYSCALE);
97 cv::Mat sceneImg = cv::imread(argv[argc-1], cv::IMREAD_GRAYSCALE);
100 if(!objectImg.empty() && !sceneImg.empty())
102 std::vector<cv::KeyPoint> objectKeypoints;
103 std::vector<cv::KeyPoint> sceneKeypoints;
104 cv::Mat objectDescriptors;
105 cv::Mat sceneDescriptors;
107 #if CV_MAJOR_VERSION < 3
112 sift.detect(objectImg, objectKeypoints);
113 sift.detect(sceneImg, sceneKeypoints);
118 sift.compute(objectImg, objectKeypoints, objectDescriptors);
119 sift.compute(sceneImg, sceneKeypoints, sceneDescriptors);
124 #if (CV_MAJOR_VERSION == 4 && CV_MINOR_VERSION <= 3) || (CV_MAJOR_VERSION == 3 && (CV_MINOR_VERSION < 4 || (CV_MINOR_VERSION==4 && CV_SUBMINOR_VERSION<11)))
125 cv::Ptr<cv::xfeatures2d::SIFT> sift = cv::xfeatures2d::SIFT::create();
127 cv::Ptr<cv::SIFT> sift = cv::SIFT::create();
129 sift->detect(objectImg, objectKeypoints);
130 sift->detect(sceneImg, sceneKeypoints);
135 sift->compute(objectImg, objectKeypoints, objectDescriptors);
136 sift->compute(sceneImg, sceneKeypoints, sceneDescriptors);
143 std::vector<std::vector<cv::DMatch> > matches;
147 cv::flann::Index flannIndex(sceneDescriptors, cv::flann::KDTreeIndexParams(), cvflann::FLANN_DIST_EUCLIDEAN);
148 results = cv::Mat(objectDescriptors.rows, k, CV_32SC1);
149 dists = cv::Mat(objectDescriptors.rows, k, CV_32FC1);
152 flannIndex.knnSearch(objectDescriptors, results, dists, k, cv::flann::SearchParams() );
159 float nndrRatio = 0.6f;
160 std::vector<cv::Point2f> mpts_1, mpts_2;
161 std::vector<int> indexes_1, indexes_2;
162 std::vector<uchar> outlier_mask;
165 for(
int i=0; i<objectDescriptors.rows; ++i)
168 if(dists.at<
float>(i,0) <= nndrRatio * dists.at<
float>(i,1))
170 mpts_1.push_back(objectKeypoints.at(i).pt);
171 indexes_1.push_back(i);
173 mpts_2.push_back(sceneKeypoints.at(results.at<
int>(i,0)).pt);
174 indexes_2.push_back(results.at<
int>(i,0));
181 unsigned int minInliers = 8;
182 if(mpts_1.size() >= minInliers)
184 cv::Mat H = findHomography(mpts_1,
189 int inliers=0, outliers=0;
190 for(
unsigned int k=0; k<mpts_1.size();++k)
192 if(outlier_mask.at(k))
202 printf(
"Total=%d Inliers=%d Outliers=%d\n", (
int)mpts_1.size(), inliers, outliers);
203 value = (inliers*100) / (inliers+outliers);
208 value = (int)mpts_1.size();
213 printf(
"Images are not valid!\n");
217 printf(
"Similarity = %d\n", value);