14 圖像梯度
目標
- 圖像梯度/圖像邊界
- 使用到的函數有:cv2.Sobel(),cv2.Schar(),cv2.Laplacian()
原理
- 圖像梯度簡單來說就是求導。
- Opencv 提供了高通濾波器:Sobel,Scharr 和 Laplacian
- Sobel 算子是高斯平滑與微分操作的結合體,所以它的抗噪聲能力很好。
- 拉普拉斯算子可以使用二階導數的形式定義,可假設其離散實現類似於二階 Sobel 導數
import cv2 import numpy as np from matplotlib import pyplot as plt img=cv2.imread('opencv.jpg',0) #cv2.CV_64F 輸出圖像的深度(數據類型),可以使用-1, 與原圖像保持一致 np.uint8 laplacian=cv2.Laplacian(img,cv2.CV_64F) # 參數 1,0 爲只在 x 方向求一階導數,最大可以求 2 階導數。 sobelx=cv2.Sobel(img,cv2.CV_64F,1,0,ksize=5) # 參數 0,1 爲只在 y 方向求一階導數,最大可以求 2 階導數。 sobely=cv2.Sobel(img,cv2.CV_64F,0,1,ksize=5) sobelx2=cv2.Sobel(img,cv2.CV_64F,2,0,ksize=5) # 參數 0,1 爲只在 y 方向求一階導數,最大可以求 2 階導數。 sobely2=cv2.Sobel(img,cv2.CV_64F,0,2,ksize=5) fig = plt.figure(figsize =(18, 10)) plt.subplot(3,2,1),plt.imshow(img,cmap = 'gray') plt.title('Original'), plt.xticks([]), plt.yticks([]) plt.subplot(3,2,2),plt.imshow(laplacian,cmap = 'gray') plt.title('Laplacian'), plt.xticks([]), plt.yticks([]) plt.subplot(3,2,3),plt.imshow(sobelx,cmap = 'gray') plt.title('Sobel X'), plt.xticks([]), plt.yticks([]) plt.subplot(3,2,4),plt.imshow(sobely,cmap = 'gray') plt.title('Sobel Y'), plt.xticks([]), plt.yticks([]) plt.subplot(3,2,5),plt.imshow(sobelx2,cmap = 'gray') plt.title('Sobel 2X'), plt.xticks([]), plt.yticks([]) plt.subplot(3,2,6),plt.imshow(sobely2,cmap = 'gray') plt.title('Sobel 2Y'), plt.xticks([]), plt.yticks([]) plt.show()
注意:
- 我們可以通過參數 -1 來設定輸出圖像的深度(數據類型)與原圖像保持一致,
- 但是我們在代碼中使用的卻是 cv2.CV_64F。這是爲什麼呢?
- 想象一下一個從黑到白的邊界的導數是整數,而一個從白到黑的邊界點導數卻是負數。
- 如果原圖像的深度是np.int8 時,所有的負值都會被截斷變成 0,換句話說就是把把邊界丟失掉。
- 所以如果這兩種邊界你都想檢測到,最好的的辦法就是將輸出的數據類型設置的更高,比如 cv2.CV_16S,cv2.CV_64F 等。
- 取絕對值然後再把它轉回到 cv2.CV_8U。
下面的示例演示了輸出圖片的深度不同造成的不同效果。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('opencv.jpg',0)
# Output dtype = cv2.CV_8U
sobelx8u = cv2.Sobel(img,cv2.CV_8U,1,0,ksize=5)
# 也可以將參數設爲-1
#sobelx8u = cv2.Sobel(img,-1,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)
fig = plt.figure(figsize =(18, 10))
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()