python-opencv之图像梯度Sobel、Scharr、Laplacian算子边缘检测

Sobel算子

是离散微分算子(discrete differentiation operator),用来计算图像灰度的近似梯度,梯度越大越有可能是边缘。

Soble算子的功能集合了高斯平滑和微分求导,又被称为一阶微分算子,求导算子,在水平和垂直两个方向上求导,得到的是图像在X方法与Y方向梯度图像。

缺点:比较敏感,容易受影响,要通过高斯模糊(平滑)来降噪。Sobel算子并没有将图像的主体与背景严格地区分开来,换言之就是Sobel算子没有基于图像灰度进行处理,由于Sobel算子没有严格地模拟人的视觉生理特征,所以提取的图像轮廓有时并不能令人满意。

梯度计算:(在两个方向求导,假设被作用图像为 I)

水平变化: 将 I 与一个奇数大小的内核 Gx进行卷积。比如,当内核大小为3时, Gx的计算结果为:

垂直变化: 将:math:I 与一个奇数大小的内核 Gy进行卷积。比如,当内核大小为3时, Gy的计算结果为:
在这里插入图片描述
在图像的每一点,结合以上两个结果求出近似梯度:

在这里插入图片描述
有时也用下面更简单公式代替,计算速度快:(最终图像梯度)。

在这里插入图片描述

函数原型

cv2.Sobel( src, ddepth, dx, dy[,ksize[, scale[, delta[, borderType]]]] )
 dst 代表目标图像。
 src 代表原始图像。
 ddepth 代表输出图像的深度。
 dx 代表 x 方向上的求导阶数。
 dy 代表 y 方向上的求导阶数。
 ksize 代表 Sobel 核的大小。该值为-1 时,则会使用 Scharr 算子进行运算。
 scale 代表计算导数值时所采用的缩放因子,默认情况下该值是 1,是没有缩放的。
 delta 代表加在目标图像 dst 上的值,该值是可选的,默认为 0。
 borderType 代表边界样式。

在实际操作中,计算梯度值可能会出现负数。通常处理的图像
是 8 位图类型,如果结果也是该类型,那么所有负数会自动截断为 0,发生信息丢失。所以,为了避免信息丢失,我们在计算时使用更高的数据类型 cv2.CV_64F,再通过取绝对值将其映射为 cv2.CV_8U(8 位图)类型。
故此我们还需要调用convertScaleAbs()函数计算绝对值,并将图像转换为8位图进行显示。其算法原型如下:
convertScaleAbs(src[, dst[, alpha[, beta]]])
 dst 代表处理结果。
 src 代表原始图像。
 alpha 代表调节系数,该值是可选值,默认为 1。
 beta 代表调节亮度值,该值是默认值,默认为 0。

代码

import cv2
import matplotlib.pyplot as plt
import numpy as np

img =cv2.imread("./cycle.png",cv2.IMREAD_COLOR)
kernel = np.ones((5,5),np.uint8)
opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
cv2.imshow("opening",opening)

sobelx = cv2.Sobel(opening,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
cv2.imshow("sobelx",sobelx)

sobely = cv2.Sobel(opening,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
cv2.imshow("sobely",sobely)


sobel = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv2.imshow("sobel",sobel)

cv2.waitKey(0)
cv2.destroyAllWindows()

结果显示

扫描二维码关注公众号,回复: 16181451 查看本文章

在这里插入图片描述

Scharr算子

为了能够有效的提取出较弱的边缘,需要将像素值间的差距增大,因此引入Scharr算子。Scharr算子是对Sobel算子差异性的增强,因此两者之间的在检测图像边缘的原理和使用方式上相同。Scharr算子的边缘检测滤波的尺寸为3×3,因此也有称其为Scharr滤波器。可以通过将滤波器中的权重系数放大来增大像素值间的差异,Scharr算子就是采用的这种思想,其在X方向和Y方向的边缘检测算子如中所示
在这里插入图片描述

函数原型

Scharr(src, ddepth, dx, dy[, dst[, scale[, delta[, borderType]]]])
参数就不一一解释了,类似于sobel

Laplacian算子

laplacian 算子,从图中可以看出当前点的位置与周围4个点位置之差, 即周围四个点之和 - 4*当前位置像素点,这种算法容易受到噪声点的干扰,不存在x和y轴的计算过程
在这里插入图片描述

函数原型

cv2.Laplacian(src, ddepth)

代码实例

import cv2
import matplotlib.pyplot as plt
import numpy as np

img =cv2.imread("./lena.jpg",cv2.IMREAD_GRAYSCALE)

sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobel = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)

scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
scharry = cv2.convertScaleAbs(scharry)
scharr = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)

laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)

res = np.hstack((img,sobel,scharr,laplacian))
cv2.imshow("res",res)
cv2.waitKey(0)
cv2.destroyAllWindows()

结果展示

三种算子的结果与原图对比
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_38505858/article/details/126834804