python边缘提取_OpenCV+Python边缘检测

Sobel算子

sobel算子计算的是图像的一阶梯度。灰度值变化越快的地方,梯度越大,如下图所示。

一阶导数

dst = cv2.Sobel(img, ddepth, dx, dy, k_size)

# ddepth: dst的图像深度,一般使用 cv2.CV_64F

# dx = 1, dy = 0 表示x方向上的梯度

# dx = 0, dy = 1 表示y方向上的梯度

# k_size 默认是3, 当k_size设为-1时,会使用3x3的scharr算子,这个算子的实现精度比Sobel更高

使用Sobel算子进行边缘检测的一般步骤:

计算x方向的一阶梯度Gx

计算y方向的一阶梯度Gy

计算G = |Gx|+|Gy|, 当G大于一个阈值时,判定为边缘点

其实可以直接传dx = 1, dy = 1。和上面步骤的结果不太一样,进过实验,分三步的效果更好,见本文最后实例部分。

拉普拉斯算子

拉普拉斯算子是图像的二阶导数,如下图所示,一阶导数的极值位置,二阶导数为0。所以我们也可以用这个特点来作为检测图像边缘的方法。 但是, 二阶导数的0值不仅仅出现在边缘(它们也可能出现在无意义的位置),但是可以过滤掉这些点。

二阶导数

对于二维离散信号:

则:

对应的mask:

当考虑对角线元素时,mask也可以是:

cv2.Laplacian(img, cv2.CV_64F)

相对于Sobel算子,拉普拉斯算子做的是团块检测(周边高、低于中心点)、像素值快速变化的区域。

Sobel和Laplacian实例

import cv2

from matplotlib import pyplot as plt

import cv2

from matplotlib import pyplot as plt

img = cv2.imread('../laugh.jpg', 0)

# 先降噪

img = cv2.bilateralFilter(img, 21, 75, 75)

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

sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)

sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)

sobelxy = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=3)

sobelxy5 = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=5)

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

sherr = cv2.addWeighted(cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=-1), 0.5, cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=-1), 0.5, 0)

# 把所有结果映射回uint8

laplacian = cv2.convertScaleAbs(laplacian)

sobelxy = cv2.convertScaleAbs(sobelxy)

sobelxy5 = cv2.convertScaleAbs(sobelxy5)

sobelx = cv2.convertScaleAbs(sobelx)

sobely = cv2.convertScaleAbs(sobely)

sobel = cv2.convertScaleAbs(sobel)

sherr = cv2.convertScaleAbs(sherr)

titles = ['Original', 'Laplacian', 'Sobel dx=1 ksize=3', 'Sobel dy=1 ksize=3', 'Sobel ksize=3', 'Sobel dx=dy=1 ksize=3',

'Sherr', 'Sobel dx=dy=1 ksize=5']

imgs = [img, laplacian, sobelx, sobely, sobel, sobelxy, sherr, sobelxy5]

for i in range(8):

plt.subplot(3, 3, i + 1), plt.imshow(imgs[i], cmap='gray')

plt.title(titles[i]), plt.xticks([]), plt.yticks([])

plt.show()

Sobel和Laplacian效果图

Canny边缘检测

cv2.Canny(img, low_thresh, high_thresh)

算法

高斯滤波平滑图像

用Sobel算子计算出一阶偏导,以及各个像素点的梯度方向

对梯度值进行非最大值抑制(non-maximum suppression),只保留那些比其梯度方向上前后两个像素的梯度都大的像素。直观的表现是瘦化了边缘

滞后阈值处理

一般的边缘检测算法用一个阈值来滤除噪声或颜色变化引起的小的梯度值,而保留大的梯度值。Canny算法应用双阈值,即一个高阈值和一个低阈值来区分边缘像素。如果边缘像素点梯度值大于高阈值,则被认为是强边缘点。如果边缘梯度值小于高阈值,大于低阈值,则标记为弱边缘点。小于低阈值的点则被抑制掉。

所有像素点标记完滞后,针对每个弱边缘点,检查其周围8个连通领域像素,只要有强边缘点存在,则保留该边缘点,否则抛弃。

实例

import cv2

from matplotlib import pyplot as plt

img = cv2.imread('laugh.jpg', 0)

canny = cv2.Canny(img, 100, 200)

titles = ['Original','canny']

imgs = [img, canny]

for i in range(2):

plt.subplot(1, 2, i + 1), plt.imshow(imgs[i], cmap='gray')

plt.title(titles[i]), plt.xticks([]), plt.yticks([])

plt.show()

canny效果图

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值