FLANN_Based SURF特征匹配

官网教程

介绍

FLANN(Fast Library for Approximate Nearest Neighbors)在一个描述符集合(询问集)中找另一个集合(相当于训练集)的最近邻。



例子

#include <iostream>
#include <vector>
 
#include <opencv2/xfeatures2d.hpp>
#include <opencv2/opencv.hpp>
 
using namespace cv;
using namespace std;
using namespace cv::xfeatures2d;
 
int main()
{

    Mat img1 = imread("../res/box.png", cv::IMREAD_GRAYSCALE);
    Mat img2 = imread("../res/box_in_scene.png", cv::IMREAD_GRAYSCALE);
    if(img1.empty()||img2.empty())
    {
	cout << "can't load image" << endl;
	return -1;
    }

//计算 keypoints and descriptor
    int minHessian = 400;
    Ptr<SURF> detector = SURF::create(minHessian);
    std::vector<KeyPoint> keypoint1, keypoint2;
    Mat descriptor1, descriptor2;
    detector->detectAndCompute(img1, noArray(), keypoint1, descriptor1);
    detector->detectAndCompute(img2, noArray(), keypoint2, descriptor2);


//匹配
    Ptr<cv::DescriptorMatcher> matcher = DescriptorMatcher::create(DescriptorMatcher::FLANNBASED); // 基于FLANN匹配
    vector<std::vector<DMatch>> knn_matches; // 因为要为每个descriptor找到最佳的k 个匹配, 对于每个descriptor来说,又是vector<DMatch>
    matcher->knnMatch(descriptor1, descriptor2, knn_matches, 2);


//筛选最好的
    const float ratio_thresh = 0.7f;
    vector<DMatch> good_matchers;
    for(int i=0; i<knn_matches.size(); i++)
    {
	if(knn_matches[i][0].distance < ratio_thresh*knn_matches[i][1].distance)// 最佳匹配距离/第二佳的匹配距离 < 0.7 
	{
	    good_matchers.push_back(knn_matches[i][0]); // 满足以上条件,最佳匹配才是我们需要的
	}
    }


//展示
    Mat img_matchers;
    drawMatches(img1, keypoint1, img2, keypoint2, good_matchers, img_matchers, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);


    imshow("Good Matchers", img_matchers);

    waitKey();
    return 0;
}

FLANN_Based SURF特征匹配



OpenCV API

  1. 画特征点、匹配( feature2d.hpp )

void cv::drawKeypoints

( 	
		InputArray  	image,     // source image
		const std::vector< KeyPoint > &  	keypoints, // KeyPoints from the source image
		InputOutputArray  	outImage,    // 输出图像
		const Scalar &  	color = Scalar::all(-1),  // color for keypoints ,default (-1)随机
		DrawMatchesFlags  	flags = DrawMatchesFlags::DEFAULT //画图的方式,默认就行, 或者NOT_DRAW_SINGLE_POINTS:没有匹配的点不画出来
) 	

void cv::drawMatches

( 	
		InputArray  	img1,   //first source image
		const std::vector< KeyPoint > &  	keypoints1, //Keypoints from the first source image. 
		InputArray  	img2,   // Second source image. 
		const std::vector< KeyPoint > &  	keypoints2,  // 	Keypoints from the second source image. 
		const std::vector< DMatch > &  	matches1to2,  // 两源图之间的匹配
		InputOutputArray  	outImg,  //输出图像
		const Scalar &  	matchColor = Scalar::all(-1),  // 随机颜色
		const Scalar &  	singlePointColor = Scalar::all(-1), // 没有匹配的点的颜色
		const std::vector< char > &  	matchesMask = std::vector< char >(), //	Mask决定哪些点画,如果为空,全都画
		DrawMatchesFlags  	flags = DrawMatchesFlags::DEFAULT  //画图方式,如上API
) 	



  1. 从候选匹配中,为每个匹配找到最佳的k个匹配

void cv::DescriptorMatcher::knnMatch

( 	
		InputArray  	queryDescriptors, // 第一张图片的匹配
		InputArray  	trainDescriptors, // 第二张图片的匹配
		std::vector< std::vector< DMatch > > &  	matches, // 存的匹配结果
		int  	k,  // 前k个最佳匹配,
		InputArray  	mask = noArray(),
		bool  	compactResult = false 
) const