14 opencv python 圖像梯度

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()

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章