OpenCV-Python实践之图像梯度算子

图像梯度算子简介

  相信只要是懂些图像处理的知识,都知道图像梯度的含义。不知道是否考虑过为什么图像梯度如此广泛认知与使用?为什么不使用图像纹理、图像色彩、图像相位等等,在这里我并不是说上述除了图像梯度之外,其它的图像信息不重要,我只是想说图像梯度最为广泛的被研究与使用。下面我们来看一幅图像:

OpenCV-Python实践之图像梯度算子_第1张图片

  从上图坐标为灰度图像,右边为Laplacian算子提取的图像梯度图;现在我们来看一下左边图片中的A、B、C、D、E、F区域,你可以通过这些子区域发现处于图像中的哪个位置吗?通过人眼观察可以轻易得出结果:E、F最容易分辨,C、D能够确定更小的范围区域,A、B最难分辨在哪个范围。OK,让我们来看右边的梯度算子,可以发现:E、F小区域在梯度图像上较为完整的保留下来,C、D保留边缘曲线,A、B已经完全发现不出什么明显的特征。

  通过上述一个简单的观察,你会发现:E、F是角点区域(梯度各个方向变化最为明显),C、D为边缘区域(梯度垂直于边缘方向最为明显)、A、B为平坦区域(梯度各个方向变化都不明显)。这不就是后面做特征点检测的信息丰富度准则,角点最为稳定、边缘检测等特征。图像梯度提取最为简单直接,能够有效的描述图像的原始状态,因此发展一系列的图像梯度算子:Roberts、Prewitt、Sobel、Laplacian、Scharr等。下面介绍一下比较经常使用的梯度提取算子卷积核函数:

Sobel算子:

W s o b e l x = [ w 00 w 01 w 02 w 10 w 11 w 12 w 20 w 21 w 22 ] = [ − 1 0 + 1 − 2 0 + 2 − 1 0 + 1 ] W_{sobelx}= \left[ \begin{matrix} w_{00} & w_{01} & w_{02} \\ w_{10} & w_{11} & w_{12} \\ w_{20} & w_{21} & w_{22} \end{matrix} \right] = \left[ \begin{matrix} -1 & 0 & +1 \\ -2 & 0 & +2 \\ -1 & 0 & +1 \end{matrix} \right] Wsobelx=w00w10w20w01w11w21w02w12w22=121000+1+2+1

W s o b e l y = [ w 00 w 01 w 02 w 10 w 11 w 12 w 20 w 21 w 22 ] = [ − 1 − 2 − 1 0 0 0 + 1 + 2 + 1 ] W_{sobely}= \left[ \begin{matrix} w_{00} & w_{01} & w_{02} \\ w_{10} & w_{11} & w_{12} \\ w_{20} & w_{21} & w_{22} \end{matrix} \right] = \left[ \begin{matrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\ +1 & +2 & +1 \end{matrix} \right] Wsobely=w00w10w20w01w11w21w02w12w22=10+120+210+1

分别为Sobel算子针对 X X X Y Y Y方向提取的图像,然后对梯度图像:
(1) G i m a g e = G x 2 + G y 2 G_{image}=\sqrt{G^{2}_x+G^{2}_y}\tag{1} Gimage=Gx2+Gy2 (1)

  参数解释: G i m a g e G_{image} Gimage为Sobel算子提取的梯度图像, G x G_x Gx W s o b e l x W_{sobelx} Wsobelx卷积核与原始图像卷积提取X方向的结果, G y G_y Gy W s o b e l y W_{sobely} Wsobely卷积核与原始图像卷积提取 Y Y Y方向的结果。

Scharr算子:

W s c h a r r x = [ w 00 w 01 w 02 w 10 w 11 w 12 w 20 w 21 w 22 ] = [ − 3 0 + 3 − 10 0 + 10 − 3 0 + 3 ] W_{scharrx}= \left[ \begin{matrix} w_{00} & w_{01} & w_{02} \\ w_{10} & w_{11} & w_{12} \\ w_{20} & w_{21} & w_{22} \end{matrix} \right] = \left[ \begin{matrix} -3 & 0 & +3 \\ -10 & 0 & +10 \\ -3 & 0 & +3 \end{matrix} \right] Wscharrx=w00w10w20w01w11w21w02w12w22=3103000+3+10+3

W s c h a r r y = [ w 00 w 01 w 02 w 10 w 11 w 12 w 20 w 21 w 22 ] = [ − 3 − 10 − 3 0 0 0 + 3 + 10 + 3 ] W_{scharry}= \left[ \begin{matrix} w_{00} & w_{01} & w_{02} \\ w_{10} & w_{11} & w_{12} \\ w_{20} & w_{21} & w_{22} \end{matrix} \right] = \left[ \begin{matrix} -3 & -10 & -3 \\ 0 & 0 & 0 \\ +3 & +10 & +3 \end{matrix} \right] Wscharry=w00w10w20w01w11w21w02w12w22=30+3100+1030+3

Scharr算子与Sobel算子原理一致,只是改进版,效果要比Sobel好些。

Laplacian算子:

  拉普拉斯算子是最广为人知的算子,完全的尺度不变性,依赖二阶导数能够提取稳定的特征点,著名的差分高斯近似加速等等。其提取图像特征的核函数为:

W l a p l a c i a n = [ w 00 w 01 w 02 w 10 w 11 w 12 w 20 w 21 w 22 ] = [ 0 1 0 1 − 4 1 0 1 0 ] W_{laplacian}= \left[ \begin{matrix} w_{00} & w_{01} & w_{02} \\ w_{10} & w_{11} & w_{12} \\ w_{20} & w_{21} & w_{22} \end{matrix} \right] = \left[ \begin{matrix} 0 & 1 & 0 \\ 1 & -4 & 1 \\ 0 & 1 & 0 \end{matrix} \right] Wlaplacian=w00w10w20w01w11w21w02w12w22=010141010

  利用卷积核与图像进行卷积运算,以此来提取图像梯度。关于卷积操作具体解释可以参考图像滤波算法系列实战总结之一博文开头卷积示例图片,抱歉暂无找到引用何处,发现后会添加上。

OpenCV-Python代码实践
import cv2
import numpy as np
from matplotlib import pyplot as plt

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

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 = np.sqrt(sobelx*sobelx + sobely*sobely)

scharrx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=-1)
scharry = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=-1)

scharrxy = np.sqrt(scharrx*scharrx + scharry*scharry)


plt.subplot(2, 4, 1), plt.imshow(img, cmap='gray')
plt.title('Original'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 4, 2), plt.imshow(laplacian, cmap='gray')
plt.title('Laplacian'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 4, 3), plt.imshow(sobelx, cmap='gray')
plt.title('Sobel X'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 4, 4), plt.imshow(sobely, cmap='gray')
plt.title('Sobel Y'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 4, 5), plt.imshow(scharrx, cmap='gray')
plt.title('Scharr X'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 4, 6), plt.imshow(scharry, cmap='gray')
plt.title('Scharr Y'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 4, 7), plt.imshow(sobelxy, cmap='gray')
plt.title('Sobel XY'), plt.xticks([]), plt.yticks([])

plt.subplot(2, 4, 8), plt.imshow(scharrxy, cmap='gray')
plt.title('Scharr XY'), plt.xticks([]), plt.yticks([])

plt.show()
实验结果
参考

https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_gradients/py_gradients.html

你可能感兴趣的:(OpenCV实践,sobel,scharr,laplacian,图像梯度)