opencv--特征点

来源:互联网 发布:电视视频通话软件 编辑:程序博客网 时间:2024/05/21 10:59

一:特征点的理解

特征点是图像中与周围领域灰度值像素的暗点或亮点

二:特征点的寻找

 CV_WRAP void detect( const Mat& image, CV_OUT vector<KeyPoint>& keypoints, const Mat& mask=Mat() ) const;

SIFT对象的detect函数可以寻找特征点

第一个参数是输入图像

第二个参数是keyPoint类的向量

第三个是掩码(可选选项)


CV_EXPORTS_W void drawKeypoints( const Mat& image, const vector<KeyPoint>& keypoints, CV_OUT Mat& outImage,const Scalar& color=Scalar::all(-1), int flags=DrawMatchesFlags::DEFAULT );

特征点绘制函数drawKeypoints可以把上一步寻找到的特征点绘制出来

第一个参数是输入的含特征点图像

第二个参数是找到的特征点

第三个参数是绘制完后的输出图像

第四个参数是颜色Scalar::all(-1)指的是随机颜色

第五个参数是绘制特征点的关键符,默认参数DEFAULT 指的是绘制出所有特征点,


代码

#include "opencv2/opencv.hpp"
#include "opencv2/nonfree/nonfree.hpp"//因为sift在nonfree里面
#include "vector"
#include "iostream"


using namespace cv;
using namespace std;




void main()
{
Mat srcImage1=imread("00.jpg");
Mat srcImage2=imread("01.jpg");
imshow("srcImage1",srcImage1);
imshow("srcImage2",srcImage2);
//宏定义feature为SIFT类对象
SIFT featuredector1;
SIFT featuredector2;
//定义keypoint类的向量
vector<KeyPoint>KeyPoint1;
vector<KeyPoint>KeyPoint2;
//用SIFT类的detect方法来寻找关键点
featuredector1.detect(srcImage1,KeyPoint1);
featuredector2.detect(srcImage2,KeyPoint2);
Mat pic1;
Mat pic2;
//用drawkeyPoint函数绘制关键点
drawKeypoints(srcImage1,KeyPoint1,pic1,Scalar::all(-1));
drawKeypoints(srcImage2,KeyPoint2,pic2,Scalar::all(-1));
imshow("pic1",pic1);
imshow("pic2",pic2);
waitKey(0);
}


三:特征点匹配

1.在完成上一步的特征点提取后要把提取后的vector向量类的特征点转变为Mat类的描述子

调用SIFT类的成员函数compute来获得Mat矩阵类的描述子

2.在获得描述子后要对描述子进行匹配

调用的是DMatch类matcher对象的成员函数match

那么在调用match之前需要明确matcher对象的匹配器类型BruteForceMatcher<L2<float>>matcher;

3.通过match函数获得匹配结果DMacher类的vector向量后需要对所获得的结果进行筛选

筛选方法有2种,一种是通过欧式距离matches.at(i).distance来获取,并设置阈值

另一种是通过std::nth_element(matches.begin(),matches.begin()+19,matches.end());//对matches进行排序,以操作符<进行排序,及前面的都比19小后面都比19大

该函数的作用为将迭代器指向的从_First 到 _last 之间的元素进行二分排序,以_Nth 为分界,前面都比 _Nth 小(大),后面都比之大(小)
matches.erase(matches.begin()+20,matches.end());//擦除剩余的匹配点(由于距离越小越精确,所以把后面大的擦除)

4.最后通过drawMatches(srcImage1,KeyPoint1,srcImage2,KeyPoint2,matches,result);函数来绘制匹配结果

drawMatches函数的第一个参数是要检测的第一张原图

第二个参数是在第一张图上的特征点

第三个参数是要检测的第二张原图

第四个参数是在第二张图上的特征点

第五个参数是两幅图描述子匹配结果

第六个参数是输出图像

第七个参数是绘制颜色


代码

#include "opencv2/opencv.hpp"
#include "opencv2/nonfree/nonfree.hpp"//因为sift在nonfree里面
#include "opencv2/legacy/legacy.hpp"//暴力匹配Brute-force的头文件
#include "vector"
#include "iostream"


using namespace cv;
using namespace std;




void main()
{
Mat srcImage1=imread("11.jpg");
Mat srcImage2=imread("22.jpg");
imshow("srcImage1",srcImage1);
imshow("srcImage2",srcImage2);
//宏定义feature为SIFT类对象
SIFT featuredector1;
SIFT featuredector2;
//定义keypoint类的向量
vector<KeyPoint>KeyPoint1;
vector<KeyPoint>KeyPoint2;
//用SIFT类的detect方法来寻找关键点
featuredector1.detect(srcImage1,KeyPoint1);
featuredector2.detect(srcImage2,KeyPoint2);
Mat pic1;
Mat pic2;
//用drawkeyPoint函数绘制关键点
drawKeypoints(srcImage1,KeyPoint1,pic1,Scalar::all(-1));
drawKeypoints(srcImage2,KeyPoint2,pic2,Scalar::all(-1));
imshow("pic1",pic1);
imshow("pic2",pic2);
//定义Mat类的描述子
Mat descriptor1;
Mat descriptor2;
featuredector1.compute(srcImage1,KeyPoint1,descriptor1);//用SIFT的成员函数compute实现vetor向Mat描述子的转变
featuredector2.compute(srcImage2,KeyPoint2,descriptor2);
BruteForceMatcher<L2<float>>matcher;//定义暴力匹配器,别名为matcher,L2适用于SIFT,SUFT,float由于matcher里面的数据是float
vector<DMatch>matches;//定义DMacher类的vector向量,用于保存匹配结果
matcher.match(descriptor1,descriptor2,matches);
std::nth_element(matches.begin(),matches.begin()+19,matches.end());//获取最佳的20个匹配结果
matches.erase(matches.begin()+20,matches.end());//擦除剩余的匹配点
Mat result;
drawMatches(srcImage1,KeyPoint1,srcImage2,KeyPoint2,matches,result);
imshow("result",result);

waitKey(0);
}


原创粉丝点击