OpenCV:深入Feature2D组件——角点检测

角点检测

  • 1 Harris角点检测
    • 1.1 兴趣点与角点
    • 1.2 角点检测
    • 1.3 harris角点检测
    • 1.4 实现harris角点检测:cornerHarris()函数
    • 1.5 综合案例:harris角点检测与测绘
  • 2. Shi—Tomasi角点检测
    • 2.1Shi—Tomasi角点检测概述
    • 2.2 确定图像强角点:goodFeaturesToTrack()函数
    • 2.3 综合示例:Shi—Tomasi角点检测
  • 3. 亚像素级角点检测
    • 3.1 背景概述
    • 3.2 寻找亚像素角点:cornerSubPix()函数

1 Harris角点检测

1.1 兴趣点与角点

在图像处理和计算机视觉领域,兴趣点,也被成作关键点、特征点。它被大量用于解决物体识别、图像识别、图像匹配、视觉跟踪、三维重建等一系列的问题。我们不再观察整幅图,而是选择某些特殊的点,然后对他们进行局部有的放矢地分析。如果能检测到足够多的这种点,同时它们的区分度很高,并且可以精确定位稳定的特征,那么这个方法就具有实用价值。
图像特征类型可以被分为如下三种:

  • 边缘
  • 角点(感兴趣关键点)
  • 斑点(感兴趣区域)

其中,角点是个很特殊的存在。如果某一点在任意方向的一个微小变化都会引起灰度很大的变化,那么我们就把它称之为角点。角点作为图像上的特征点,包含有重要的信息,在图像融合和目标跟踪以及三维重建中有重要的应用价值。他们在图像中可以轻易地定位,同时,在人造物体场景,比如门、窗、桌等处也随处可见。因为角点位于两条边缘交点处,代表了两个边缘变化的方向上的点,所以他们是可以精确定位的而为特征,甚至可以达到亚像素的精度。又由于其图像梯度有很高的变化,这种变化是可以用来帮助检测角点的。需要注意的是,角点位于相同强度区域上的点不同,与物体轮廓上的点也不同,因为轮廓点难以在相同的其物体上精确定位。

另外,关于角点的具体描述可以有如下几种:

  • 一阶导数(即灰度的梯度)的局部最大所对应的像素点;
  • 两条及两条以上边缘的交点;
  • 图像中梯度值和梯度方向的变化速率都很高的
  • 角点处的一阶导数最大,二阶导数为零,它指示了物体边缘变化不连续的方向。

1.2 角点检测

现有的角点检测算法并不是都十分的健壮。很多方法都要求有大量的训练集和冗余数据来防止或减少错误特征的出现。另外,角点检测方法的一个很重要的评价标准是其对多幅图像中相同或相似特征的检测能力,并且能够应对光照变化、图像旋转等图像变化。

在当前的图像处理领域,角点检测算法可归纳为一下三类。

  • 基于灰度图像的角点检测
  • 基于二值图像的角点检测
  • 基于轮廓曲线的角点检测

1.3 harris角点检测

harris角点检测是一种直接基于灰度图像的角点提取算法,稳定性高,尤其对L型角点检测精度高但由于采用了高斯滤波,运算速度相对较慢,角点信息有丢失和位置偏移的现象,而且角点提取有聚簇的现象。

1.4 实现harris角点检测:cornerHarris()函数

在这里插入图片描述
在这里插入图片描述

  • 第一个参数:输入单通道8位或浮点图像。
  • 第二个参数:用于存储Harris检测器响应的图像。它的类型为CV_32FC1,大小与src相同。
  • 第三个参数:邻域大小
  • 第四个参数:表示Sobel()算子的孔径大小
  • 第五个参数:Harris检测器的自由参数,见上述公式

1.5 综合案例:harris角点检测与测绘

