【第二部分 图像处理】第3章 Opencv图像处理进阶【6角点检测 A】

2024-08-30 13:32

本文主要是介绍【第二部分 图像处理】第3章 Opencv图像处理进阶【6角点检测 A】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

6.1 Harris 角点检测

6.1.1角点检测概述及原理

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

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

其中,角点是个很特殊的存在。他们在图像中可以轻易地定位,同时,他们在人造物体场景,比如门、窗、桌等出随处可见。因为角点位于两条边缘的交点处,代表了两个边缘变化的方向上的点,,所以他们是可以精确定位的二维特征,甚至可以达到亚像素的精度。且其图像梯度有很高的变化,这种变化是可以用来帮助检测角点的。需要注意的是,角点与位于相同强度区域上的点不同,与物体轮廓上的点也不同,因为轮廓点难以在相同的其他物体上精确定位。
角点检测算法的分类
在当前的图像处理领域,角点检测算法可归纳为三类:

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

而基于灰度图像的角点检测又可分为基于梯度、基于模板和基于模板梯度组合三类方法,其中基于模板的方法主要考虑像素领域点的灰度变化,即图像亮度的变化,将与邻点亮度对比足够大的点定义为角点。常见的基于模板的角点检测算法有Kitchen-Rosenfeld角点检测算法,Harris角点检测算法、KLT角点检测算法及SUSAN角点检测算法。和其他角点检测算法相比,SUSAN角点检测算法具有算法简单、位置准确、抗噪声能力强等特点。
角点的定义
“如果某一点在任意方向的一个微小变动都会引起灰度很大的变化,那么我们就把它称之为角点”。
角点检测(Corner Detection)是计算机视觉系统中用来获得图像特征的一种方法,广泛应用于运动检测、图像匹配、视频跟踪、三维建模和目标识别等领域中。也称为特征点检测。
角点通常被定义为两条边的交点,更严格的说,角点的局部邻域应该具有两个不同区域的不同方向的边界。而实际应用中,大多数所谓的角点检测方法检测的是拥有特定特征的图像点,而不仅仅是“角点”。这些特征点在图像中有具体的坐标,并具有某些数学特征,如局部最大或最小灰度、某些梯度特征等。
现有的角点检测算法并不是都十分的健壮。很多方法都要求有大量的训练集和冗余数据来防止或减少错误特征的出现。另外,角点检测方法的一个很重要的评价标准是其对多幅图像中相同或相似特征的检测能力,并且能够应对光照变化、图像旋转等图像变化。
在我们解决问题时,往往希望找到特征点,“特征”顾名思义,指能描述物体本质的东西,还有一种解释就是这个特征微小的变化都会对物体的某一属性产生重大的影响。而角点就是这样的特征。
观察日常生活中的“角落”就会发现,“角落”可以视为所有平面的交汇处,或者说是所有表面的发起处。假设我们要改变一个墙角的位置,那么由它而出发的平面势必都要有很大的变化。所以,这就引出了图像角点的定义。
我们知道,特征检测与匹配是计算机视觉应用中非常重要的一部分,这需要寻找图像之间的特征建立对应关系。图像中的点作为图像的特殊位置,是很常用的一类特征,点的局部特征也可以叫做“关键特征点”(keypoint feature),或“兴趣点”(interest point),或“角点”(conrner)。
另外,关于角点的具体描述可以有几种:

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

角点检测的工作原理
由于角点代表了图像像素梯度变化,我们将寻找这个”变化”。考虑到一个灰度图像 I I 。划动窗口 w(x,y) (with displacements u u x方向和 v v 方向) 计算像素灰度变化。
这里写图片描述
其中:
w(x,y) is the window at position (x,y) ( x , y )
I(x,y) I ( x , y ) is the intensity at (x,y) ( x , y )
i(x+u,y+v) i ( x + u , y + v ) is the intensity at the moved window (x+u,y+v) ( x + u , y + v )
为了寻找带角点的窗口,我们搜索像素灰度变化较大的窗口。于是, 我们期望最大化以下式子:
这里写图片描述
使用泰勒(Taylor)展开式:
这里写图片描述
式子可以展开为:
这里写图片描述
一个矩阵表达式可以写为:
这里写图片描述
表示为:
这里写图片描述
因此我们有等式:
这里写图片描述
每个窗口中计算得到一个值。这个值决定了这个窗口中是否包含了角点:
这里写图片描述
其中:
这里写图片描述
一个窗口,它的分数 大于一个特定值,这个窗口就可以被认为是”角点”

6.1.2 Harris 角点检测相关API

