1.影像梯度

影像梯度計算的是影像變化的速度,影像中越平滑的地方,梯度越小。反之,梯度越大,像是邊緣。常見的計算梯度的運算元(濾波器)主要有Sobel、Scharr、Laplacian。

實作重點在於,為避免資訊遺失,先將影像深度轉換成cv2.CV_64F,再透過取絕對值將其對應為cv2.CV_8U


1.1. Sobel

1.1.1. Sobel說明

一種離散的微分運算元,結合了微分求導與高斯平滑之運算。利用局部差分尋找邊緣,所求得的是一個梯度近似值。

dst = cv2.Sobel(src, ddpeth, dx, dy, kernel_size, scale)

  • dst為輸出影像,src為輸入影像
  • ddepth為輸出影像深度,通常為避免資訊在計算時遺失,常設為CV_64F。
  • dx為x方向上求導階數、dy為y方向上求導階數。
  • kernel_size為Sobel濾波器大小。當設為 -1 時,會使用Scharr濾波器。


下圖第一列的圖像影像深度為cv2.CV_64F,第二列的圖像影像深度為cv2.CV_8U。

<source:Greatway9999>

1.1.2. 完整程式

import numpy as np

import cv2

img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE)


# Sobel:一種離散的微分運算元,結合了微分求導與高斯平滑之運算。利用局部差分尋找邊緣,所求得的是一個梯度近似值。

#dst = cv2.Sobel(src, ddpeth, dx, dy, kernel_size, scale)

# dst為輸出影像,src為輸入影像

# ddepth為輸出影像深度,通常為避免資訊在計算時遺失,常設為CV_64F。

# dx為x方向上求導階數、dy為y方向上求導階數。

# kernel_size為Sobel濾波器大小。當設為 -1 時,會使用Scharr濾波器。


img_Sobel_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize = 3)

img_Sobel_y = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize = 3)

img_Sobel_xy = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize = 3)


img_Sobel_x_cvt = cv2.convertScaleAbs(img_Sobel_x) #為了避免資訊遺失,計算時先使用cv2.CV_64F,再透過取絕對值將其對應為cv2.CV_8U

img_Sobel_y_cvt = cv2.convertScaleAbs(img_Sobel_y)

img_Sobel_xy_cvt = cv2.addWeighted(img_Sobel_x_cvt, 0.5, img_Sobel_y_cvt, 0.5, 0)


cv2.imshow('img', img)

cv2.imshow('img_Sobel_x', img_Sobel_x)

cv2.imshow('img_Sobel_y', img_Sobel_y)

cv2.imshow('img_Sobel_xy', img_Sobel_xy)


cv2.imshow('img_Sobel_x_cvt', img_Sobel_x_cvt)

cv2.imshow('img_Sobel_y_cvt', img_Sobel_y_cvt)

cv2.imshow('img_Sobel_xy_cvt', img_Sobel_xy_cvt)


cv2.waitKey()

cv2.destroyAllWindows()


1.2. Scharr

1.2.1. Scharr說明

用法同Sobel,而精度更高。

img_Scharr_x = cv2.Scharr(img, cv2.CV_64F, 1, 0)

另一種寫法,將kernel_size設為 -1 ,則會使用Scharr濾波器,如下所示。

img_Scharr_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, -1) 


另外要注意的地方為dx和dy不能同時為1,因為會有error。

<source:Greatway9999>

1.2.2. 完整程式

#Scharr:用法同Sobel,而精度更高。

import numpy as np

import cv2

img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE)


img_Scharr_x = cv2.Scharr(img, cv2.CV_64F, 1, 0)

#img_Scharr_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, -1) #另一種寫法,將kernel_size設為 -1 ,則會使用Scharr濾波器。

img_Scharr_y = cv2.Scharr(img, cv2.CV_64F, 0, 1) 

#img_Scharr_xy = cv2.Scharr(img, cv2.CV_64F, 1, 1) #會有error,因為dx和dy不能同時為1。


img_Scharr_x_cvt = cv2.convertScaleAbs(img_Scharr_x) #為了避免資訊遺失,計算時先使用cv2.CV_64F,再透過取絕對值將其對應為cv2.CV_8U

img_Scharr_y_cvt = cv2.convertScaleAbs(img_Scharr_y)

img_Scharr_xy_cvt = cv2.addWeighted(img_Scharr_x_cvt, 0.5, img_Scharr_y_cvt, 0.5, 0)


cv2.imshow('img', img)

cv2.imshow('img_Scharr_x', img_Scharr_x)

cv2.imshow('img_Scharr_y', img_Scharr_y)

#cv2.imshow('img_Scharr_xy', img_Scharr_xy)


cv2.imshow('img_Scharr_x_cvt', img_Scharr_x_cvt)

cv2.imshow('img_Scharr_y_cvt', img_Scharr_y_cvt)

cv2.imshow('img_Scharr_xy_cvt', img_Scharr_xy_cvt)


cv2.waitKey()

cv2.destroyAllWindows()


1.3. Laplacian

1.3.1. Laplacian說明

具有旋轉不變性,可滿足不同方向邊緣銳化之需求。

<source:Greatway9999>

1.3.2. 完整程式

# Laplacian,具有旋轉不變性,可滿足不同方向邊緣銳化之需求。

import numpy as np

import cv2

img = cv2.imread('Lenna.jpg', cv2.IMREAD_GRAYSCALE)


img_Laplacian = cv2.Laplacian(img, cv2.CV_64F)

img_Laplacian_cvt = cv2.convertScaleAbs(img_Laplacian)

cv2.imshow('img', img)

cv2.imshow('img_Laplacian', img_Laplacian)

cv2.imshow('img_Laplacian_cvt', img_Laplacian_cvt)


cv2.waitKey()

cv2.destroyAllWindows()


#影像梯度 #Sobel #Scharr #Laplacian

---

參考資料:

0 留言