如何在OpenCV中比较两个组关键点
How to compare two group keypoint in OpenCV
我想从图像中找到一些东西。
就像人脸检测,但未检测到人脸,我想检测其他东西。
所以我使用SURF算术找到关键点,并使用FLANN算术匹配关键点。
但我怎么知道图像是否匹配?
我认为如果源图像s Key Points distribute and template image
的关键点分布需要非常相似,那么两个 iamge 匹配。但是怎么办?
int main( int argc, char** argv )
{
std::string templateStr = "D:\template2.jpg";
std::string srcString = "D:\IMG_0284.jpg";
Mat img_1 = imread(templateStr, CV_LOAD_IMAGE_GRAYSCALE );
Mat img_2 = imread(srcString, CV_LOAD_IMAGE_GRAYSCALE );
//-- Step 1: Detect the keypoints using SURF Detector
int minHessian = 500;
SurfFeatureDetector detector( minHessian );
std::vector<KeyPoint> keypoints_1, keypoints_2;
detector.detect( img_1, keypoints_1 );
detector.detect( img_2, keypoints_2 );
//show keypoint,only test
Mat img_11 = imread(templateStr, CV_LOAD_IMAGE_GRAYSCALE );
Mat img_21 = imread(srcString, CV_LOAD_IMAGE_GRAYSCALE );
drawKeypoints (img_11, keypoints_1, img_11, cv::Scalar::all(0), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
drawKeypoints (img_21, keypoints_2, img_21, cv::Scalar::all(0), cv::DrawMatchesFlags::DRAW_RICH_KEYPOINTS);
cv::namedWindow ("img_11");
cv::imshow ("img_11",img_11);
cv::namedWindow ("img_21");
cv::imshow ("img_21",img_21);
cv::waitKey (0);
//-- Step 2: Calculate descriptors (feature vectors)
SurfDescriptorExtractor extractor;
Mat descriptors_1, descriptors_2;
extractor.compute( img_1, keypoints_1, descriptors_1 );
extractor.compute( img_2, keypoints_2, descriptors_2 );
//-- Step 3: Matching descriptor vectors using FLANN matcher
FlannBasedMatcher matcher;
std::vector<DMatch> matches;
tt = (double)cvGetTickCount();
matcher.match( descriptors_1, descriptors_2, matches );
double max_dist = 0; double min_dist = 100;
//-- Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptors_1.rows; i++ )
{
double dist = matches[i].distance;
if( dist < min_dist )
min_dist = dist;
if( dist > max_dist )
max_dist = dist;
}
printf("-- Max dist : %f n", max_dist );
printf("-- Min dist : %f n", min_dist );
//-- Draw only "good" matches (i.e. whose distance is less than 2*min_dist )
//-- PS.- radiusMatch can also be used here.
std::vector< DMatch > good_matches;
for( int i = 0; i < descriptors_1.rows; i++ )
{
if( matches[i].distance < 3*min_dist )
{
good_matches.push_back( matches[i]);
}
}
//-- Draw only "good" matches
Mat img_matches;
drawMatches( img_1, keypoints_1, img_2, keypoints_2, good_matches, img_matches,
Scalar::all(-1), Scalar::all(-1),vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
//now I have two group keypoint,keypoints_1 and keypoints_2,and they is match.
//keypoints_1 is tmeplate image`s keypoints,
//keypoints_2 is source image`s keypoints,
//so I how to compare distribution of keypoints_1 and keypoints_2?
//if the two group keypoint`s distribute is very similarity,I will think the two image is match
return 0;
}
我使用OpenCV2.4.9,VS 2010。
-
您可以尝试以下代码。也许这会对你有所帮助。
#include <opencv2/nonfree/nonfree.hpp> #include <iostream> #include <dirent.h> #include <ctime> #include <stdio.h> using namespace cv; using namespace std; int main(int argc, const char *argv[]) { double ratio = 0.9; Mat image1 = imread("Image1_path"); Mat image2 = cv::imread("Image2_path"); Ptr<FeatureDetector> detector; Ptr<DescriptorExtractor> extractor; // TODO default is 500 keypoints..but we can change detector = FeatureDetector::create("ORB"); extractor = DescriptorExtractor::create("ORB"); vector<KeyPoint> keypoints1, keypoints2; detector->detect(image1, keypoints1); detector->detect(image2, keypoints2); cout << "# keypoints of image1 :" << keypoints1.size() << endl; cout << "# keypoints of image2 :" << keypoints2.size() << endl; Mat descriptors1,descriptors2; extractor->compute(image1,keypoints1,descriptors1); extractor->compute(image2,keypoints2,descriptors2); cout << "Descriptors size :" << descriptors1.cols << ":"<< descriptors1.rows << endl; vector< vector<DMatch> > matches12, matches21; Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("BruteForce-Hamming"); matcher->knnMatch( descriptors1, descriptors2, matches12, 2); matcher->knnMatch( descriptors2, descriptors1, matches21, 2); //BFMatcher bfmatcher(NORM_L2, true); //vector<DMatch> matches; //bfmatcher.match(descriptors1, descriptors2, matches); double max_dist = 0; double min_dist = 100; for( int i = 0; i < descriptors1.rows; i++) { double dist = matches12[i].data()->distance; if(dist < min_dist) min_dist = dist; if(dist > max_dist) max_dist = dist; } printf("-- Max dist : %f n", max_dist); printf("-- Min dist : %f n", min_dist); cout << "Matches1-2:" << matches12.size() << endl; cout << "Matches2-1:" << matches21.size() << endl; std::vector<DMatch> good_matches1, good_matches2; for(int i=0; i < matches12.size(); i++) { if(matches12[i][0].distance < ratio * matches12[i][1].distance) good_matches1.push_back(matches12[i][0]); } for(int i=0; i < matches21.size(); i++) { if(matches21[i][0].distance < ratio * matches21[i][1].distance) good_matches2.push_back(matches21[i][0]); } cout << "Good matches1:" << good_matches1.size() << endl; cout << "Good matches2:" << good_matches2.size() << endl; // Symmetric Test std::vector<DMatch> better_matches; for(int i=0; i<good_matches1.size(); i++) { for(int j=0; j<good_matches2.size(); j++) { if(good_matches1[i].queryIdx == good_matches2[j].trainIdx && good_matches2[j].queryIdx == good_matches1[i].trainIdx) { better_matches.push_back(DMatch(good_matches1[i].queryIdx, good_matches1[i].trainIdx, good_matches1[i].distance)); break; } } } cout << "Better matches:" << better_matches.size() << endl; // show it on an image Mat output; drawMatches(image1, keypoints1, image2, keypoints2, better_matches, output); imshow("Matches result",output); waitKey(0); return 0; }
-
为了找到良好的匹配,您可以取阈值,例如如果更好
matches.size() > threshold
则将其视为良好图像。
相关文章:
- 如何在C++中从两个单独的for循环中添加两个数组
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- 如何返回一个类的两个对象相加的结果
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 两个字符串在 c++ 中不相等
- 在两个类中共享相同的函数调用,并在不需要时避免空实例化
- 两个文件使用彼此的功能-如何解决
- 为什么Mat类的两个对象可以在不重载运算符+的情况下添加
- 如何确保在使用基于布尔值的两个方法之一调用方法时避免分支预测错误
- 停止cmake target_link_libraries将插件中静态库的两个对象文件链接到静态库本身
- 将fold表达式与std::一起用于两个元组
- 如何在C++中比较两个char数组
- 给定两个偶数,求出它们之间所有偶数的平方和
- 比较两个大小不等的映射c++
- C++需要帮助从用户那里获得一个整数,并确保它在另外两个整数之间
- 如何在for循环中包含两个索引值的测试条件
- 如何在OpenCV中比较两个组关键点
- 基于关键点组合两个贴图的值