6.1.2.1 Harris角点检测

当一个窗口在图像上移动,在平滑区域如图1-(a),窗口在各个方向上没有变化。在边缘上如图1-(b),窗口在边缘的方向上没有变化。在角点处如图1-(c),窗口在各个方向上具有变化。Harris角点检测正是利用了这个直观的物理现象,通过窗口在各个方向上的变化程度,决定是否为角点。

这里写图片描述

图1
将图像窗口平移 [u,v] [ u , v ] 产生灰度变化 E(u,v) E ( u , v )
这里写图片描述
由: 这里写图片描述 , 得到:
这里写图片描述
对于局部微小的移动量 [u,v],近似表达为:
这里写图片描述
其中M是 2*2 矩阵,可由图像的导数求得:
这里写图片描述
E(u,v)的椭圆形式如下图:
这里写图片描述

图2

定义角点响应函数 R R 为:
这里写图片描述
Harris角点检测算法就是对角点响应函数R进行阈值处理:R > threshold,即提取R的局部极大值。
参考论文:A Combined Corner and Edge Detector-1988. (见附件)

6.1.2.2 Harris 角点检测相关API函数讲解

角点检测:cornerHarris函数详解
cornerHarris 函数用于在OpenCV中运行Harris角点检测算子处理图像。和cornerMinEigenVal( )以及cornerEigenValsAndVecs( )函数类似,cornerHarris 函数对于每一个像素(x,y)在邻域blockSize×blockSize内,计算2x2梯度的协方差矩阵 M((x,y)) M ( ( x , y ) ) ,接着它计算如下式子:
这里写图片描述
即可以找出输出图中的局部最大值,即找出了角点。

C++: void cornerHarris( InputArray src,OutputArray dst, int blockSize, int ksize, double k, intborderType=BORDER_DEFAULT )  

【参数】
第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像。
第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放Harris角点检测的输出结果,和源图片有一样的尺寸和类型。
第三个参数,int类型的blockSize,表示邻域的大小,更多的详细信息在cornerEigenValsAndVecs()中有讲到。
第四个参数,int类型的ksize,表示Sobel()算子的孔径大小。
第五个参数,double类型的k,Harris参数。
第六个参数,int类型的borderType,图像像素的边界模式,注意它有默认值BORDER_DEFAULT。更详细的解释,参考borderInterpolate( )函数。
接着我们一起过一遍稍后需要用到的Threshold函数的解析,然后看一个以cornerHarris为核心的示例程序。
阈值操作:Threshold()函数详解
函数Threshold( ) 对单通道数组应用固定阈值操作。该函数的典型应用是对灰度图像进行阈值操作得到二值图像。(另外,compare( )函数也可以达到此目的) 或者是去掉噪声,例如过滤很小或很大象素值的图像点。

C++: double threshold( InputArray src, OutputArray dst, double thresh, double maxVal, int thresholdType)

【参数】
第一个参数,InputArray类型的src,输入数组,填单通道 , 8或32位浮点类型的Mat即可。
第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放输出结果,且和第一个参数中的Mat变量有一样的尺寸和类型。
第三个参数,double类型的thresh,阈值的具体值。
第四个参数,double类型的maxval,当第五个参数阈值类型type取 CV_THRESH_BINARY 或CV_THRESH_BINARY_INV 阈值类型时的最大值.
第五个参数,int类型的type,阈值类型,。threshold( )函数支持的对图像取阈值的方法由其确定,具体用法如下。
这里写图片描述
而图形化的阈值描述如下图:

这里写图片描述

图3

6.1.2.3 Harris 角点检测相关API函数源代码

角点检测:cornerHarris函数源代码