#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;#define WINDOW_NAME1 "程序窗口1"
#define WINDOW_NAME2 "程序窗口2"Mat g_srcImage, g_srcImage1, g_grayImage;
int thresh = 30; //当前阈值
int max_thresh = 175; //最大阈值//回调函数
void on_ConerHarris(int, void*) {Mat dstImage;Mat normImage; //归一化之后Mat scaledImage; //线性变换后的八位无符号整型的图dstImage = Mat::zeros(g_srcImage.size(), CV_32FC1);g_srcImage1 = g_srcImage.clone();//进行角点检测cornerHarris(g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT);//归一化normalize(dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat());convertScaleAbs(normImage, scaledImage);//将归一化后的图线性变化为无符号整型	//进行绘制for (int j = 0; j < normImage.rows; j++) {for (int i = 0; i < normImage.cols; i++) {if ((int)normImage.at<float>(j, i) > thresh + 80) {circle(g_srcImage1, Point(i, j), 5, Scalar(10, 10, 255), 2, 0);circle(scaledImage, Point(i, j), 5, Scalar(0, 10, 255), 2, 0);}}}imshow(WINDOW_NAME1, g_srcImage1);imshow(WINDOW_NAME2, scaledImage);
}int main() {g_srcImage = imread("1.jpg", 1);imshow("原始图", g_srcImage);g_srcImage1 = g_srcImage.clone();//存留一张灰度图cvtColor(g_srcImage1, g_grayImage, COLOR_BGR2GRAY);//创建窗口和滚动条namedWindow(WINDOW_NAME1, 0);createTrackbar("阈值", WINDOW_NAME1, &thresh, max_thresh, on_ConerHarris);//对回调函数进行初始化on_ConerHarris(0, 0);waitKey();return 0;
}

在这里插入图片描述

2. Shi—Tomasi角点检测

2.1Shi—Tomasi角点检测概述

除了利用Harris进行角点检测之外,我们通常还可以利用Shi-Tomasi方法进行角点检测。Shi-Tomasi算法是 Harris算法的改进,此算法最原始的定义是将矩阵M的行列式值与M的迹相减,再将差值同预先给定的阈值进行比较。后来Shi和 Tomasi提出改进了方法,若两个特征值中较小的一个大于最小阈值,则会得到强角点。

2.2 确定图像强角点:goodFeaturesToTrack()函数

goodFeaturesToTrack()函数结合了Shi-Tomasi算子,用于确定图像的墙角点。
在这里插入图片描述

  • 第一个参数:输入8位或浮点32位的单通道图像。
  • 第二个参数:检测到的角的输出向量。
  • 第三个参数:要返回的角的最大数量。maxCorners <= 0意味着没有设置最大数量的限制,所有检测到的角都被返回。
  • 第四个参数:表征图像角落的最小接受质量的参数。参数值乘以最佳角部质量度量,即最小特征值(见cornerMinEigenVal)或Harris函数响应(见cornerHarris)。质量度量小于乘积的角被拒绝。例如,如果最佳角的质量度量=1500,并且qualityLevel=0.01,那么所有质量度量小于15的角都被拒绝。
  • 第五个参数:角点之间的最小距离,此参数用于保证返回的角点之间的距离不小于minDistance个像素。
  • 第六个参数:可选的兴趣区域。如果图像不是空的(它需要有CV_8UC1的类型和与图像相同的大小),它指定了检测角的区域。
  • 第七个参数:计算导数自相关矩阵时指定的邻域范围。
  • 第八个参数:表示是否使用Harris检测器(见cornerHarris)或cornerMinEigenVal的参数。
  • 第九个参数:设置Hessian自相关矩阵行列式的权重系数。

2.3 综合示例:Shi—Tomasi角点检测

