图像分析:边缘检测中的梯度算子
如果要计算梯度图,就必须设计模板卷积。第一,计算时一定要了解图像的坐标系。许多博客文章对应的模板与坐标系不匹配。我们在卷积运算中主要使用计算坐标系。
左边摄像师使用的坐标系经常用于图像计算。它的坐标原点在左上角,X轴水平向右延伸。y是垂直的,向下延伸。它不仅可以表示这个图像,还可以表示坐标上像素的值。
屏幕显示经常使用右边的Lena坐标系,因为屏幕扫描是从左到右,从上到下进行的。原点在图像的左上角,纵轴标记图像的行,横轴标记图像的列。它不仅可以表示这个图像,还可以表示行和列的交点处的图像值。
我们首先需要知道的是,梯度是一个向量。如果它是一个向量,它就有方向和大小。梯度方向指向函数变化最快的方向,大小就是它的模和最大变化率。对于二元函数,它在该点的梯度是,或者,它是:
其中,该梯度向量的振幅和方向角为
下图显示了灰度贴图的数学表达式。一个像素的灰度值是它有八个邻域。
图像在该点的梯度为
在…之中
即图像对应的水平方向,即水图像对应的垂直方向。
要了解渐变图的生成,首先要了解模板卷积的过程。
模板卷积是模板操作的一种方式,其步骤如下:
(1)在输入图像中漫游模板,并将模板的中心与图像中的像素位置重叠;
(2)将模板上的每个系数与模板下每个对应像素的灰度相乘;
(3)将所有乘积相加(为了保持灰度范围,往往将结果除以模板系数之和,如果梯度算子的模板和为0则不必除法);
(4)将上述运算结果(模板的响应输出)赋给输出图像中模板中心位置对应的像素。
其实梯度图的生成和模板卷积是一样的,只是不同的是,生成梯度图需要计算模板卷积完成后该点梯度的幅度,以该幅度作为像素值,从而完成计算。。
下图显示了用于生成渐变图的水平模板和垂直模板:
例如,如果只想生成水平方向的渐变图,那么只计算水平方向的渐变,渐变图上对应点的灰度值为
一般水平方向用一个模板,垂直方向用一个模板,然后合并,那么该点的渐变图灰度值为
就是我们上面说的梯度的幅度,以2为范数计算,对应的是欧氏距离。因为涉及平方和和平方根运算,所以计算量比较大。如何简化计算?改成近似的计算方法!!!)
在计算实际坡度图输出时,采用了一种简单的计算方法,定额为1(对应于市区距离),即
另一个简单的方法是取为规范(对应于棋盘距离),即
首先了解下梯度算子的设计,一般是横平竖直。水平模板转置后对折,就是垂直方向。
其本质是一个对角梯度算子,对应的水平和垂直梯度为
输出渐变图的灰度值为
优点:边缘定位准确
缺点:(1)没有描述水平和垂直方向的灰度变化,只关注对角线方向,容易造成遗漏。(2)鲁棒性差。由于点本身参与梯度计算,不能有效地抑制噪声干扰。
适用于边缘明显、噪点较少的图像。
Prewitt算子是典型的模板,其模板中心对应需要梯度的原始图像坐标,对应的8邻域像素灰度值如下表所示:
通过Prewitt算子的水平模板卷积后,对应的水平梯度为
通过Prewitt算子的垂直模板进行卷积后,对应的垂直梯度为
输出渐变图的灰度值为
Prewitt算子引入了类似于局部平均的运算,对噪声有平滑作用,比Roberts算子更能抑制噪声。
通过Prewitt算子的水平模板卷积后,对应的水平梯度为
通过Prewitt算子的垂直模板进行卷积后,对应的垂直梯度为
输出渐变图的灰度值为
Sobel算子引入了类似于局部加权平均的运算,其边缘定位比优于Prewitt算子。
Python调用OpenCV接口实现Sobel算子边缘检测。