/*【cornerHarris ( )源代码】************************************************************ @VersionOpenCV 3.0.0Opnencv2Opnencv3差别不大,LinuxPC的对应版本源码完全一样,均在对应的安装目录下)  * @源码路径:…\opencv\sources\modules\imgproc\src\ corner.cpp* @起始行数:597行   
********************************************************************************/
void cv::cornerHarris( InputArray _src, OutputArray _dst, int blockSize, int ksize, double k, int borderType )
{CV_OCL_RUN(_src.dims() <= 2 && _dst.isUMat(),ocl_cornerMinEigenValVecs(_src, _dst, blockSize, ksize, k, borderType, HARRIS))Mat src = _src.getMat();_dst.create( src.size(), CV_32FC1 );Mat dst = _dst.getMat();#if IPP_VERSION_X100 >= 801 && 0CV_IPP_CHECK(){int type = src.type(), depth = CV_MAT_DEPTH(type), cn = CV_MAT_CN(type);int borderTypeNI = borderType & ~BORDER_ISOLATED;bool isolated = (borderType & BORDER_ISOLATED) != 0;if ( (ksize == 3 || ksize == 5) && (type == CV_8UC1 || type == CV_32FC1) &&(borderTypeNI == BORDER_CONSTANT || borderTypeNI == BORDER_REPLICATE) && cn == 1 && (!src.isSubmatrix() || isolated) ){IppiSize roisize = { src.cols, src.rows };IppiMaskSize masksize = ksize == 5 ? ippMskSize5x5 : ippMskSize3x3;IppDataType datatype = type == CV_8UC1 ? ipp8u : ipp32f;Ipp32s bufsize = 0;double scale = (double)(1 << ((ksize > 0 ? ksize : 3) - 1)) * blockSize;if (ksize < 0)scale *= 2.0;if (depth == CV_8U)scale *= 255.0;scale = std::pow(scale, -4.0);if (ippiHarrisCornerGetBufferSize(roisize, masksize, blockSize, datatype, cn, &bufsize) >= 0){Ipp8u * buffer = ippsMalloc_8u(bufsize);IppiDifferentialKernel filterType = ksize > 0 ? ippFilterSobel : ippFilterScharr;IppiBorderType borderTypeIpp = borderTypeNI == BORDER_CONSTANT ? ippBorderConst : ippBorderRepl;IppStatus status = (IppStatus)-1;if (depth == CV_8U)status = ippiHarrisCorner_8u32f_C1R((const Ipp8u *)src.data, (int)src.step, (Ipp32f *)dst.data, (int)dst.step, roisize,filterType, masksize, blockSize, (Ipp32f)k, (Ipp32f)scale, borderTypeIpp, 0, buffer);else if (depth == CV_32F)status = ippiHarrisCorner_32f_C1R((const Ipp32f *)src.data, (int)src.step, (Ipp32f *)dst.data, (int)dst.step, roisize,filterType, masksize, blockSize, (Ipp32f)k, (Ipp32f)scale, borderTypeIpp, 0, buffer);ippsFree(buffer);if (status >= 0){CV_IMPL_ADD(CV_IMPL_IPP);return;}}setIppErrorStatus();}}
#endifcornerEigenValsVecs( src, dst, blockSize, ksize, HARRIS, k, borderType );
}

阈值操作:Threshold()函数详解

/*【threshold ( )函数源代码】********************************************************** @VersionOpenCV 3.0.0Opnencv2Opnencv3差别不大,LinuxPC的对应版本源码完全一样,均在对应的安装目录下)  * @源码路径:…\opencv\sources\modules\imgproc\src\ thresh.cpp* @起始行数:1186行   
********************************************************************************/
double cv::threshold( InputArray _src, OutputArray _dst, double thresh, double maxval, int type )
{CV_OCL_RUN_(_src.dims() <= 2 && _dst.isUMat(),ocl_threshold(_src, _dst, thresh, maxval, type), thresh)Mat src = _src.getMat();int automatic_thresh = (type & ~CV_THRESH_MASK);type &= THRESH_MASK;CV_Assert( automatic_thresh != (CV_THRESH_OTSU | CV_THRESH_TRIANGLE) );if( automatic_thresh == CV_THRESH_OTSU ){CV_Assert( src.type() == CV_8UC1 );thresh = getThreshVal_Otsu_8u( src );}else if( automatic_thresh == CV_THRESH_TRIANGLE ){CV_Assert( src.type() == CV_8UC1 );thresh = getThreshVal_Triangle_8u( src );}_dst.create( src.size(), src.type() );Mat dst = _dst.getMat();if( src.depth() == CV_8U ){int ithresh = cvFloor(thresh);thresh = ithresh;int imaxval = cvRound(maxval);if( type == THRESH_TRUNC )imaxval = ithresh;imaxval = saturate_cast<uchar>(imaxval);if( ithresh < 0 || ithresh >= 255 ){if( type == THRESH_BINARY || type == THRESH_BINARY_INV ||((type == THRESH_TRUNC || type == THRESH_TOZERO_INV) && ithresh < 0) ||(type == THRESH_TOZERO && ithresh >= 255) ){int v = type == THRESH_BINARY ? (ithresh >= 255 ? 0 : imaxval) :type == THRESH_BINARY_INV ? (ithresh >= 255 ? imaxval : 0) :/*type == THRESH_TRUNC ? imaxval :*/ 0;dst.setTo(v);}elsesrc.copyTo(dst);return thresh;}thresh = ithresh;maxval = imaxval;}else if( src.depth() == CV_16S ){int ithresh = cvFloor(thresh);thresh = ithresh;int imaxval = cvRound(maxval);if( type == THRESH_TRUNC )imaxval = ithresh;imaxval = saturate_cast<short>(imaxval);if( ithresh < SHRT_MIN || ithresh >= SHRT_MAX ){if( type == THRESH_BINARY || type == THRESH_BINARY_INV ||((type == THRESH_TRUNC || type == THRESH_TOZERO_INV) && ithresh < SHRT_MIN) ||(type == THRESH_TOZERO && ithresh >= SHRT_MAX) ){int v = type == THRESH_BINARY ? (ithresh >= SHRT_MAX ? 0 : imaxval) :type == THRESH_BINARY_INV ? (ithresh >= SHRT_MAX ? imaxval : 0) :/*type == THRESH_TRUNC ? imaxval :*/ 0;dst.setTo(v);}elsesrc.copyTo(dst);return thresh;}thresh = ithresh;maxval = imaxval;}else if( src.depth() == CV_32F );elseCV_Error( CV_StsUnsupportedFormat, "" );parallel_for_(Range(0, dst.rows),ThresholdRunner(src, dst, thresh, maxval, type),dst.total()/(double)(1<<16));return thresh;
}

