今天要整理记录的是OpenCV中BRISK特征提取描述算法的运用。
BRISK特征提取描述算法全称为 Binary Robust Invariant Scalable Keypoints(二进制鲁棒不变可扩展关键点)。BRISK算法也是SIFT算法的一种改进型,主要是针对于旋转不变性、鲁棒性、运算速度等方面做了优化,其大致流程如下:
(1)在提取特征点阶段与SIFT算法类似(可参阅《OpenCV4学习笔记(38)》,同样是先构造多尺度图像金字塔,再从每一层图像组的多尺度空间中找到最大特征点(非极大值抑制);
(2)再通过亚像素插值得到最大特征点的精确坐标位置,也即把最大特征点从其它层的坐标映射到金字塔最底层的坐标位置,从而完成对最大特征点的定位。
(3)在描述特征点阶段,使用特征点邻域同心圆采样法,在每个特征点的邻域中选择一个同心圆,在这个同心圆上均匀采样,并对所有采样点进行高斯模糊以消除重复采样带来的影响,并以采样点中的短距离点对的灰度值比较结果,来构建二进制描述子(类似BRIEF特征二进制描述算法,可参阅《OpenCV4学习笔记(39)》)。
(4)再以每个特征点的方向特征、也就是梯度来进行方向归一化,强化了BRISK特征描述子的旋转不变性。
通过上述步骤即可得到BRISK特征的二进制描述子,总的来说BRISK特征算法是一种效果比较好的特征算法,主要优点在于它的检测速度,相比SIFT等特征算法而言要明显更快,可以用于实时处理中。
在OpenCV中同样封装好了BRISK算法的特征检测器,下面是调用BRISK算法的代码演示:
Mat tem_image = imread("D:\\opencv_c++\\opencv_tutorial\\data\\images\\tem.jpg");
Mat dected_image = imread("D:\\opencv_c++\\opencv_tutorial\\data\\images\\miao.jpg");
resize(tem_image, tem_image, Size(160,120));
resize(dected_image, dected_image, Size(600, 800));
auto brisk = BRISK::create();
vector<KeyPoint> keyPoints_tem, keyPoints_dected;
Mat descriptors_tem, descriptors_dected;
brisk->detectAndCompute(tem_image, Mat(), keyPoints_tem, descriptors_tem, false);
brisk->detectAndCompute(dected_image, Mat(), keyPoints_dected, descriptors_dected, false);
auto matcher = DescriptorMatcher::create(DescriptorMatcher::MatcherType::BRUTEFORCE);
vector<DMatch> matches;
matcher->match(descriptors_tem, descriptors_dected, matches);
float maxdist = matches[0].distance;
for (int i = 0; i < matches.size(); i++)
{
if (maxdist < matches[i].distance)
{
maxdist = matches[i].distance;
}
}
float thresh = 0.45;
vector<DMatch> good_Matches;
vector<Point2f> temPoints, dectedPoints;
for (int j = 0; j < matches.size(); j++)
{
if (matches[j].distance < thresh * maxdist)
{
good_Matches.push_back(matches[j]);
temPoints.push_back(keyPoints_tem[matches[j].queryIdx].pt);
dectedPoints.push_back(keyPoints_dected[matches[j].trainIdx].pt);
}
}
if (0 == good_Matches.size())
{
cout << "不存在最佳匹配特征点" << endl;
return 0;
}
Mat result;
drawMatches(tem_image, keyPoints_tem, dected_image, keyPoints_dected, good_Matches, result, Scalar::all(-1), Scalar::all(-1), vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS);
imshow("result", result);
演示效果如下图:
在运行BRISK算法和SIFT等算法对同一张图像进行特征点提取时,可以明显的感受到二者的速度差距,可以说BRISK是一种高速的特征点检测和特征描述子生成以及高速匹配的算法。
而且BRISK特征提取描述算法在很大程度上还保留了旋转不变性和尺度不变性,实现了较高检测质量的同时仍然具有较快的运行速度,有效降低了计算成本,更适合用于实时特征提取的工作中。
好的,今天的笔记整理到此结束,谢谢阅读。
PS:本人的注释比较杂,既有自己的心得体会也有网上查阅资料时摘抄下的知识内容,所以如有雷同,纯属我向前辈学习的致敬,如果有前辈觉得我的笔记内容侵犯了您的知识产权,请和我联系,我会将涉及到的博文内容删除,谢谢!