- 导入必要的头文件和库,包括opencv。
- 读取两张图像作为输入。
- 创建SIFT特征检测器对象并设置参数,例如特征点数目。
- 对每张图像进行特征检测和特征描述符计算。
- 使用FLANN(快速最近邻)匹配器进行特征点匹配。
- 使用KNN-NNDR(K最近邻和最近邻距离比率)匹配方法找到特征点的匹配对。
- 绘制匹配结果,并显示在窗口中。
// SIFT 尺度不变特征转换(Scale Invariant Feature Transform)
// SIFT算法不仅只有尺度不变性,当旋转图像,改变图像亮度,移动拍摄位置时,仍可得到较好的检测效果.
// 图像高斯金字塔 图像高斯金字塔考虑了这两个方面:① 图像的远近程度;② 图像的模糊程度 采样法 高斯核对图像进行平滑处理 https://zhuanlan.zhihu.com/p/343522892
int i;
Mat img[2];
img[0] = imread("E:/study/cv/计算机视觉/imgMain/lena.jpg");
img[1] = imread("E:/study/cv/计算机视觉/imgMain/lena_copy.jpg");
if (img[0].empty() || img[1].empty())
return 0;
Ptr<SiftFeatureDetector> sift = SiftFeatureDetector::create(100);
std::vector<KeyPoint> keyPoints[2];
Mat descriptors[2];
for (i = 0; i < 2; i++) {
// 计算特征点
sift->detect(img[i], keyPoints[i]);
// 计算特征描述符
sift->compute(img[i], keyPoints[i], descriptors[i]);
// 绘制KeyPoints
drawKeypoints(img[i], keyPoints[i], img[i]);
}
// 特征匹配:Flann-based matcher 使用快速近似最近邻搜索算法寻找 当我们需要找到一个相对好的匹配但是不需要最佳匹配的时候往往使用FlannBasedMatcher
cv::Ptr<cv::DescriptorMatcher> matcher = cv::DescriptorMatcher::create(cv::DescriptorMatcher::FLANNBASED);
// KNN-NNDR匹配法
// KNN:K最邻近。如果一个样本在特征空间中的K个最相似(即特征空间中最邻近)的样本中大多数属于某一个类别,则该样本叶属于这个类别
// NNDR:最近邻距离比率。最近邻距离和次近邻距离的比值
std::vector<std::vector<cv::DMatch>> knn_matches;
const float ratio_thresh = 0.7f;
std::vector<cv::DMatch> good_matches;
matcher->knnMatch(descriptors[0], descriptors[0], knn_matches, 2);
for (auto& knn_matche : knn_matches)
{
if (knn_matche[0].distance<ratio_thresh * knn_matche[1].distance)
good_matches.push_back(knn_matche[0]);
}
// 最匹配图
cv::Mat img_matches_knn;
drawMatches(img[0], keyPoints[0], img[1], keyPoints[1], good_matches, img_matches_knn, cv::Scalar::all(-1),
cv::Scalar::all(-1), std::vector<char>(), cv::DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
cv::imshow("knn_matches", img_matches_knn);
waitKey();
SiftFeatureDetector::create(100)
:创建SIFT特征检测器对象,参数100表示预期检测到的特征点数目。sift->detect(img[i], keyPoints[i])
:对图像进行SIFT特征检测,提取关键点。sift->compute(img[i], keyPoints[i], descriptors[i])
:计算关键点的描述符,描述了每个关键点周围的局部特征信息。cv::DescriptorMatcher::create(cv::DescriptorMatcher::FLANNBASED)
:创建FLANN(快速最近邻)匹配器。matcher->knnMatch(descriptors[0], descriptors[0], knn_matches, 2)
:使用KNN(K最近邻)算法进行特征点匹配,得到每个特征点的两个最佳匹配。if (knn_matche[0].distance<ratio_thresh * knn_matche[1].distance)
:通过比较最近邻距离和次近邻距离的比值来筛选出优秀的匹配点对。drawMatches
:绘制特征点匹配结果。