OpenCV 图像梯度 Sobel、Scharr、Laplacian

本文详细介绍了OpenCV中用于图像梯度检测的Sobel、Scharr和Laplacian算子,解释了它们的原理和使用方法。通过示例代码展示了如何使用OpenCV实现这些算子,并讨论了不同图像深度对结果的影响。最后,给出了实际应用中处理图像边缘检测和梯度计算的注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念:

梯度简单来说就是求导,在图像上表现出来的就是提取图像的边缘(不管是横向的、纵向的、斜方向的等等),所需要的无非也是一个核模板,模板的不同结果也不同。所以可以看到,所有的这些个算子函数,归结到底都可以用函数cv2.filter2D()来表示,不同的方法给予不同的核模板,然后演化为不同的算子而已。

OpenCV提供了三种梯度过滤器(高通过滤器)-Sobel、Scharr、Laplacian。

一、Sobel算子与Scharr算子

Sobel算子是高斯平滑与微分操作的结合体,所以其抗噪能力很强,用途较多。一般的sobel算子包括x与y两个方向,算子模板为: 

 在opencv函数中,还可以设置卷积核(ksize)的大小,如果ksize=-1,就演变为3*3的Scharr算子,模板无非变了个数字: 

二、Laplacian(拉普拉斯)算子

其模板为:

 三、Sobel算子函数

函数原型:

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

参数

  前四个是必须的参数: 

  1. src - 需要处理的图像

  2.  ddepth - 图像的深度,-1表示采用的是与原图像相同的深度。目标图像的深度必须大于等于原图像的深度

  3.  dx - 对x轴方向求导的阶数,一般为0、1、2,其中0表示这个方向上没有求导

  4.  dy - 对y轴方向求导的阶数,一般为0、1、2,其中0表示这个方向上没有求导

  其后是可选的参数: 

  5.  dst - 目标图像

  6.  ksize - Sobel算子的大小,必须为1、3、5、7

  7.  scale -  缩放导数的比例常数,默认情况下没有伸缩系数

  8.  delta - 可选增量, 将会加到最终的dst中,同样,默认情况下没有额外的值加到dst中

  9.  borderType - 图像边界的模式。这个参数默认值为cv2.BORDER_DEFAULT

四、简单实现

import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt

if __name__ == '__main__':

    img = cv.imread('1.png',0)
    # cv2.IMREAD_COLOR:默认参数,读入一副彩色图片,忽略alpha通道,可以直接写1
    # cv2.IMREAD_GRAYSCALE:读入灰度图片,可以直接写0
    # cv2.IMREAD_UNCHANGED:顾名思义,读入完整图片,包括alpha通道,可以直接写-1

    # laplacion 梯度
    laplacian_64f = cv.Laplacian(img,cv.CV_64F)
    # 在经过处理后,需要用convertScaleAbs()函数将其转回原来的uint8形式,否则将无法显示图像,而只是一副灰色的窗口
    laplacian_8u = cv.convertScaleAbs(laplacian_64f)
    # abs_laplacian_64f = np.absolute(laplacian_64f)
    # # 转换为cv.CV_8U
    # laplacian_8u = np.uint8(abs_laplacian_64f)


    # Sobel 梯度 x 方向
    sobelx_64f = cv.Sobel(img,cv.CV_64F,1,0,ksize=5)
    sobelx_8u = cv.convertScaleAbs(sobelx_64f)
    # Sobel 梯度 y 方向
    sobely_64f = cv.Sobel(img,cv.CV_64F,0,1,ksize=5)
    sobely_8u = cv.convertScaleAbs(sobely_64f)

    plt.subplot(2,2,1),plt.imshow(img,cmap = 'gray')
    plt.subplot(2,2,2),plt.imshow(laplacian_8u,cmap = 'gray')
    plt.subplot(2,2,3),plt.imshow(sobelx_8u,cmap = 'gray')
    plt.subplot(2,2,4),plt.imshow(sobely_8u,cmap = 'gray')
    plt.show()

输出结果:

 

五、小结

在上面的例子中(original图),(imshow)输出数据类型(图像深度)是cv2.CV_8U或者是np.uint8。

但是由于输出数据类型[python-灰度:0是黑、1是白],当有正梯度的时候,会出现黑白变换,同样,当有负梯度的时候,会导致白黑变换。因此,当输出图像深度为np.uint8时,python 会让所有的负梯度自动变为0。简单的说就是丢失边缘

如果想要获得所有的边缘,就需要提高图像深度,将输出图像数据类型变成更高格式,比如cv2.CV_16S或者cv2.CV_64F等,然后取绝对值,再转换为cv2.CV_8U。下面的代码将展示这个流程,对一副图片进行水平Sobel过滤,不同的图像深度会导致不同的结果。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_yuki_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值