SURF 特征匹配
参考:http://www.cnblogs.com/ronny/p/4045979.html,博主对源码进行了分析,不过很多没看明白。
分为几个部分。积分图:借助积分图像,图像与高斯二阶微分模板的滤波转化为对积分图像的加减运算。在哈尔特征中也用到这个。
DoH近似:将模板与图产像的卷积转换为盒子滤波运算,我们需要对高斯二阶微分模板进行简化,进而对Hessian矩阵行列式的值进行简化。使用近似的Hessian矩阵行列式的极大值检测斑点,
使用近似的Hessian矩阵行列式来表示图像中某一点x处的斑点响应值,遍历图像中所有的像元点, 便形成了在某一尺度下琉璃点检测的响应图像。
使用不同的模板尺寸,便形成了多尺度斑点响应的金字塔图像,利用这一金字塔图像,就可以进行斑点响应极值点的搜 索,其过程完全与SIFT算法类同。
尺度空间表示:通常想要获取不同尺度的斑点,必须建立图像的尺度空间金字塔。由于采用了盒子滤波和积分图像,并不需要像SIFT算法那样去直接建立图像金字塔,
而是采用不断增大盒子滤波模板的尺寸的间接方法。
兴趣点的定位:为了在图像及不同尺寸中定位兴趣点,我们用了3×3×3邻域非最大值抑制。
这篇博文说得很详细:http://www.cnblogs.com/wangguchangqing/p/4333873.html
关于BFMatcher和FlannBasedMatcher,可参考:http://m.blog.csdn.net/blog/u012564690/40926315
#include <stdio.h> #include <iostream> #include "opencv2/core/core.hpp"//因为在属性中已经配置了opencv等目录,所以把其当成了本地目录一样 #include <opencv2/nonfree/features2d.hpp> #include "opencv2/highgui/highgui.hpp" #include<opencv2/legacy/legacy.hpp> /*这里用的是图像对图像集,注意FLANN的用法*/ using namespace cv; using namespace std; int main() { Mat trainImage = imread("1.jpg"), trainImage_gray; cvtColor(trainImage, trainImage_gray, CV_BGR2GRAY); vector<KeyPoint> train_keypoint; Mat trainDescriptor; SurfFeatureDetector featureDector(80);//80是什么? featureDector.detect(trainImage_gray, train_keypoint); SurfDescriptorExtractor featureExtractor; featureExtractor.compute(trainImage_gray, train_keypoint, trainDescriptor); //创建基于FLANN的描述符匹配对象 FlannBasedMatcher matcher; vector<Mat> train_desc_collection(1, trainDescriptor);//两个参数是什么 matcher.add(train_desc_collection);//这两句什么意思 matcher.train(); VideoCapture cap("test.avi"); 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); vector<KeyPoint> test_keyPoint; Mat testDescriptor; featureDector.detect(testIMage_gray, test_keyPoint); featureExtractor.compute(testIMage_gray, test_keyPoint, testDescriptor); vector<vector<DMatch>> matches; matcher.knnMatch(testDescriptor, matches, 2);//对每个匹配,返回两个最近邻匹配 vector<DMatch> goodMatches; for (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 << cvGetTickFrequency() / (getTickCount() - time0) << endl; } waitKey(0); return 0; }