3.6. 图像梯度¶
3.6.2. 理论¶
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
,然后使用以下内核进行筛选:
\[\begin{split}\begin{aligned}
kernel = \begin{bmatrix} 0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0 \end{bmatrix}
\end{aligned}\end{split}\]
3.6.3. 代码¶
下面的代码显示了一个图表中的所有运算符。所有的内核都是5x5大小。输出图像的深度通过-1得到np.uint8类型的结果。
>>> %matplotlib inline
>>> import cv2
>>> import numpy as np
>>> from matplotlib import pyplot as plt
>>>
>>> img = cv2.imread('/cvdata/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()

结果:
3.6.4. 一件重要的事!¶
在上一个示例中,输出数据类型是cv2.CV_8U或np.uint8。但有一个小问题。黑白过渡为正斜率(有正值),黑白过渡为负斜率(有负值)。因此,当您将数据转换为np.uint8时,所有负斜率都设为零。简单地说,你错过了这一点。
如果要检测两条边,更好的选择是将输出数据类型保持为一些更高的形式,如cv2.CV s、cv2.CV f等,取其绝对值,然后转换回cv2.CV u。下面的代码演示了水平Sobel筛选器的此过程和结果差异。
>>> import cv2
>>> import numpy as np
>>> from matplotlib import pyplot as plt
>>>
>>> img = cv2.imread('/cvdata/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()

检查以下结果: