[OpenCV筆記] 7. Image Gradients (影像梯度) 計算
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 留言