导数算子
背景
由于边缘是由灰阶值的变化定义的,因此对这种变化敏感的算子就可以用作边缘检测器。
导数算子是可以实现这种功能的:
导数的意义之一就是表示函数值的变化率,而图像中的灰阶值的变化率在边缘附近很大,在常量区域很小。
理论
由于图像是二维的,因此应该考虑很多方向上的灰阶值变化。基于这个原因,我们采用了图像关于主方向x,y的偏导数。
对边缘实际方向的估计可以将x方向和y方向的导数看做实际方向上沿两条轴的分量,然后通过计算向量和得到。
这里使用的算子刚好是梯度(gradient),如果把图像看做是一个二变量的函数A(x,y),那么梯度可以定义为:
这是一个二维向量。
当然,一幅图像不是一个函数,因而不能通过这种方式进行求导。
由于图像是离散的,因此我们使用差分运算,即:一个像素点的导数可以由一块局部区域内灰阶值的变化来近似。
近似方案一
这种情况的假设为灰阶值在像素之间线性变化,因此不论在哪里取导数,导数的值都是直线的斜率。
这种近似的问题在于斜率的计算并不是在点(x,y),而是在(x - 1/2, y - 1/2)点处。
因此,边缘的位置会在原来的基础上向-x和-y方向偏移半个像素。
近似方案二
这个算子关于像素(x,y)是对称的,不过没有考虑像素(x,y)的值。
不管采用什么算子来计算梯度,得到的向量都能表示边缘在那个像素处的强度以及边缘的方向。
梯度向量的长度为一个直角三角形斜边的长度,而这个长度反映了给定像素上的边缘强度(或称边缘响应,edge response)。
在这个像素上边缘的方向为直角三角形斜边和轴的夹角。
边缘大小的值为一个实数,通常通过取整操作转换成整数。
任何像素的梯度值如果超过了一个指定的阈值,这个像素就被称为一个边缘像素,而其他像素则不是。
(一般,会将一定范围内的灰阶值的中值作为阈值)
从技术上说,边缘检测器只会报告出边缘像素,而边缘增强操作将边缘像素绘制在原始图像上。
边缘增强的测试图像能够粗略的表明边缘检测算法的成功性。
度量边缘检测方法的好坏
我们需要一个能够绝对表示边缘检测方法好坏的数值度量值用于评判。通常来说,没有这样的度量。
对边缘检测器可能失败或出错的方式,我们进行思考:
(1)首先,边缘检测器可能在没有边缘存在的时候报告边缘,可能的原因包括噪声、阈值和糟糕的设计,这种情形称作错误肯定(false positive)。
(2)此外,边缘检测器也可能在存在边缘像素的地方没有报告边缘的存在,这种情形称作错误否定(false negative)。
(3)最后,边缘像素的位置可能是错误的。
能够报告出边缘像素正确位置的边缘检测器显然比那些无法报告出正确位置的要好,因此我们找些测试图像,这些测试图像的边缘像素的数目和位置都是已知的,而且应用噪声的类型和数量都是已知的,因此对这些标准图像应用边缘检测器可以给出这些边缘检测器效果好坏的近似评估。
Pratt边缘检测器性能评估法(Pratt测试法)
这种方法,考虑的是边缘的实际位置。
Kitchen and Rosenfeld评估法(KR测试法)
这种方法基于局部边缘一致性(local edge coherence)。
这种方法并没有考虑边缘的实际位置,因此是Pratt度量的一种补充。
这种方法考虑的是边缘像素和局部周边边缘像素的匹配程度。
(1)首先,定义了一个函数,测量一个边缘像素在左侧的连续性如何,这个函数如下所示:
(2)还有一个类似的函数,用于测量一个边缘像素在右侧的连续性如何,如下所示:
(3)然后在应用一个细度的测度。
边缘应该是一条细线,即1个像素宽。更大宽度的线条表示存在错误肯定的情况,原因可能是因为边缘检测器对同一个边缘进行了多次响应。
细度T的度量表示的是以要测量的像素为中心的3x3区域中的6个像素,即去除中心像素和L(k)和R(k)找到的两个像素(边缘像素)得到的6个像素。
(4)边缘检测器的整体评估函数如下所示:
源码
导数算子方案一:
https://github.com/ThranduilELFKING/study-openCV/tree/main/gradient1
导数算子方案二:
https://github.com/ThranduilELFKING/study-openCV/tree/main/gradient2
pratt测试法:
https://github.com/ThranduilELFKING/study-openCV/tree/main/pratt
KR测试法:
https://github.com/ThranduilELFKING/study-openCV/tree/main/kr