• Opencv | 边缘检测 & 轮廓信息


    一. 边缘检测

    1. 边缘的定义

    在这里插入图片描述

    	边缘:像素值快速变化的区域,也就是像素值函数一阶导数的极值区域
    	边缘信息:像素值明显变化的区域, 具有非常丰富的语义信息,常用于物体识别等领域
    
    • 1
    • 2

    2. Sobel算子 边缘提取

    	Sobel滤波作用:相当于先高斯去燥,再使用一阶导数获取极值
    				  导数对噪声非常敏感
    	
    	语法
    	方法1:
    		cv2.Sobel(src, ddepth, dx, dy[, ksize[, scale[, delta[, borderType]]]])
    	参数:
    		src:表示输入图像,即待处理的原始图像
    		ddepth:表示输出图像的深度,当其值为负时(通常取-1),输出图像与输入图像有相同的深度
    		dx:表示x方向上的求导阶数,若想计算水平方向的边缘,则设置为1
    		dy:表示y方向上的求导阶数,若想计算垂直方向的边缘,则设置为1
    		ksize:Sobel核的大小,默认为3,即3x3的矩阵
    			   如果该值为-1,则会使用Scharr算子进行运算
    		scale:计算导数值时所采用的缩放因子,默认情况下该值是1,即无缩放
    		delta:在结果中加入的一个可选的常数项,用于调节输出图像的亮度
    		borderType:像素外推法选择项,用于处理图像边缘的像素
    	作用:计算图像的一阶导数,通常用于边缘检测
    	
    	方法2:
    		cv.filter2D()函数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述
    d d x ( f ∗ g ) = f ∗ d d x g \frac{d}{d x}(f * g)=f * \frac{d}{d x} g dxd(fg)=fdxdg

    • SobelX:水平梯度/垂直边缘,提取垂直的边缘信息
      在这里插入图片描述
      经过SobelX提取的边缘信息为:
      在这里插入图片描述

    • SobelY:垂直梯度/水平边缘,提取水平的边缘信息
      在这里插入图片描述
      经过SobelY提取的边缘信息为:
      在这里插入图片描述

    3. Scharr算子 边缘提取

    	Scharr是Sobel算子的改进版,具有更好的性能和更高的精度
    
    • 1

    4. Laplacian算子 边缘提取

    Δ s r c = ∂ 2 s r c ∂ x 2 + ∂ 2 s r c ∂ y 2 \Delta s r c=\frac{\partial^{2} s r c}{\partial x^{2}}+\frac{\partial^{2} s r c}{\partial y^{2}} Δsrc=x22src+y22src

    	cv2.Laplacian(src, ddepth, ksize, scale=1, delta=0, borderType=BORDER_DEFAULT)
    	参数:
    		src:表示原始输入图像
    		ddepth:表示目标图像的深度
    		ksize:
    			用于计算二阶导数的核(kernel)尺寸大小
    				必须是正的奇数
    				如果该参数未指定,则默认使用3x3的核
    		scale:表示计算Laplacian值的缩放比例因子,该参数是可选的
    			   默认情况下,该值为1,表示不进行缩放
    		delta:表示加到目标图像上的可选值,默认为0
    		borderType:表示像素外推法选择项,用于处理图像边界
    	作用:Laplacian滤波器在图像处理中常用于边缘检测和增强
    	效果:
    		块团检测:周边高于或者低于中心点的区域 
    		边缘检测:像素值快速变化的区域
    
    	特点:二阶微分算子作为梯度值
    	不同点:与Sobel和Scharr滤波器不同,Laplacian滤波器对图像中的突变(即边缘)更加敏感,因为它使用的是二阶导数
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    5. Canny 边缘检测算法

    Canny边缘检测算法是从不同视觉对象中提取有用的结构信息,是传统计算机视觉中非常广泛应用的一种边缘提取算法

    	语法:
    		cv2.Canny(image, threshold1, threshold2[, apertureSize[, L2gradient]])
    		参数:
    			image:表示要进行边缘检测的输入图像
    			threshold1:第一个阈值,用于边缘连接,较小的值会导致更多边缘被检测到
    			threshold2:第二个阈值,用于检测强边缘,较大的值将导致仅检测到强边缘
    			apertureSize:可选参数,表示Sobel算子的孔径大小,默认值为3
    			L2gradient:可选参数,表示是否使用L2范数计算梯度幅值,默认值为False
    	Canny边缘检测算法通过以下步骤实现:
    		使用高斯滤波平滑图像,减少图像中的噪声
    		计算图像的梯度幅值和方向
    		对梯度幅值应用非最大抑制,以得到细化的边缘
    		使用两个阈值(threshold1和threshold2)来确定潜在的边缘
    		通过抑制孤立的弱边缘,最终得到边缘检测结果。
    	作用:	
    		Canny算法能够有效地识别图像中的弱边缘和强边缘,并结合它们的位置关系,给出图像整体的边缘信息
    		由于其优越的性能,Canny算法是目前最常用的边缘检测算法之一
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    5.1 计算梯度的强度及方向

    强度: G = G x 2 + G y 2 强度:G=\sqrt{G_{x}^{2}+G_{y}^{2}} 强度:G=Gx2+Gy2
    方向: θ = arctan ⁡ ( G y / G x ) 方向:\theta=\arctan \left(G_{y} / G_{x}\right) 方向:θ=arctan(Gy/Gx)

    其中,Sobel算子为:
    S x = [ − 1 0 1 − 2 0 2 − 1 0 1 ] S y = [ 1 2 1 0 0 0 − 1 − 2 − 1 ] S_{x}=\left[

    101202101" role="presentation" style="position: relative;">101202101
    \right] S_{y}=\left[
    121000121" role="presentation" style="position: relative;">121000121
    \right] Sx= 121000121 Sy= 101202101

    因此:
    G x = S x ∗ A = [ − 1 0 1 − 2 0 2 − 1 0 1 ] ∗ [ a b c d e f g h i ] = sum ⁡ ( [ − a 0 c − 2 d 0 2 f − g 0 i ] ) G_{x}=S_{x} * A=\left[

    101202101" role="presentation" style="position: relative;">101202101
    \right] *\left[
    abcdefghi" role="presentation" style="position: relative;">abcdefghi
    \right]=\operatorname{sum}\left(\left[
    a0c2d02fg0i" role="presentation" style="position: relative;">a0c2d02fg0i
    \right]\right) Gx=SxA= 121000121 adgbehcfi =sum a2dg000c2fi

    G y = S y ∗ A = [ 1 2 1 0 0 0 − 1 − 2 − 1 ] ∗ [ a b c d e f g h i ] = sum ⁡ ( [ a 2 b c 0 0 0 − g − 2 h − i ] ) G_{y}=S_{y} * A=\left[

    121000121" role="presentation" style="position: relative;">121000121
    \right] *\left[
    abcdefghi" role="presentation" style="position: relative;">abcdefghi
    \right]=\operatorname{sum}\left(\left[
    a2bc000g2hi" role="presentation" style="position: relative;">a2bc000g2hi
    \right]\right) Gy=SyA= 101202101 adgbehcfi =sum a0g2b02hc0i

    5.2 非极大值抑制

    	属于一种边缘稀疏技术
    	作用:主要作用就是构建“瘦”边 
    	效果:非极大值抑制可以将局部最大值之外的所有梯度值抑制为0
    	
    	其构建过程:
    		将当前像素的梯度强度与沿着正负梯度方向上的两个像素进行比较
    			如果当前像素的梯度强度 > 另外两个像素,则该像素点保留为边缘点
    			否则该像素点被抑制为0 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5.3 双阈值检测

    在进行非极大值抑制后,剩余的像素可以更准确地表示图像中的实际边缘,但是有可能还是存在一些噪音数据形成的边缘像素,所以需要使用弱梯度值来过滤这些非实际的边缘像素,并保留高梯度的实际边缘值

    	像素边缘的梯度值 > 高阈值,标记为强边缘像素
    	高阈值 > 像素边缘的梯度值 > 低阈值,标记为弱边缘像素
    	像素边缘的梯度值 < 低阈值,则会将其抑制
    
    • 1
    • 2
    • 3

    5.4 抑制孤立弱边缘

    查看弱边缘像素及其周边的八个邻域像素:

    	只要其中有一个为强边缘像素/真实边缘像素,则该弱边缘点被保留为真实边缘/强边缘像素
    
    • 1

    算法原理:真实的弱边缘像素一定是连接强边缘像素点的

    二. 轮廓信息

    轮廓信息可以简单的理解为从图像中获取图像曲线的连接点信息,在目标检测、目标识别等业务场景中,具有一定的效果

    轮廓信息就是从图像中获取图像边缘信息

    1. 获取轮廓信息

    	contours, hierarchy = cv.findContours(image, mode, method[, contours[, hierarchy[, offset]]])
    	参数:
    		image:
    			输入的单通道图像矩阵
    			通常是经过边缘检测算子处理的二值图像
    		contours:
    			双重向量
    				其中每个元素包含由连续的Point点构成的点的集合,代表一个轮廓
    				有多少轮廓,这个向量就有多少元素
    			hierarchy:
    				包含4个整型的向量,定义了图像中各个轮廓之间的等级关系
    			mode:
    				定义轮廓的检索模式
    					CV_RETR_EXTERNAL:只检测最外围轮廓,内围轮廓被忽略
    					CV_RETR_LIST:检测所有轮廓,包括内围和外围轮廓,但检测到的轮廓不建立等级关系,彼此之间独立
    					CV_RETR_CCOMP:检测所有轮廓,并建立两个等级的轮廓层次关系;顶层是外部轮廓,底层是内部轮廓
    					CV_RETR_TREE:检测所有轮廓,并建立完整的等级树状结构,每个轮廓都有相应的父轮廓或子轮廓
    			method:
    				定义轮廓的近似方法
    					CV_CHAIN_APPROX_NONE:存储所有轮廓点,即不进行任何近似
    					CV_CHAIN_APPROX_SIMPLE:仅存储轮廓的拐点信息,即对于一条直线上的点而言,仅仅保留端点信息
    					CV_CHAIN_APPROX_TC89_L1:使用Teh-Chin链逼近算法,将轮廓近似为一条折线
    					CV_CHAIN_APPROX_TC89_KCOS:使用Teh-Chin链逼近算法,将轮廓近似为一条曲线
    			offset:是可选参数,表示轮廓点相对于原始图像的偏移量
    	返回值:contours和hierarchy
    	操作:
    		先对图像进行预处理:转为灰度图像,阈值分割或边缘检测算法来获取二值图像
    		随后使用该函数进行检测和提取图像中的轮廓,为后续的图像分析、目标识别或形状匹配等任务提供基础
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    2. 画轮廓

    	cv.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])
    	参数:
    		image:输入单通道图像矩阵,通常是经过边缘检测算子处理的二值图像
    		contours:双重向量
    		contourIdx:
    			要绘制的轮廓的索引
    			如果为负数,则绘制所有轮廓
    		color:表示绘制轮廓的颜色
    		thickness:
    			绘制轮廓的线条粗细
    			如果为负数,则填充轮廓内部
    		lineType:	表示绘制轮廓的线条类型,如:实线、虚线等
    		hierarchy:包含4个整型的向量,定义了图像中各个轮廓之间的等级关系
    		maxLevel:
    			绘制轮廓的最大层级
    				如果为0,则只绘制指定索引的轮廓
    				如果大于0,则绘制指定索引及其子轮廓
    		offset:可选参数,表示轮廓点相对于原始图像的偏移量
    	作用:在图像中直观地显示轮廓信息
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    初始I/O及其基本操作
    The timestamp difference between admin and executor exceeds the limit.解决办法
    代码随想录训练营day58 || ● 739. 每日温度 ● 496.下一个更大元素 I
    全网最全95道MongoDB面试题1万字详细解析
    【数据结构与算法】二叉树的知识讲解
    Java并发编程吐血1个月总结最全面的100道面试题!!!
    咪咕MGV2000KL南传_S905L3B_MT7668线刷固件包
    LeetCode-数组-No48旋转图像
    Springboot基于Restful风格
    Java小树的参天成长【内部类,成员内部类,静态内部类,局部内部类,匿名内部类】
  • 原文地址:https://blog.csdn.net/weixin_49613115/article/details/138091446