Opencv笔记(十三)——图像的梯度

目标

  • 认识图像梯度、边界
  • 学习函数cv2.Sobel(),cv2.Schar(),cv2.Laplacian()

原理

  图像梯度可以把图像看成二维离散函数,图像梯度其实就是这个二维离散函数的求导。OpenCV提供三种类型的梯度滤波器或高通滤波器,Sobel,Scharr和Laplacian.

Sobel 和 Scharr 算子

Sobel算子是结合了高斯平滑与微分运算的结合方法,所以它的抗噪声能力很强,其是普通一阶差分,是基于寻找梯度强度。每一个算子分别对应这x和y这两个方向的模板,故在代码中要分别在两个方向上处理,最后用cv2.addWeighted(...)函数将其组合起来。

Sobel算子

Sobel函数原型如下:

cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]])

前四个是必须的参数:

  • 第一个参数是需要处理的图像;
  • 第二个参数是图像的深度(数据类型),-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度;
  • dx和dy表示的是求导的阶数,0表示这个方向上没有求导,一般为0、1、2;

其后是可选的参数:

  • ksize是Sobel算子的大小,必须为1、3、5、7。如果ksize=-1,那么一个3*3的scharr滤波器会被使用;
  • delta是一个可选的增量,将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中;
  • borderType是判断图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT;

Laplacian算子

拉普拉斯算子是常用的边缘检测算子,它是各向同性的二阶导数。

计算公式卷积核

代码实践

Sobel算子:

# coding=utf-8
import cv2
import numpy as np

img = cv2.imread("/home/wl/1.jpg", 0)

x = cv2.Sobel(img, cv2.CV_16S, 1, 0)
y = cv2.Sobel(img, cv2.CV_16S, 0, 1)

absX = cv2.convertScaleAbs(x)  # 转回uint8
absY = cv2.convertScaleAbs(y)

dst = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)

while(1):
    cv2.imshow("absX", absX)
    cv2.imshow("absY", absY)
    cv2.imshow("Result", dst)
    k = cv2.waitKey(1) & 0XFF
    if k==ord('q'):
        break;
cv2.destroyAllWindows()

原图:

效果图:

Laplacian算子:

# coding=utf-8
import cv2
import numpy as np

img = cv2.imread("/home/wl/1.jpg", 0)
laplacian=cv2.Laplacian(img,cv2.CV_64F)
dst = cv2.convertScaleAbs(laplacian) #转回uint8
while(1):
    cv2.imshow("Result",dst)
    k = cv2.waitKey(1) & 0XFF
    if k==ord('q'):
        break;
cv2.destroyAllWindows()

效果图:

注意点

   代码看了的话,会发现我们的sobel函数的第二个参数(数据类型)会换成cv2.CV_16S或cv2.CV_64F,最后再变回uint8。这是因为从黑到白的边界点的导数是正数,而从白到黑是负数,如果还是使用uint8,那么所有的负数都会变为0,即被截断。

猜你喜欢

转载自blog.csdn.net/wzyaiwl/article/details/81274930