OpenCV中提取SIFT特征点、图像匹配、图像配准
来源:互联网 发布:导入数据load from 编辑:程序博客网 时间:2024/05/21 15:43
在实际中提取图像的sift特征点,再对特征点做匹配,形成特征点对,最后计算图像变换的矩阵,一般为单应矩阵,再利用单应矩阵进行图像的配准,现在基于OpenCV实现相关的算法和步骤,具体代码和主要的函数讲解如下。
一、代码如下:
#include<iostream>#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/features2d/features2d.hpp>#include <opencv2/nonfree/nonfree.hpp>#include "opencv2/calib3d/calib3d.hpp"#include <highgui.h> #include <cv.h> #include<vector>#include<cmath>#define PI 3.14159265358979323846264338327950288419716939937510582097using namespace std;using namespace cv;void main(){ //读取原始基准图和待匹配图 Mat srcImg1 = imread("1.JPG"); //待配准图 Mat srcImg2 = imread("2.JPG"); //基准图 //显示基准和待配准图 imshow("待配准图", srcImg1); imshow("基准图", srcImg2); //定义SIFT特征检测类对象 SiftFeatureDetector siftDetector1; SiftFeatureDetector siftDetector2; //定义KeyPoint变量 vector<KeyPoint>keyPoints1; vector<KeyPoint>keyPoints2; //特征点检测 siftDetector1.detect(srcImg1, keyPoints1); siftDetector2.detect(srcImg2, keyPoints2); //绘制特征点(关键点) Mat feature_pic1, feature_pic2; drawKeypoints(srcImg1, keyPoints1, feature_pic1, Scalar::all(-1)); drawKeypoints(srcImg2, keyPoints2, feature_pic2, Scalar::all(-1)); drawKeypoints(srcImg1, keyPoints1, feature_pic1, Scalar(0, 255, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS); drawKeypoints(srcImg2, keyPoints2, feature_pic2, Scalar(0, 255, 0), DrawMatchesFlags::DRAW_RICH_KEYPOINTS); //显示原图 //显示结果 imshow("feature1", feature_pic1); imshow("feature2", feature_pic2); //计算特征点描述符 / 特征向量提取 SiftDescriptorExtractor descriptor; Mat description1; descriptor.compute(srcImg1, keyPoints1, description1); Mat description2; descriptor.compute(srcImg2, keyPoints2, description2); cout << keyPoints1.size() << endl; cout << description1.cols << endl; //列数 cout << description1.rows << endl; //行数 //进行BFMatch暴力匹配 //BruteForceMatcher<L2<float>>matcher; //实例化暴力匹配器 FlannBasedMatcher matcher; //实例化FLANN匹配器 vector<DMatch>matches; //定义匹配结果变量 matcher.match(description1, description2, matches); //实现描述符之间的匹配 //中间变量 int i,j,k;double sum=0;double b; double max_dist = 0; double min_dist = 100; for(int i=0; i<matches.size(); i++) { double dist = matches[i].distance; if(dist < min_dist) min_dist = dist; if(dist > max_dist) max_dist = dist; } cout<<"最大距离:"<<max_dist<<endl; cout<<"最小距离:"<<min_dist<<endl; //筛选出较好的匹配点 vector<DMatch> good_matches; double dThreshold = 0.5; //匹配的阈值,越大匹配的点数越多 for(int i=0; i<matches.size(); i++) { if(matches[i].distance < dThreshold * max_dist) { good_matches.push_back(matches[i]); } } //RANSAC 消除误匹配特征点 主要分为三个部分: //1)根据matches将特征点对齐,将坐标转换为float类型 //2)使用求基础矩阵方法findFundamentalMat,得到RansacStatus //3)根据RansacStatus来将误匹配的点也即RansacStatus[i]=0的点删除 //根据matches将特征点对齐,将坐标转换为float类型 vector<KeyPoint> R_keypoint01,R_keypoint02; for (i=0;i<good_matches.size();i++) { R_keypoint01.push_back(keyPoints1[good_matches[i].queryIdx]); R_keypoint02.push_back(keyPoints2[good_matches[i].trainIdx]); // 这两句话的理解:R_keypoint1是要存储img01中能与img02匹配的特征点, // matches中存储了这些匹配点对的img01和img02的索引值 } //坐标转换 vector<Point2f>p01,p02; for (i=0;i<good_matches.size();i++) { p01.push_back(R_keypoint01[i].pt); p02.push_back(R_keypoint02[i].pt); } //计算基础矩阵并剔除误匹配点 vector<uchar> RansacStatus; Mat Fundamental= findHomography(p01,p02,RansacStatus,CV_RANSAC); Mat dst; warpPerspective(srcImg1, dst, Fundamental,Size(srcImg1.cols,srcImg1.rows)); imshow("配准后的图",dst ); imwrite("dst.jpg", dst); //剔除误匹配的点对 vector<KeyPoint> RR_keypoint01,RR_keypoint02; vector<DMatch> RR_matches; //重新定义RR_keypoint 和RR_matches来存储新的关键点和匹配矩阵 int index=0; for (i=0;i<good_matches.size();i++) { if (RansacStatus[i]!=0) { RR_keypoint01.push_back(R_keypoint01[i]); RR_keypoint02.push_back(R_keypoint02[i]); good_matches[i].queryIdx=index; good_matches[i].trainIdx=index; RR_matches.push_back(good_matches[i]); index++; } } cout<<"找到的特征点对:"<<RR_matches.size()<<endl; //画出消除误匹配后的图 Mat img_RR_matches; drawMatches(srcImg1,RR_keypoint01,srcImg2,RR_keypoint02,RR_matches,img_RR_matches, Scalar(0, 255, 0), Scalar::all(-1)); imshow("消除误匹配点后",img_RR_matches); imwrite("匹配图.jpg", img_RR_matches); waitKey(0);}
二、主要函数解释:
1、findHomography函数:根据匹配点对坐标对的值,和RANSAC随机一致性算法剔除误匹配点对,并计算两幅图的单应矩阵。
主要参数:参数1–待配准图中特征点坐标向量,
参数2–基准图像中特征点坐标向量;
返回值–计算出的3*3的单应矩阵的值,该矩阵即代表两幅图的变换关系
注意:这个函数计算处单应矩阵,最少需要4对成功的匹配点对。
2、warpPerspective函数:根据单应矩阵,对待配准的图像进行重采样,计算配准后的图。
主要参数:参数1–待配准图类对象,
参数2–待匹配图根据单应矩阵变换后的输出图像类对象;
参数3–单应矩阵;
参数4–输出图像类对象的大小,即输出图像的高度和宽度;
返回值–计算出的3*3的单应矩阵的值,该矩阵即代表两幅图的变换关系
三、算法运行效果:
运行效果:从待匹配图到匹配后的图,图像发生了一定的旋转,同时向基准图像靠拢了。
0 1
- OpenCV中提取SIFT特征点、图像匹配、图像配准
- 【OpenCV】SIFT特征检测器进行图像匹配
- 基于opencv的图像拼接(一): sift特征点提取
- 基于SIFT点特征匹配的图像配准MATLAB程序
- 基于SIFT点特征匹配的图像配准MATLAB程序
- 基于SIFT点特征匹配的图像配准MATLAB程序
- sift图像特征提取与匹配算法代码
- sift图像特征提取与匹配算法代码
- 图像特征提取与匹配之SIFT算法
- 图像特征提取与匹配之SIFT算法
- 图像特征提取与匹配之SIFT算法
- Opencv实现图像无缝拼接,Sift查找特征点,Flann进行匹配
- Opencv下利用SIFT、SURF、ORB三种特征点实现图像匹配
- Opencv实现图像无缝拼接,Sift查找特征点,Flann进行匹配
- Opencv实现:SIFT特征提取+RANSAC剔除误匹配点
- Opencv实现:SIFT特征提取+RANSAC剔除误匹配点
- OpenCV-基于特征点的图像匹配
- 《Master Opencv...读书笔记》图像特征点匹配
- 解决mysql数据库因过多错误链接导致拒绝访问的问题
- yuiCompressor linux批量压缩js、css
- Condition 很好的例子
- Spring3.x升级到Spring.x4时, 找不到MappingJacksonHttpMessageConverter的异常
- java 工厂模式
- OpenCV中提取SIFT特征点、图像匹配、图像配准
- 机器学习笔记(四)经验误差与过拟合
- android-每次进入Activity控制横竖屏幕的情况
- spring-mvc 抓取视图报错:No mapping found for HTTP
- ios 常用的30个动画效果
- Spring MyBatis多数据源(同包)
- pyasn1模块缺失解决
- 算法导论 练习题 13.1-4
- Spring速查手册(三)——Spring+JDBC