OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()
OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()
参考博客:
Harris角点检测原理详解
Harris角点检测原理及C++实现
OpenCV亚像素角点cornerSubPixel()源代码分析
Taylor公式(泰勒公式)通俗+本质详解
如何理解最小二乘法?
一、概述
1、角点定义:
角点没有明确的数学定义,但人们普遍认为角点是二维图像亮度变化剧烈的点或图像边缘曲线上曲率极大值的点。这些点在保留图像图形重要特征的同时,可以有效地减少信息的数据量,使其信息的含量很高,有效地提高了计算的速度,有利于图像的可靠匹配,使得实时处理成为可能。其在三维场景重建、运动估计、目标跟踪、目标识别、图像配准与匹配等计算机视觉领域起着非常重要的作用。
2、角点检测:
计算机视觉子系统中用来捕获图像特征的一种方法,广泛应用于运动检测,图相匹配,视频跟踪,三维重建和目标识别等领域,也称为特征点检测。我不再观测整幅图,二十选择某些特殊的点,然后对他们进行局部 有的放矢(有明确的目的性和针对性)地分析。
图像的特征类型包括有:
1)边缘
2)角点(感兴趣的关键点)
3)斑点(感兴趣的区域)
关于角点的具体描述有:
1)一阶导数(既灰度的梯度)的局部最大所对应的像素点
2)两条既两条以上边缘的交点
3)图像中梯度值和梯度方向的变化速率都很高的点
4)角点处得一阶导数最大,二阶导数为零,它指示了物体边缘变化不连续的方向
在当前的图像处理领域中,角点检测算法可以归纳为:
1)基于灰度图像的角点检测(基于灰度图像的角点检测又可分三类,见下)
2)基于二值图像的角点检测
3)基于轮廓曲线的角点检测
基于灰度图像的角点检测:
1)基于梯度:
其中基于梯度的方法是通过计算边缘的曲率来判断角点的存在性,角点计算数值的大小不仅与边缘强度有关,而且与边缘方向的变化率有关,该方法对噪声比基于模板的角点检测方法对噪声更为敏感。
2)基于模板:
其中基于模板的方法主要考虑像素领域点的灰度变化,即图像亮度的变化,将与邻点亮度对比足够大的点定义为角点。常见的基于模板的角点检测算法有Kitchen-Rosenfeld角点检测算法,Harris角点检测算法、KLT角点检测算法及SUSAN角点检测算法。和其他角点检测算法相比,SUSAN角点检测算法具有算法简单、位置准确、抗噪声能力强等特点。
3)基于模板+梯度组合
二、harris角点检测,cornerHarris()函数
harris角点检测是一种直接基于灰度图像的角点提取算法,稳定性高,尤其对L型角点检测精度高。但由于
该函数在图像上运行Harris角探测器。与cornerMinEigenVal()和cornerEigenValsAndVecs()函数类似,对于每个像素(x,y),它计算 blockSize×blockSize 邻域上的2×2梯度协方差矩阵M(x,y)。然后计算如下特征
:
图像中的角点可以作为此响应映射的局部最大值。即找出角点。
void cornerHarris(
InputArray src, // 输入图像,单通道8位或者浮点型图像
OutputArray dst, // 存放利用角点检测之后的图像
int blockSize*blockSize, // 表示领域的大小
int ksize, // 表示Sobel()算子孔径的大小
double k, // Harris参数
intborderType=BORDER_DEFAULT // 图像像素的边界模式有默认值BORDER_DEFAULT
)
在用cornerHarris函数时要用单通道的图像,要配合阈值操作函数一起threshold()对角点检测之后的图像进行显示操作,确定图像的强角点:goodFeatureToTrack()函数。
三、cornerMinEigenVal(),cornerEigenValsAndVecs()函数
作用:计算图像块的特征值和特征向量用于角点检测。
void cornerEigenValsAndVecs(
InputArray src, // 输入单通道8位或浮点图像
OutputArray dst, // 用来存储结果的图像;它有src相同的大小和类型为CV_32FC(6)
int blockSize, // 领域尺寸
int ksize, // Sobel()算子的孔径参数
int borderType=BORDER_DEFAULT // 图像像素的边界模式有默认值BORDER_DEFAULT
);
作用:计算梯度矩阵的最小特征值用于角点检测。
void cornerMinEigenVal(
InputArray src, // 输入单通道8位或浮点图像;
OutputArray dst, // 用来存储最小特征值的图像;它有src相同的大小和类型为CV_32FC1;
int blockSize, // 领域尺寸;
int ksize=3, // Sobel()算子的孔径参数;
int borderType=BORDER_DEFAULT // 像素外推方式;
);
三、确定图像强角点:Shi-Tomasi角点检测,goodFeaturesToTrack()函数
goodFeatureToTrack()函数结合了Shi-Tomasi算子,用于确定图像的强角点:
void goodFeaturesToTrack(
InputArray image, // 输入图像,需要8位的或者浮点型32位单通道图像
OutputArray corners, // 检测到角点的输出向量
int maxCorners, // 角点的最大数量
double qualityLevel, // 角点检测可接受的最小特征值:其实实际用于过滤角点的最小特征值// 是 qualityLevel 与图像中最大特征值得乘积。// 通常不超过1(常用0.10和0.01)。检测完所有角点后,// 还要剔除一些距离较近的角点
double minDistance, // 角点之间的最小距离,单位为像素
InputArray mask=noMask(), // 用于指定感兴趣区域的角点检测,默认是noArray()
int blockSize=3, // 是计算导数自相关矩阵时指定的邻域范围
bool useHarrisDetector=false, // 指示是否使用Harris角点检测
double k=0.04 // 为了用于设置Hessian 自相关矩阵行列式 的相对权重的权重系数
);
四、亚像素级角点检测:cornerSubPix()函数
原理见上:
cornerSubPix()函数用于寻找亚像素级角点位置(更精确的浮点类型位置)
void cornerSubPix(
InputArray _image, // 输入的单通道图像
InputOutputArray _corners, // 提取的初始整数角点(比如用goodFeatureToTrack提取的强角点)
Size winSize, // 为求取亚像素角点的窗口大小,比如设置Size(11,11),需要注意的是11为半径,则窗口大小为23x23
Size zeroZone, // 设置的“零区域”,在搜索窗口内,设置的“零区域”内的值不会被累加,权重值为0。如果设置为Size(-1,-1),则表示没有这样的区域
TermCriteria criteria // 条件阈值,包括迭代次数阈值和误差精度阈值,一旦其中一项条件满足设置的阈值,则停止迭代,获得亚像素角点
)
五示例一:harris角点检测
#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;#define WINDOW_NAME1 "【程序窗口1】" //为窗口标题定义的宏
#define WINDOW_NAME2 "【程序窗口2】" //为窗口标题定义的宏Mat g_srcImage, g_srcImage1,g_grayImage;
int thresh = 30; //当前阈值
int max_thresh = 175; //最大阈值int main()
{// 1、载入原始图并进行克隆保存g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/corner.jpg", 1 );if(!g_srcImage.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }imshow("原始图",g_srcImage);g_srcImage1=g_srcImage.clone( );// 2、存留一张灰度图cvtColor( g_srcImage1, g_grayImage, COLOR_BGR2GRAY );// 3、创建窗口和滚动条namedWindow( WINDOW_NAME1, WINDOW_AUTOSIZE );createTrackbar( "阈值: ", WINDOW_NAME1, &thresh, max_thresh, on_CornerHarris );on_CornerHarris( 0, 0 );waitKey(0);return 0;
}
void on_CornerHarris( int, void* )
{// 1、定义一些局部变量Mat dstImage;//目标图Mat normImage;//归一化后的图Mat scaledImage;//线性变换后的八位无符号整型的图// 2、初始化//置零当前需要显示的两幅图,即清除上一次调用此函数时他们的值dstImage = Mat::zeros( g_srcImage.size(), CV_32FC1 );g_srcImage1=g_srcImage.clone( );// 3、正式检测// 进行角点检测// 领域大小为 2// sobel 算子孔径 3// harris 参数cornerHarris( g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT );// 归一化与转换normalize( dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat() );convertScaleAbs( normImage, scaledImage ); //将归一化后的图线性变换成8位无符号整型// 4、进行绘制// 将检测到的,且符合阈值条件的角点绘制出来int corner_count = 0;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, 8, 0 );circle( scaledImage, Point( i, j ), 5, Scalar(0,10,255), 2, 8, 0 );}}cout<<"角点个数="<<corner_count<<endl;// 4、显示最终效果imshow( WINDOW_NAME1, g_srcImage1 );imshow( WINDOW_NAME2, scaledImage );
}
结果:
六、示例二:确定图像强角点:Shi-Tomasi角点检测,亚像素级角点检测:cornerSubPix()函数
#include <opencv2/opencv.hpp>using namespace cv;
using namespace std;#define WINDOW_NAME "【Shi-Tomasi角点检测】" //为窗口标题定义的宏Mat g_srcImage, g_grayImage;
int g_maxCornerNumber = 50; // 角点的最大数量
int g_maxTrackbarNumber = 500;
int g_minDistance =10;
RNG g_rng(12345);//初始化随机数生成器int main()
{// 1、载入原始图并进行克隆保存
// g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/corner2.jpg", 1 );g_srcImage = imread("F:/C++/2. OPENCV 3.1.0/TEST/test1.png", 1 );if(!g_srcImage.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }cvtColor( g_srcImage, g_grayImage, COLOR_BGR2GRAY );// 2、创建窗口和滑动条,并进行显示和回调函数初始化namedWindow( WINDOW_NAME, WINDOW_AUTOSIZE );createTrackbar( "最大角点数", WINDOW_NAME, &g_maxCornerNumber, g_maxTrackbarNumber, on_GoodFeaturesToTrack );createTrackbar( "最小距离", WINDOW_NAME, &g_minDistance, 100, on_GoodFeaturesToTrack );imshow( "原始图", g_srcImage );on_GoodFeaturesToTrack( 0, 0 );waitKey(0);return 0;
}
void on_GoodFeaturesToTrack( int, void* )
{// 1、对变量小于等于1时的处理if( g_maxCornerNumber <= 1 ){g_maxCornerNumber = 1;}// 2、Shi-Tomasi算法(goodFeaturesToTrack函数)的参数准备vector<Point2f> corners;double qualityLevel = 0.01;//角点检测可接受的最小特征值int blockSize = 3;//计算导数自相关矩阵时指定的邻域范围double k = 0.04;//权重系数Mat copy = g_srcImage.clone(); //复制源图像到一个临时变量中,作为感兴趣区域// 3、进行Shi-Tomasi角点检测goodFeaturesToTrack( g_grayImage, // 输入图像corners, // 检测到的角点的输出向量g_maxCornerNumber, // 角点的最大数量qualityLevel, // 角点检测可接受的最小特征值g_minDistance, // 角点之间的最小距离Mat(), // 感兴趣区域blockSize, // 计算导数自相关矩阵时指定的邻域范围false, // 不使用Harris角点检测k ); // 权重系数// 4、输出文字信息cout<<"\t>此次检测到的角点数量为:"<<corners.size()<<endl;// 5、绘制检测到的角点int r = 4;for( int i = 0; i < corners.size(); i++ ){//以随机的颜色绘制出角点circle( copy, corners[i], r, Scalar(g_rng.uniform(0,255), g_rng.uniform(0,255),g_rng.uniform(0,255)), -1, 8, 0 );}// 6、显示(更新)窗口imshow( WINDOW_NAME, copy );// 7、亚像素角点检测的参数设置Size winSize = Size( 5, 5 );Size zeroZone = Size( -1, -1 );// TermCriteria术语标准TermCriteria criteria = TermCriteria( TermCriteria::EPS + TermCriteria::MAX_ITER, 40, 0.001 );// 8、计算出亚像素角点位置vector<Point2f> corners_sub=corners;cornerSubPix( g_grayImage, corners_sub, winSize, zeroZone, criteria );// 9、输出角点信息for( int i = 0; i < corners.size(); i++ ){cout<<" \t>>亚像素级/像素级 角点坐标["<<i<<"] ("<<corners_sub[i]<<")"<<" ("<<corners[i].x<<","<<corners[i].y<<")"<<endl;}
}
结果:
OpenCV学习(二十四 ):角点检测(Corner Detection):cornerHarris(),goodFeatureToTrack()相关推荐
- OpenCV学习(二十二) :反向投影:calcBackProject(),mixChannels()
OpenCV学习(二十二) :反向投影:calcHist(),minMaxLoc(),compareHist() 参考博客: 反向投影backproject的直观理解 opencv 反向投影 颜色直方 ...
- OpenCV学习(二十) :分水岭算法:watershed()
OpenCV学习(二十) :分水岭算法:watershed() 参考博客: OpenCV-分水岭算法 图像处理--分水岭算法 OpenCV学习(7) 分水岭算法(1) Opencv分水岭算法--wat ...
- OpenCV——角点检测 (Corner Detection)
角点 角点通常被定义为两条边的交点,或者说,角点的局部邻域应该具有两个不同区域的不同方向的边界.角点检测(Corner Detection)是计算机视觉系统中获取图像特征的一种方法,广泛应用于运动检测 ...
- 【opencv学习】【Harris角点检测】
下面看代码: import cv2 import numpy as np# 1.cv2.cornerHarris(img, blocksize, kszie, k) # 找出图像中的角点 # 参数说明 ...
- OpenCV学习(二十) :直方图匹配、对比:calcHist(),minMaxLoc(),compareHist()
直方图匹配.对比:calcHist ,minMaxLoc,compareHist 1.calcHist()函数 2.归一化:normalize()函数 3.minMaxLoc()函数 4.compar ...
- Golang学习(二十四)家庭记账项目
一.项目开发流程 需求分析-->设计阶段-->实现阶段(代码)-->测试阶段-->实施阶段-->维护阶段 二.项目需求说明 1.模拟实现基于文本界面的 <家庭记账软 ...
- OpenCV学习三十四:watershed 分水岭算法
1. watershed void watershed( InputArray image, InputOutputArray markers ); 第一个参数 image,必须是一个8bit 3通道 ...
- opencv学习(二十六)之图像金字塔(高斯金字塔、拉普拉斯金字塔)
在进行数字图像处理时,我们可能会需要将某种尺寸的图像转换为其他尺寸的图像,这样会存在放大图像核缩小图像两种可能.opencv提供了一个真正意义上的图像所方函数resize(),但在本篇中主要学习以下使 ...
- Java多线程学习二十四:阻塞队列包含哪些常用的方法?add、offer、put 等方法的区别?
阻塞队列包含哪些常用的方法,以及 add,offer,put 等方法的区别. 在阻塞队列中有很多方法,而且它们都非常相似,所以非常有必要对这些类似的方法进行辨析,所以本课时会用分类的方式,和你一起,把 ...
最新文章
- windows下如何正确使用Jconsole远程连接linux主机上的JVM
- 记录MNIST采用卷积方式实现与理解
- Xftp连接到Linux服务器时提示连接失败的配置
- No relevant classes found. No output generated、metaObject连接错误
- thinkcmf搭建教程_5分钟快速入门
- 热式气体质量流量计检定规程_宁夏热式气体质量流量计价位,玻璃管液位计怎么样...
- 【Web网站服务器开发】Apache 和 Tomcat的区别及配置
- 总结一下优化算法关系【压缩传感】【图像逆问题】
- pageContext对象、JSP标签
- pytorch 创建神经网络
- 命令折叠代码的所有部分?
- linux zfs raid,ZFS-自我恢复RAID
- wpf 修改输入框 光标_WPF中鼠标光标的设置
- 字符串与整型的相互转换
- foxmail邮箱服务器类型,foxmail
- 一文梳理2021年常见消息中间件MQ与RabbitMQ面试题
- 【学术写作规范】论文写作注意事项
- 【转】目前最常见的”无线通信(数据)传输技术“有哪些?
- 自适应空间特征融合( adaptively spatial feature fusion)一种基于数据驱动的金字塔特征融合策略
- android4.1 l36h,索尼L36h
热门文章
- animation 先执行一次 在持续执行_这一次,彻底弄懂 JavaScript 执行机制
- Power BI 的 最佳搭档 Excel(基础数据分析)
- php 将颜色透明度,css中如何使颜色透明度
- ab的plc跟西门子哪个好些_2020滚筒洗衣机哪个牌子好?想买滚筒洗衣机的看过来!...
- 改变世界,改善生活:我从科沃斯扫地机器人X1,看到了AI新的希望
- 不要再纠结卷积的公式啦!0公式深度解析全连接前馈网络与卷积神经网络!
- 论文浅尝 | 重新审视语言模型与知识库的关系
- 领域应用 | 知识图谱在小米的应用与探索
- 论文浅尝 | 基于文本关联的知识图谱的无监督嵌入增强
- 论文浅尝 | 具有图卷积网络和顺序注意力机制的应用于目标导向的对话系统