图像处理算法 之 梯度/边缘检测(Sobel算子,拉普拉斯算子,Canny等)

边缘检测

    • 一、一阶微分算子
      • 1.1 Sobel算子
      • 1.2 Scharr算子
        • OpenCV函数使用:
      • 1.3 Roberts算子
    • 二、二阶微分算子
      • 2.1 拉普拉斯算子
        • OpenCV函数使用
    • 三、Canny算法
      • 算法流程
      • OpenCV 函数使用

梯度是一个量变化的速度,在数学中通常使用求导、求偏导获取梯度或者某一方向上的梯度。
在数字图像中梯度可以看为像素值分别在x,y方向上的变化速度,因为数字图像的离散型,以及像素是最小处理单元的特性,求数字图像的梯度时,不需要求导,只需要进行加减运算即可。(其实就是求导的差分近似形式).如下图所示:
图像处理算法 之 梯度/边缘检测(Sobel算子,拉普拉斯算子,Canny等)_第1张图片

这就使得可以通过简单的卷积运算得到图像的边缘信息。
因此就有了一些基本的梯度算子:Sobel算子、Scharr算子、Roberts算子、拉普拉斯算子,都属于一阶微分算子

一、一阶微分算子

1.1 Sobel算子

在这里插入图片描述
如上式,G_x 与G_y 分别表示对图像A进行横向和纵向梯度检测得到的结果。(注意,是横向的梯度,不是横向的边缘
取二者平方和即可得到图像上每一点的梯度值,即在该点同时计算x方向与y方向的梯度。
在这里插入图片描述
该点的梯度方向可以通过取这两个值的比的反正切arctan得到:
在这里插入图片描述
前面也说了,Sobel算子并不是真正的导数,只是对函数的差分近似,或者说是局部拟合,而差分近似的阶数越高,拟合就更加准确。因此大的核能够更好的近似导数,可以消除部分噪声影响。但是导数变化比较剧烈时,核太大会导致结果偏差大。

1.2 Scharr算子

Scharr算子是Sobel算子的一种特殊形式。
其核的形式如下:
图像处理算法 之 梯度/边缘检测(Sobel算子,拉普拉斯算子,Canny等)_第2张图片
前面提到了,Sobel算子中核越大就能够更好的近似导数,准确度也更高。因此,在核比较小时如3×3时,Sobel核的准确度较差,使用Scharr算子代替3×3的Sobel核能够提高精度。因为加大了在x方向或y方向的权重,使得梯度角(梯度方向)不会距离x或y方向太远,因此误差也不会太大。例如,只求x方向的梯度时,核的中心点的x方向的两个权值远大于其它权值,这使得求得的梯度更靠近x方向,一定程度减小了误差。

OpenCV函数使用:

void cv::Sobel(
cv::InputArray src,
cv::OutputArray dst,
int ddepth, //输出图的深度或类型
int xorder, //求导顺序取值可为:0,1,2 。0表示不求导
int yorder, //同上
cv::Size ksize = 3,//核大小,必须为奇数
double scale = 1,
double delta = 0,
int borderType = cv::BORDER_DEFAULT
)

将ksize 设为cv::SCHARR可转为使用Scharr算子

1.3 Roberts算子

图像处理算法 之 梯度/边缘检测(Sobel算子,拉普拉斯算子,Canny等)_第3张图片
Roberts算子的核如上图所示,是一种简单的交叉差分算法,在求±45°的梯度时最有效。
相比于一般的水平竖直方向的差分算子,Roberts算子能够有效地保留边缘的角点,并且计算速度较快。缺点是对细节敏感导致对噪声也十分敏感。

一阶微分算子即是对图像的灰度变化情况进行求导,获得的边缘比较粗糙,并且信息较少。二阶微分算子是对灰度变化的导数求导,对灰度值变化更为敏感,获得的边缘更加准确。

二、二阶微分算子

2.1 拉普拉斯算子

拉普拉斯算子可由二阶导数定义:
在这里插入图片描述
而在数字图像中离散化,用二阶差分表示为:
图像处理算法 之 梯度/边缘检测(Sobel算子,拉普拉斯算子,Canny等)_第4张图片
所以拉普拉斯算子可以表示为:
在这里插入图片描述
其卷积核如下图所示:
图像处理算法 之 梯度/边缘检测(Sobel算子,拉普拉斯算子,Canny等)_第5张图片
拉普拉斯算子法其实是一种图像边缘增强算子,常用于图像锐化,在增强边缘的同时也增强了噪声,因此使用前需要进行平滑或滤波处理
如下图,可以看出,在函数值发生突变的情况时,二阶导数能够增强突变点与其两侧的对比度。在数字图像中就是图像边缘处得到了增强,因此实现了图像的锐化。
图像处理算法 之 梯度/边缘检测(Sobel算子,拉普拉斯算子,Canny等)_第6张图片

OpenCV函数使用

Void cv::Laplacian(
cv::InputArray src,
cv::OutputArray dst,
int ddepth,
cv::Size ksize = 3,
double scale = 1,
double delta = 0,
int borderType = cv::BORDER_DEFAULT
);

其实二阶微分算子还有LOG的,但其实和拉普拉斯算子差别不是特别大,就不再详细进行说明了

二阶微分算子检测的边缘更加准确,对边缘的定位能力更强。但是相较于一阶微分算子,不能保留梯度的方向信息,并且对噪声更为敏感。 1986年提出Canny算子能够较好的兼顾这几方面,成为最常用也最有效稳定的边缘检测算法。

三、Canny算法

算法流程

去噪。使用高斯滤波对图像进行平滑去除噪声。滤波详情可见
https://blog.csdn.net/qq_38574198/article/details/109030375
检测初始边缘。使用Sobel算子进行边缘检测,得到初始的边缘信息。
非极大值抑制细化。利用非极大值抑制算法,只保留局部极大梯度,抑制其它非极大的梯度。
在Sobel算子进行边缘检测后得到的边缘图可以视为梯度图,每个位置的梯度大小可以根据其灰度值得到
如图,点C处的梯度方向为蓝线,然后对比C点的灰度值与其正负梯度方向上相邻位置(点dTmp1和dTmp2)的灰度值,只有当C的灰度值大于其它两个点的灰度值时,才视C点为边缘点,否则将其置0. 而因为正负梯度方向上的位置不一定正对单个像素点,这两个位置的灰度值往往通过其相邻的点进行线性插值得到。例如g1,g2插值得到dTmp1的灰度值
图像处理算法 之 梯度/边缘检测(Sobel算子,拉普拉斯算子,Canny等)_第7张图片
双阈值筛选
定义一个高阈值和一个低阈值。梯度强度低于低阈值的像素点被抑制,不作为边缘点;高于高阈值的像素点被定义为强边缘,保留为边缘点;处于高低阈值之间的定义为弱边缘,留待进一步处理。
边缘连接(孤立点筛选)
因为还是有部分噪声的存在,噪声在梯度图中算是 “假边缘“。通常而言,由真实边缘引起的弱边缘像素点将连接到强边缘像素点,而噪声响应则未连接。通过查看弱边缘像素及其8个邻域像素,可根据其与强边缘的连接情况来进行判断。一般,可定义只要其中邻域像素其中一个为强边缘像素点,则该弱边缘就可以保留为强边缘,即真实边缘点。

OpenCV 函数使用

Void cv::Canny(
Cv::InputArray image, //输入图片,必须单通道格式
Cv::OutputArray edges, //输出
Double threshold1, //双阈值中的低阈值
Double threshold2, //高阈值
Int apertureSize = 3, //Sobel算子处理的核的大小
Bool L2gradient = false //计算方向梯度时使用1范数(快,精度较低)还是2范数(精度高)
)

你可能感兴趣的:(图像处理,1024程序员节,计算机视觉,opencv,canny算法,图像处理)