当前位置: 首页 > 文档资料 > OpenCV 中文文档 >

4.6 图像梯度

优质
小牛编辑
129浏览
2023-12-01

目标

在这一章中,我们将学习:

  • 查找图像梯度,边缘等。
  • 我们将学习以下函数:cv2.Sobel()cv2.Scharr()cv2.Laplacian()等。

理论基础

OpenCV提供了三种类型的梯度滤波器或高通滤波器,Sobel,Scharr和Laplacian。

我们会一一介绍它们。

1. Sobel和Scharr导数

Sobel算子是一个联合了高斯平滑和差分的运算,因此它更能抵抗噪声。 您可以指定要取导数的方向,垂直方向或者水平方向(分别通过参数 yorder 和 xorder)。 你也可以通过参数 ksize 来指定内核的大小。 如果 ksize = -1,则使用3x3 Scharr滤波器,其结果比 3x3 Sobel 滤波器更好。 请参阅文档来看看使用的内核的特性。

2. 拉普拉斯导数

它计算由 $\Delta src = \frac{\partial ^2{src}}{\partial x^2} + \frac{\partial ^2{src}}{\partial y^2}$ 给出的,图像的拉普拉斯算子,其中每个导数都是用Sobel导数计算的,如果 ksize=1,则使用以下内核进行过滤:

$$
kernel = \begin{bmatrix} 0 & 1 & 0 \ 1 & -4 & 1 \ 0 & 1 & 0 \end{bmatrix}
$$

代码

下面的代码在单个图表中显示了所有操作的运算结果。 所有内核都是 5x5 大小。 输出图像的深度传递-1以得到 np.uint8 类型的结果。

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

img = cv2.imread('dave.jpg',0)
laplacian = cv2.Laplacian(img,cv2.CV_64F)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5)
plt.subplot(2,2,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,2),plt.imshow(laplacian,cmap = 'gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,3),plt.imshow(sobelx,cmap = 'gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])
plt.subplot(2,2,4),plt.imshow(sobely,cmap = 'gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])
plt.show()

一件重要的事

在我们的最后一个例子中,输出数据类型是 cv2.CV_8U 或 np.uint8。 但是有一个小问题。 黑白转换为正斜率(正值),白转黑转换为负斜率(负值)。 所以当你把数据转换成np.uint8时,所有的负斜率都会变成零。 简而言之,你会忽略了这个边缘。

如果黑到白和白到黑两边你都想检测,更好的选择是保持输出数据类型的一些更多位数的形式,如cv2.CV16Scv2.CV64F等,取其绝对值,然后转换回 cv2.CV_8U

下面的代码演示了水平Sobel滤波器的这个过程和结果的差异。

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

img = cv2.imread('box.png',0)

# Output dtype = cv2.CV_8U
sobelx8u = cv2.Sobel(img,cv2.CV_8U,1,0,ksize=5)

# Output dtype = cv2.CV_64F. Then take its absolute and convert to cv2.CV_8U
sobelx64f = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5)
abs_sobel64f = np.absolute(sobelx64f)
sobel_8u = np.uint8(abs_sobel64f)

plt.subplot(1,3,1),plt.imshow(img,cmap = 'gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,2),plt.imshow(sobelx8u,cmap = 'gray')
plt.title('Sobel CV_8U'), plt.xticks([]), plt.yticks([])
plt.subplot(1,3,3),plt.imshow(sobel_8u,cmap = 'gray')
plt.title('Sobel abs(CV_64F)'), plt.xticks([]), plt.yticks([])

plt.show()

更多资源