#include<opencv2/opencv.hpp>
using namespace std;
using namespace cv;#define WINDOW_NAME "Shi-Tomasi角点检测"Mat g_srcImage, g_grayImage;
int g_maxCornerNumber = 33;
int g_maxTarckbar = 500;
RNG g_rng(12345);void on_GoodFeaturesToTrack(int, void*) {if (g_maxCornerNumber <= 1) g_maxCornerNumber = 1;//Shi-Tomasi算法参数准备vector<Point2f> corners;double qualityLevel = 0.01;double minDistance = 10;int blockSize = 3;double k = 0.04;Mat copy = g_srcImage.clone();goodFeaturesToTrack(g_grayImage,corners,g_maxCornerNumber,qualityLevel,minDistance,Mat(),blockSize,false,k);cout << "此次检测到的角点数量为:" << corners.size() << endl;//绘制检测到的角点for (int i = 0; i < corners.size(); i++) {circle(copy, corners[i], 4, Scalar(0, 0, 255), 1, 8, 0);}imshow(WINDOW_NAME, copy);
}int main() {g_srcImage = imread("1.jpg", 1);cvtColor(g_srcImage, g_grayImage, COLOR_BGR2GRAY);namedWindow(WINDOW_NAME);createTrackbar("最大角点数", WINDOW_NAME, &g_maxCornerNumber,g_maxTarckbar, on_GoodFeaturesToTrack);imshow("源图像", g_srcImage);on_GoodFeaturesToTrack(0, 0);waitKey();
}

在这里插入图片描述

3. 亚像素级角点检测

3.1 背景概述

若我们进行图像处理的目的不是提取用于识别的特征点而是进行几何测量,这通常需要更高的精度,而函数 goodFeaturesToTrack()只能提供简单的像素的坐标值,也就是说,有时候会需要实数坐标值而不是整数坐标值。
亚像素级角点检测的位置在摄像机标定、跟踪并重建摄像机的轨迹,或者重建被跟踪目标的三维结构时,是一个基本的测量值。
在这里插入图片描述
亚像素精确的角定位器是基于这样的观察:从中心q到位于q的邻域内的点p的每个矢量都是与p处的图像梯度正交的,并受到图像和测量噪声的影响。考虑一下这个表达式:
在这里插入图片描述
其中DIpi是q附近的一个点pi的图像梯度。要找到q的值,使ϵi达到最小。可以建立一个方程组,将ϵi设为零:
在这里插入图片描述
其中梯度是在q的邻域(“搜索窗口”)内求和。将第一个梯度项称为G,第二个梯度项称为b,就可以得到:
在这里插入图片描述
该算法将邻域窗口的中心设置在这个新的中心q,然后进行迭代,直到该中心保持在一个设定的阈值之内。

3.2 寻找亚像素角点:cornerSubPix()函数

在这里插入图片描述

  • 第一个参数:输入的图像
  • 第二个参数:InputOutputArray类型的corners,提供输入角点的初始坐标和精确地输出坐标
  • 第三个参数:搜索窗口边长的一半。例如,如果winSize=Size(5,5) ,则使用(5∗2+1)×(5∗2+1)=11×11的搜索窗口。
  • 第四个参数:Size类型的zeroZone,表示死区的一半尺寸。而死区为不对搜索区的中央位置做求和运算的区域,用来避免自相关矩阵出现的某些可能的奇异性。值为(-1,-1)表示没有死区。
  • 第五个参数:角部细化迭代过程的终止标准。也就是说,角位置的细化过程要么在 criteria.maxCount 迭代之后停止,要么在某个迭代中角位置的移动小于 criteria.epsilon时停止。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/7828.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

leetcode 21.合并两个有序链表

⭐️ 往期相关文章 &#x1f4ab;链接1&#xff1a;链表中倒数第k个结点(快慢指针问题) &#x1f4ab;链接2&#xff1a;leetcode 876.链表的中间结点(快慢指针问题) &#x1f4ab;链接3&#xff1a;leetcode 206.反转链表 &#x1f4ab;链接4&#xff1a;leetcode 203.移除链…

RabbitMQ入门指南

人生永没有终点。只有等到你瞑目的那一刻&#xff0c;才能说你走完了人生路&#xff0c;在此之前&#xff0c;新的第一次始终有&#xff0c;新的挑战依然在&#xff0c;新的感悟不断涌现。 文章目录 一、MQ与RabbitMQ概述1. MQ简述2. MQ的优势3. MQ的劣势4. 常见的MQ产品5. Rab…

FastDFS【SpringBoot操作FastDFS、复习】(三)-全面详解(学习总结---从入门到深化)

目录 SpringBoot操作FastDFS 复习&#xff1a; SpringBoot操作FastDFS 由GitHub大牛tobato在原作者YuQing与yuqih发布的JAVA客户端基 础上进行了大量重构工作&#xff0c;并于GitHub上发布了FastDFS-Client1.26.5。 主要特性 1 对关键部分代码加入了单元测试&#xff0c;便于…

使用家庭宽带和摄像头,实现公网直播

那天去逛商场看到有个营业厅&#xff0c;本想进去问问有没有存话费送话费的活动&#xff0c;结果被忽悠办了一个19.9升千兆宽带加送一个路由器的业务。 网络环境验证 听他们说现在家庭宽带都是有公网IPV6地址的&#xff0c;立马用电脑试了下确实有IPV6地址。 赶紧随便写了几行…

C++ 数据结构图(1)

1. 图的基本概念 图是由顶点集合及顶点间的关系组成的一种数据结构&#xff1a;G (V&#xff0c; E) &#xff0c;其中&#xff1a; 顶点集合 V {x|x 属于某个数据对象集 } 是有穷非空集合 &#xff1b; E {(x,y)|x,y 属于 V} 或者 E {<x, y>|x,y 属于 V &&…

那些无法避免的弯路

近日&#xff0c;某高校毕业生在校期间窃取学校内网数据&#xff0c;收集全校学生个人隐私信息的新闻引发了人们对互联网生活中个人信息安全问题的再度关注。在大数据时代&#xff0c;算法分发带来了隐私侵犯&#xff0c;在享受消费生活等便捷权利的同时&#xff0c;似乎又有不…

Lion:闭源大语言模型的对抗蒸馏

Lion&#xff1a;闭源大语言模型的对抗蒸馏 Lion&#xff0c;由香港科技大学提出的针对闭源大语言模型的对抗蒸馏框架&#xff0c;成功将 ChatGPT 的知识转移到了参数量 7B的 LLaMA 模型&#xff08;命名为 Lion&#xff09;&#xff0c;在只有 70k训练数据的情况下&#xff0…

84、基于stm32单片机超市自助存储柜快递箱系统设计(程序+原理图+流程图+参考论文+开题报告+任务书+设计资料+元器件清单等)

单片机主芯片选择方案 方案一&#xff1a;AT89C51是美国ATMEL公司生产的低电压&#xff0c;高性能CMOS型8位单片机&#xff0c;器件采用ATMEL公司的高密度、非易失性存储技术生产&#xff0c;兼容标准MCS-51指令系统&#xff0c;片内置通用8位中央处理器(CPU)和Flash存储单元&a…

select 框添加树结构(todu)

1. 案例: 2. 代码 下班了&#xff0c;明天写

短视频seo矩阵+抖音小程序源码开发解决方案(一)

该解决方案主要针对产品用户交易决策周期长/非标定制等情况的企业&#xff0c;如&#xff1a;房产、汽车、金融、咨询服务&#xff0c;广告设计、网络科技公司&#xff0c;TOB类销售行业等。 基于不同的经营场景&#xff0c;解决方案全面更新&#xff0c;新增账号管理&#xf…

【嵌入式Qt开发入门】如何使用Qt进行文本读写——QFile读写文本

在很多时候我们需要读写文本文件进行读写&#xff0c;比如写个 Mp3 音乐播放器需要读 Mp3 歌词里的文本&#xff0c;比如修改了一个 txt 文件后保存&#xff0c;就需要对这个文件进行读写操作。本文介绍简单的文本文件读写&#xff0c;内容精简&#xff0c;让大家了解文本读写的…

JavaWeb 速通HTML(常用标签汇总及演示)

目录 一、拾枝杂谈 1.网页组成 : 1 结构 2 表现 3 行为 2.HTML入门 : 1 基本介绍 2.基本结构 : 3.HTML标签 : 1 基本说明 2 注意事项 二、常用标签汇总及演示 1.font标签 : 1 定义 2 演示 2.字符实体 : 1 定义 2 演示 3.标题标签 : 1 定义 2 演示 4. 超链接标签 : 1…