s1093705 作業二
線條自畫像 (二值化與邊緣偵測 Image Thresholding and Edge Detection)
題目說明:
撰寫一個程式,以灰階模式讀取一張圖像 imread(path, IMREAD_GRAYSCALE)
(a)利用Sobel Operators 偵測並輸出邊緣成分圖
(b)設計一個類似素描線條的自畫像圖案。
開發環境:
- Windows 11
- Visual Studio Code
- Python 3.11.2
- Opencv 4.7.0
實作結果:
Sobel Operators 偵測邊緣圖 |
實作Demo:
程式說明:
本題利用 cv2.createTrackbar() 和 cv2.getTrackbarPos() 來控制以下變數,來尋找邊緣偵測的最佳參數:
- A: 用 cv2.threadhold() ,將圖形顏色較淡的地方,去除小於A 的值,A 以上的值維持不變。
- B:用高斯分佈進行模糊化的計算,指定模糊區域單位 BxB。
- C:用 cv2.threadhold() ,去除小於 C 的值,C 以上的值維持不變,以達到加強邊緣線的效果。
- D:
(a)利用Sobel Operators 偵測並輸出邊緣成分圖
1. 先將圖形顏色較淡的地方,用 cv2.threadhold() 去除,此例是去除小於A 的值,A 以上的值維持不變,
參數介紹: (Reference)
v2.THRESH_BINARY | 如果大於 A 就等於 255,反之等於 0。 |
cv2.THRESH_BINARY_INV | 如果大於 A 就等於 0,反之等於 255。 |
cv2.THRESH_TRUNC | 如果大於 A 就等於 127,反之數值不變。 |
cv2.THRESH_TOZERO | 如果大於 A 數值不變,反之數值等於 0。 |
cv2.THRESH_TOZERO_INV | 如果大於 A 等於 0,反之數值不變。 |
ret, image = cv2.threshold(image, A, 255, cv2.THRESH_TOZERO)
ret, image = cv2.threshold(image, A, 255, cv2.THRESH_TOZERO)
2. 使用 cv2.GaussianBlur() 方法,使用高斯分佈進行模糊化的計算,指定模糊區域單位 ( 必須是大於 1 的奇數 ) ,此範例是BxB:
blur_image = cv2.GaussianBlur(image, (B,B), sigmaX=0, sigmaY=0)
該算子包含兩組3x3的矩陣,分別為橫向及縱向,將之與圖像作平面
卷積,即可分別得出橫向及縱向的亮度差分近似值。
卷積,即可分別得出橫向及縱向的亮度差分近似值。
sobel_x = cv2.Sobel(blur_image, cv2.CV_16S, 1, 0, ksize=3, scale=1, delta=0,
borderType=cv2.BORDER_DEFAULT)
sobel_y = cv2.Sobel(blur_image, cv2.CV_16S, 0, 1, ksize=3, scale=1, delta=0,
borderType=cv2.BORDER_DEFAULT)
取其絕對值:
abs_sobel_x = cv2.convertScaleAbs(sobel_x)
abs_sobel_y = cv2.convertScaleAbs(sobel_y)
將 x軸和 y軸算出的梯度,利用各50%的權重權重相加:
edge_image = cv2.addWeighted(abs_sobel_x, 0.5, abs_sobel_y, 0.5, 0)
4. 最後再用二值化 cv2.threadhold(),數值大於 C 就等於 255,反之等於 0,來加強邊緣線:
ret, edge_image = cv2.threshold(edge_image, C, 255, cv2.THRESH_BINARY)
(b)設計一個類似素描線條的自畫像圖案
方法一:利用 (a) 的邊緣偵測結果,做 cv2.bitwise_not,達到我們對於素描的印象—白底的畫布上,有著簡單的灰階線條,描述圖形簡單的線條輪廓。
sketch_image = cv2.bitwise_not(edge_image)
方法二: 先用 cv2.GaussianBlur() 方法,使用高斯分佈進行模糊化的計算,指定DxD的模糊區域單位,此處D的值越大,素描圖繪越清晰:
接著用 cv2.divide(),將原圖與高斯模糊圖做相除,就會有十分逼真的素描圖。
blur_image = cv2.GaussianBlur(image, (D,D), sigmaX=0, sigmaY=0)
sketch_image = cv2.divide(image, blur_image, scale=256)
留言
張貼留言