概述
描述并匹配局部轻度值模式
本节的主要内容是使用特征描述子来描述兴趣点的邻域。
- 特征描述子通常是一个 N 维的向量,在光照变化和拍摄角度发生微小扭曲时,它描述特征点的方式不会发生变化。通常可以用简单的差值矩阵来比较描述子,例如用欧几里得距离。综上所述,特征描述子是一种非常强大的工具,能进行目标的匹配。
示例程序
#include <iostream>
#include <algorithm>
#include <vector>
#include <opencv2/core/core.hpp>
#include </home/jlm/3rdparty/opencv/opencv_contrib/modules/xfeatures2d/include/opencv2/xfeatures2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
int main(int argc, char** argv) {
if(argc != 3)
{
cerr << "don't get the right numbers of image" << endl;
return -1;
}
cv::Mat image1 = cv::imread(argv[1],cv::IMREAD_GRAYSCALE);
cv::Mat image2 = cv::imread(argv[2],cv::IMREAD_GRAYSCALE);
if(image1.empty() || image2.empty())
{
cout << "don't get the data of the argv[1]" << endl;
return -1;
}
cv::imshow("Original1", image1);
cv::imshow("Original2", image2);
cv::waitKey(0);
// 定义关键点的容器
vector<cv::KeyPoint> keypoints1;
vector<cv::KeyPoint> keypoints2;
// 定义特征检测器
//对于 SIFT,调用 cv::SIFT::create 函数即可
cv::Ptr<cv::Feature2D> ptrFeature2D =
cv::xfeatures2d::SURF::create(2000.0);
// 检测关键点
ptrFeature2D -> detect(image1,keypoints1);
ptrFeature2D -> detect(image2, keypoints2);
// 提取描述子
cv::Mat descriptors1;
cv::Mat descriptors2;
ptrFeature2D -> compute(image1, keypoints1, descriptors1);
ptrFeature2D -> compute(image2, keypoints2, descriptors2);
//
兴趣点描述子的计算结果是一个矩阵(即cv::Mat 实例)
//
,矩阵的行数等于关键点容器的元素个数。每行是一个 N 维的描述子容器。 SURF
//
描述子的默认尺寸是 64,而 SIFT 的默认尺寸是 128。这个容器用于区分特征点周围的强度值图
//
案。两个特征点越相似,它们的描述子容器就会越接近。注意, SURF 兴趣点并不一定要使用 SURF
//
描述子,SIFT 也一样;检测器和描述子可以任意搭配。
// 构造匹配器
//
将第一幅图像的每个特征
//
描述子向量与第二幅图像的全部特征描述子进行比较,把相似度最高的一对(即两个描述子向量
//
之间的距离最短)保留下来,作为最佳匹配项。
cv::BFMatcher matcher(cv::NORM_L2);
// 匹配两幅图像的描述子
vector<cv::DMatch> matches;
matcher.match(descriptors1,descriptors2,matches);
// 输出结果
cv::Mat outImage;
cv::drawMatches(image1, keypoints1,
image2, keypoints2,
matches,
outImage,
cv::Scalar(255, 255, 255),
cv::Scalar(255, 255, 255));
cv::imshow("OUT IMAGE", outImage);
cout << "the keypoints number of image1 : " << keypoints1.size() << endl;
cout << "the keypoints number of image2 : " << keypoints2.size() << endl;
cv::waitKey(0);
return 0;
}
其他容错算法
用任何算法得到的匹配结果都含有相当多的错误匹配项,但有一些策略可以提高匹配的质量。
交叉检查匹配项
cv::BFMatcher matcher(cv::NORM_L2,
true); // 将第二个参数设置位true
比率检验法
#include <iostream>
#include <algorithm>
#include <vector>
#include <opencv2/core/core.hpp>
#include </home/jlm/3rdparty/opencv/opencv_contrib/modules/xfeatures2d/include/opencv2/xfeatures2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
int main(int argc, char** argv) {
if(argc != 3)
{
cerr << "don't get the right numbers of image" << endl;
return -1;
}
cv::Mat image1 = cv::imread(argv[1],cv::IMREAD_GRAYSCALE);
cv::Mat image2 = cv::imread(argv[2],cv::IMREAD_GRAYSCALE);
if(image1.empty() || image2.empty())
{
cout << "don't get the data of the argv[1]" << endl;
return -1;
}
cv::imshow("Original1", image1);
cv::imshow("Original2", image2);
cv::waitKey(0);
// 定义关键点的容器
vector<cv::KeyPoint> keypoints1;
vector<cv::KeyPoint> keypoints2;
// 定义特征检测器
//对于 SIFT,调用 cv::SIFT::create 函数即可
cv::Ptr<cv::Feature2D> ptrFeature2D =
cv::xfeatures2d::SURF::create(2000.0);
// 检测关键点
ptrFeature2D -> detect(image1,keypoints1);
ptrFeature2D -> detect(image2, keypoints2);
// 提取描述子
cv::Mat descriptors1;
cv::Mat descriptors2;
ptrFeature2D -> compute(image1, keypoints1, descriptors1);
ptrFeature2D -> compute(image2, keypoints2, descriptors2);
//
兴趣点描述子的计算结果是一个矩阵(即cv::Mat 实例)
//
,矩阵的行数等于关键点容器的元素个数。每行是一个 N 维的描述子容器。 SURF
//
描述子的默认尺寸是 64,而 SIFT 的默认尺寸是 128。这个容器用于区分特征点周围的强度值图
//
案。两个特征点越相似,它们的描述子容器就会越接近。注意, SURF 兴趣点并不一定要使用 SURF
//
描述子,SIFT 也一样;检测器和描述子可以任意搭配。
// 构造匹配器
//
将第一幅图像的每个特征
//
描述子向量与第二幅图像的全部特征描述子进行比较,把相似度最高的一对(即两个描述子向量
//
之间的距离最短)保留下来,作为最佳匹配项。
cv::BFMatcher matcher(cv::NORM_L2);
vector<vector<cv::DMatch> > matches;
vector<cv::DMatch> newMatches;
matcher.knnMatch(descriptors1,descriptors2, matches, 2); // 找出k个最佳匹配项
// 执行比率检验法
double ratio = 0.85;
vector<vector<cv::DMatch> >::iterator it;
for (it = matches.begin(); it != matches.end(); ++it)
{
// 第一个最佳匹配项 / 第二个最佳匹配项
if((*it)[0].distance / (*it)[1].distance < ratio)
{
newMatches.push_back((*it)[0]);
}
}// newMatches是最新的匹配项集合
// 输出结果
cv::Mat outImage;
cv::drawMatches(image1, keypoints1,
image2, keypoints2,
newMatches,
outImage,
cv::Scalar(255, 255, 255),
cv::Scalar(255, 255, 255));
cv::imshow("OUT IMAGE", outImage);
cout << "the keypoints number of image1 : " << keypoints1.size() << endl;
cout << "the keypoints number of image2 : " << keypoints2.size() << endl;
cout << "the number of newMatches : " << newMatches.size() << endl;
cv::waitKey(0);
return 0;
}
匹配差值的阈值化
#include <iostream>
#include <algorithm>
#include <vector>
#include <opencv2/core/core.hpp>
#include </home/jlm/3rdparty/opencv/opencv_contrib/modules/xfeatures2d/include/opencv2/xfeatures2d.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace std;
int main(int argc, char** argv) {
if(argc != 3)
{
cerr << "don't get the right numbers of image" << endl;
return -1;
}
cv::Mat image1 = cv::imread(argv[1],cv::IMREAD_GRAYSCALE);
cv::Mat image2 = cv::imread(argv[2],cv::IMREAD_GRAYSCALE);
if(image1.empty() || image2.empty())
{
cout << "don't get the data of the argv[1]" << endl;
return -1;
}
cv::imshow("Original1", image1);
cv::imshow("Original2", image2);
cv::waitKey(0);
// 定义关键点的容器
vector<cv::KeyPoint> keypoints1;
vector<cv::KeyPoint> keypoints2;
// 定义特征检测器
//对于 SIFT,调用 cv::SIFT::create 函数即可
cv::Ptr<cv::Feature2D> ptrFeature2D =
cv::xfeatures2d::SURF::create(2000.0);
// 检测关键点
ptrFeature2D -> detect(image1,keypoints1);
ptrFeature2D -> detect(image2, keypoints2);
// 提取描述子
cv::Mat descriptors1;
cv::Mat descriptors2;
ptrFeature2D -> compute(image1, keypoints1, descriptors1);
ptrFeature2D -> compute(image2, keypoints2, descriptors2);
//
兴趣点描述子的计算结果是一个矩阵(即cv::Mat 实例)
//
,矩阵的行数等于关键点容器的元素个数。每行是一个 N 维的描述子容器。 SURF
//
描述子的默认尺寸是 64,而 SIFT 的默认尺寸是 128。这个容器用于区分特征点周围的强度值图
//
案。两个特征点越相似,它们的描述子容器就会越接近。注意, SURF 兴趣点并不一定要使用 SURF
//
描述子,SIFT 也一样;检测器和描述子可以任意搭配。
cv::BFMatcher matcher(cv::NORM_L2);
// 指定范围的匹配
float maxDist = 0.25;
vector<vector<cv::DMatch> > matches;
matcher.radiusMatch(descriptors1, descriptors2, matches, maxDist);
// 输出结果
cv::Mat outImage;
cv::drawMatches(image1, keypoints1,
image2, keypoints2,
matches,
outImage,
cv::Scalar(255, 255, 255),
cv::Scalar(255, 255, 255));
cv::imshow("OUT IMAGE", outImage);
cout << "the keypoints number of image1 : " << keypoints1.size() << endl;
cout << "the keypoints number of image2 : " << keypoints2.size() << endl;
cout << "the number of newMatches : " << matches.size() << endl;
cv::waitKey(0);
return 0;
}
最后
以上就是高挑红牛为你收集整理的计算机视觉攻略 笔记10 (描述并匹配局部强度值模式)描述并匹配局部轻度值模式的全部内容,希望文章能够帮你解决计算机视觉攻略 笔记10 (描述并匹配局部强度值模式)描述并匹配局部轻度值模式所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复