一,FlannBasedMatcher类的简单分析
在 OpenCV源代码中,找到FlannBasedMatcher类的脉络如下。
可以发现 FlannBasedMatcher类也是继承自 DescriptorMatcher,并且同样主要使用来自 DescriptorMatcher类的match方法进行匹配。下面,让我们讲解一下此类方法的用法。
二,找到最佳匹配:DescriptorMatcher::match方法
DescriptorMatcher:.match()函数从每个描述符查询集中找到最佳匹配,有两个版本的源码,下面用注释对其进行讲解。
三,示例程序:使用FLANN进行特征点匹配
#include
#include
#include
#include
using namespace cv;
using namespace std;
using namespace cv::xfeatures2d;
//检测计算和绘制时,源图(img1)在前面,目标图像(img2)在后面
Mat img1, img2;
int main(int argc, char** argv)
{
img1 = imread("E:/pictures/2.jpg", 0);
img2 = imread("E:/pictures/3.2.jpg", 0);
if (!img1.data || !img2.data)
{
cout << "图片为空!" << endl;
return -1;
}
int minHesssion = 400;
Ptr detector = SURF::create(minHesssion); //也可以用SIRF,但是效率比SURF低
vector keypoints_obj; //存放img1的特征值
vector keypoints_scene; //存放img2的特征值
Mat descript_obj, descript_scene;
detector->detectAndCompute(img1, Mat(), keypoints_obj, descript_obj); //检测并计算特征描述子
detector->detectAndCompute(img2, Mat(), keypoints_scene, descript_scene);
FlannBasedMatcher fbmatcher;
vectormatches;
fbmatcher.match(descript_obj, descript_scene, matches); //特征描述子匹配
//找出最优特征点
double minDist = 1000; //初始化最大最小距离
double maxDist = 0;
for (int i = 0; i < descript_obj.rows; i++)
{
double dist = matches[i].distance;
if (dist > maxDist)
{
maxDist = dist;
}
if (dist < minDist)
{
minDist = dist;
}
}
printf("maxDist:%f\n", maxDist);
printf("minDist:%f\n", minDist);
vector goodMatches;
for (int i = 0; i < descript_obj.rows; i++)
{
double dist = matches[i].distance;
if (dist < max(2 * minDist, 0.02)) {
goodMatches.push_back(matches[i]);
}
}
Mat resultImg;
drawMatches(img1, keypoints_obj, img2, keypoints_scene, goodMatches, resultImg, Scalar::all(-1),
Scalar::all(-1), vector(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS
);
imshow("input image1", img1);
imshow("input image2", img2);
imshow("FlannBasedMatcher demo", resultImg);
waitKey(0);
return 0;
}
四,综合示例程序:FLANN结合SURF进行关键点的描述和匹配
#include
#include
#include
#include
#include
using namespace std;
using namespace cv;
using namespace cv::xfeatures2d;
int main()
{
Mat trainImage = imread("E:/pictures/2.jpg", 1);
Mat trainImage_gray;
imshow("原始图", trainImage);
cvtColor(trainImage, trainImage_gray, CV_BGR2GRAY);
vectortrain_keypoint;
Mat trainDescriptor;
Ptr Detector = SurfFeatureDetector::create(80);
Detector->detectAndCompute(trainImage_gray, Mat(), train_keypoint, trainDescriptor);
vector train_desc_collection(1, trainDescriptor);
FlannBasedMatcher matcher;
matcher.add(train_desc_collection);
matcher.train();
VideoCapture cap(0);
unsigned int frameCount = 0;
while (char(waitKey(1) != 'q'))
{
int64 time0 = getTickCount();
Mat testImage, testImage_gray;
cap >> testImage;
if (testImage.empty())
continue;
cvtColor(testImage, testImage_gray, CV_BGR2GRAY);
vectortest_keypoint;
Mat testDescriptor;
Detector->detectAndCompute(testImage_gray, Mat(), test_keypoint, testDescriptor);
vector>matches;
matcher.knnMatch(testDescriptor, matches, 2);
vectorgoodMatches;
for (unsigned int i = 0; i < matches.size(); i++)
{
if (matches[i][0].distance < 0.6 * matches[i][1].distance)
goodMatches.push_back(matches[i][0]);
}
Mat dstImage;
drawMatches(testImage, test_keypoint, trainImage, train_keypoint, goodMatches, dstImage);
imshow("匹配窗口", dstImage);
cout << "当前帧率为" << getTickFrequency() / (getTickCount() - time0) << endl;
}
return 0;
}
五,综合示例程序:SIFT配合暴力匹配进行关键点描述和提取
#include
#include
#include
#include
using namespace std;
using namespace cv;
int main()
{
Mat trainImage = imread("E:/pictures/2.jpg"), trainImage_gray;
//imshow("trainImage", trainImage);
cvtColor(trainImage, trainImage_gray, COLOR_BGR2GRAY);
vectortrain_keyPoint;
Mat trainDescription;
//SiftFeatureDetector featureDetector;
//featureDetector.detect(trainImage_gray, train_keyPoint);
Ptr featureDetector = xfeatures2d::SiftFeatureDetector::create();
featureDetector->detect(trainImage_gray, train_keyPoint);
Ptr featureExtractor = xfeatures2d::SiftDescriptorExtractor::create();
featureExtractor->compute(trainImage_gray, train_keyPoint, trainDescription);
BFMatcher matcher;
vectortrain_desc_collection(1, trainDescription);
matcher.add(train_desc_collection);
matcher.train();
Mat captureImage, captureImage_gray;
captureImage = imread("D:/script/myGit/autojs-flann-feature-matching/图片素材/game001_女生头像.png");
cvtColor(captureImage, captureImage_gray, COLOR_BGR2GRAY);
vectortest_keyPoint;
Mat testDescriptor;
featureDetector->detect(captureImage_gray, test_keyPoint);
featureExtractor->compute(captureImage_gray, test_keyPoint, testDescriptor);
vector>matches;
matcher.knnMatch(testDescriptor, matches, 2);
vectorgoodMatches;
for (unsigned int i = 0; i < matches.size(); i++)
{
if (matches[i][0].distance < 0.6 * matches[i][1].distance)
goodMatches.push_back(matches[i][0]);
}
Mat dstImage;
drawMatches(captureImage, test_keyPoint, trainImage, train_keyPoint, goodMatches, dstImage);
imshow("dstImage", dstImage);
cv::waitKey(0);
return 0;
}