学更好的别人,
做更好的自己。
——《微卡智享》
本文长度为2739字,预计阅读6分钟
前言
关于SIFT的特征点检测在《C OpenCV特征提取之SIFT特征检测》有介绍过,在OpenCV4.5版本中SIFT做是算法优化,也移到主仓库中了,并且有朋友也留言问了4.5版本下的DEMO。
所以这篇就做一下OpenCV4.5版本的SIFT特征点检测及匹配。
实现效果
两张原图
匹配的效果
代码实现
微卡智享
# | 实现流程 |
---|---|
1 | 定义检测的特征点个数,用SIFT进行特征检测 |
2 | 对检测完的两个图做特征向量的提取 |
3 | 使用BFMatch进行匹配,筛选出好的结果 |
4 | 画出匹配的特征点 |
01
SIFT特征检测
以前版本中使用SIFT需要引入xfeatures2d.hpp,而现在就不用了。
旧版本
新版本
02
特征向量的提取
接下来就是计算特征点描述符,特征向量的提取
特征向量提取
03
使用BFMatch匹配
提取完特征向量后,对两个特征向量进行匹配,然后通过匹配的结果计算出向量的最大和最小距离。
特征匹配及计算最大最小距离
04
筛选好的匹配结果
最后就是根据最大最小的距离,从匹配的点中筛选出好的结果,再展示出来。
筛选结果绘制图像
完整代码
代码语言:javascript复制#include<iostream>
#include<opencv2/opencv.hpp>
#include"CvUtils.h"
using namespace std;
using namespace cv;
int main(int argc, char** argv) {
Mat src = imread("E:/DCIM/hrd/h1.jpg");
CvUtils::MatResize(src);
CvUtils::SetShowWindow(src, "src", 10, 20);
imshow("src", src);
Mat src2 = imread("E:/DCIM/hrd/h3.jpg");
CvUtils::MatResize(src2);
CvUtils::SetShowWindow(src2, "src2", 300, 20);
imshow("src2", src2);
//定义Sift的基本参数
int numFeatures = 500;
//创建detector存放到KeyPoints中
Ptr<SIFT> detector = SIFT::create(numFeatures);
vector<KeyPoint> keypoints, keypoints2;
detector->detect(src, keypoints);
detector->detect(src2, keypoints2);
//打印Keypoints
cout << "Keypoints:" << keypoints.size() << endl;
cout << "Keypoints2:" << keypoints2.size() << endl;
Mat drawsrc, drawsrc2;
drawKeypoints(src, keypoints, drawsrc);
CvUtils::SetShowWindow(drawsrc, "drawsrc", 10, 20);
imshow("drawsrc", drawsrc);
drawKeypoints(src2, keypoints2, drawsrc2);
CvUtils::SetShowWindow(drawsrc2, "drawsrc2", 300, 20);
imshow("drawsrc2", drawsrc2);
//计算特征点描述符,特征向量提取
Mat dstSIFT, dstSIFT2;
Ptr<SiftDescriptorExtractor> descriptor = SiftDescriptorExtractor::create();
descriptor->compute(src, keypoints, dstSIFT);
descriptor->compute(src2, keypoints2, dstSIFT2);
cout << dstSIFT.cols << endl;
cout << dstSIFT2.rows << endl;
//进行BFMatch暴力匹配
BFMatcher matcher(NORM_L2);
//定义匹配结果变量
vector<DMatch> matches;
//实现描述符之间的匹配
matcher.match(dstSIFT, dstSIFT2, matches);
//定义向量距离的最大值与最小值
double max_dist = 0;
double min_dist = 1000;
for (int i = 1; i < dstSIFT.rows; i)
{
//通过循环更新距离,距离越小越匹配
double dist = matches[i].distance;
if (dist > max_dist)
max_dist = dist;
if (dist < min_dist)
min_dist = dist;
}
cout << "min_dist=" << min_dist << endl;
cout << "max_dist=" << max_dist << endl;
//匹配结果筛选
vector<DMatch> goodMatches;
for (int i = 0; i < matches.size(); i)
{
double dist = matches[i].distance;
if (dist < 2 * min_dist)
goodMatches.push_back(matches[i]);
}
cout << "goodMatches:" << goodMatches.size() << endl;
Mat result;
//匹配特征点天蓝色,单一特征点颜色随机
drawMatches(src, keypoints, src2, keypoints2, goodMatches, result,
Scalar(255, 255, 0), Scalar::all(-1));
CvUtils::SetShowWindow(result, "Result", 100, 20);
imshow("Result", result);
waitKey(0);
return 0;
}
源码地址
https://github.com/Vaccae/OpenCVDemoCpp.git
这个Demo我也整合到OpenCV练习Demo中了,GitHub上不去的朋友,可以击下方的原文链接跳转到码云的地址,关注【微卡智享】公众号,回复【源码】可以下载我的所有开源项目。