好了,让我们看一个调用示例程序,代码参看附件【demo1】。

这里写图片描述

图4

6.1.3 Harris 角点检测综合实例

本次综合示例为调节滚动条来控制阈值,以控制的harris检测角点的数量。一共有三个图片窗口,分别为显示原始图的窗口,包含滚动条的彩色效果图窗口,以及灰度图效果图窗口。代码参看附件【demo2】。

这里写图片描述

图5

这里写图片描述

图6

参考:
中文链接
英文链接

本章参考附件

点击进入

这篇关于【第二部分 图像处理】第3章 Opencv图像处理进阶【6角点检测 A】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1120953

相关文章

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

一文详解如何在Python中从字符串中提取部分内容

《一文详解如何在Python中从字符串中提取部分内容》:本文主要介绍如何在Python中从字符串中提取部分内容的相关资料,包括使用正则表达式、Pyparsing库、AST(抽象语法树)、字符串操作... 目录前言解决方案方法一:使用正则表达式方法二:使用 Pyparsing方法三:使用 AST方法四:使用字

在PyCharm中安装PyTorch、torchvision和OpenCV详解

《在PyCharm中安装PyTorch、torchvision和OpenCV详解》:本文主要介绍在PyCharm中安装PyTorch、torchvision和OpenCV方式,具有很好的参考价值,... 目录PyCharm安装PyTorch、torchvision和OpenCV安装python安装PyTor

openCV中KNN算法的实现

《openCV中KNN算法的实现》KNN算法是一种简单且常用的分类算法,本文主要介绍了openCV中KNN算法的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录KNN算法流程使用OpenCV实现KNNOpenCV 是一个开源的跨平台计算机视觉库,它提供了各

OpenCV图像形态学的实现

《OpenCV图像形态学的实现》本文主要介绍了OpenCV图像形态学的实现,包括腐蚀、膨胀、开运算、闭运算、梯度运算、顶帽运算和黑帽运算,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起... 目录一、图像形态学简介二、腐蚀(Erosion)1. 原理2. OpenCV 实现三、膨胀China编程(

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

opencv图像处理之指纹验证的实现

《opencv图像处理之指纹验证的实现》本文主要介绍了opencv图像处理之指纹验证的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学... 目录一、简介二、具体案例实现1. 图像显示函数2. 指纹验证函数3. 主函数4、运行结果三、总结一、

Mysql删除几亿条数据表中的部分数据的方法实现

《Mysql删除几亿条数据表中的部分数据的方法实现》在MySQL中删除一个大表中的数据时,需要特别注意操作的性能和对系统的影响,本文主要介绍了Mysql删除几亿条数据表中的部分数据的方法实现,具有一定... 目录1、需求2、方案1. 使用 DELETE 语句分批删除2. 使用 INPLACE ALTER T

python+opencv处理颜色之将目标颜色转换实例代码

《python+opencv处理颜色之将目标颜色转换实例代码》OpenCV是一个的跨平台计算机视觉库,可以运行在Linux、Windows和MacOS操作系统上,:本文主要介绍python+ope... 目录下面是代码+ 效果 + 解释转HSV: 关于颜色总是要转HSV的掩膜再标注总结 目标:将红色的部分滤

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx