Post

影像處理小白(二):影像邊緣偵測

本系列將紀錄影像處理小白從 0 開始學習 Python x OpenCV 的過程。
透過選修課一次次的作業把影像處理的基礎知識建立起來。

本次作業是將圖片轉換成灰階模式並使用 Sobel operator 繪製一張素描圖。

入門者可以參照上一篇: 影像處理小白(一):建立滑桿以旋轉圖片、裁切圖片
若好奇其他的作業可以參照 影像處理分類

功課要求

撰寫一個程式,以灰階模式讀取一張圖像 imread(path, IMREAD_GRAYSCALE)

  1. 利用 Sobel Operators 偵測並輸出邊緣成分圖
  2. 設計一個類似素描線條的自畫像圖案。

成果

邊緣偵測與素描線條展示

開發環境

OSEditorLanguageOpenCV
Windows 10Visual Studio CodePython 3.9.16OpenCV 4.5.4

實作

本次程式碼

使用的 library 如下:

1
2
3
import cv2
import matplotlib.pyplot as plt
import numpy as np

1/ 讀取灰階圖片

colored_img 用以展示彩色的原圖,而 cv2.imread(file_name, cv2.IMREAD_GRAYSCALE) 會以灰階模式讀入一張圖。

1
2
3
file_name = ".\\fig.jpg"
colored_img = cv2.imread(file_name)
gray_img = cv2.imread(file_name, cv2.IMREAD_GRAYSCALE)

上一個程式不同,這次的圖片輸出如下:
使用 result_img 儲存所有要顯示的圖片,一個個將他們貼到 plt 中,這裡帶入了 plt.axis("off") 隱藏 matplotlib 預設的 x 軸和 y 軸的刻度。

1
2
3
4
5
6
7
8
9
10
11
result_img = [colored_img]

fig = plt.figure()
def show_img():
    for i in range(0, len(result_img)):
        image_rgb = cv2.cvtColor(result_img[i], cv2.COLOR_BGR2RGB)
        fig.add_subplot(2, 2, i + 1)
        plt.imshow(image_rgb)
        plt.axis("off")

    plt.show()

2/ 邊緣成分圖

首先利用高斯模糊 (Gaussian blur) 去除雜訊(噪聲),使邊界更好檢測:

1
2
3
# 高斯模糊協助過濾雜訊
gray_img = cv2.GaussianBlur(gray_img,(3, 3), 0)
result_img.append(gray_img)

再利用索伯算子 (Sobel operaters) 提取 x 方向和 y 方向的邊界,之後將兩者的絕對值相加,獲得完整的邊緣成分圖。

1
2
3
4
5
6
7
8
9
# 提取 x 方向和 y 方向的邊緣
edge_x = cv2.Sobel(gray_img, cv2.CV_16S, 1, 0, 3)
edge_Y = cv2.Sobel(gray_img, cv2.CV_16S, 0, 1, 3)
# 轉換為 unit8 (提取絕對值)
abs_x = cv2.convertScaleAbs(edge_x) 
abs_y = cv2.convertScaleAbs(edge_Y)
# 將兩者取絕對值相加,獲得完整影像
edge_all = cv2.addWeighted(abs_x, 0.5, abs_y, 0.5, 0)
result_img.append(edge_all)

關於高斯模糊和索伯算子,日後我想寫篇文章給他們。

3/ 素描線條畫像

這裡簡單的使用 bitwise_not() 將邊緣成分圖黑白相反,使其看起來像素描:

1
2
sketch_img = cv2.bitwise_not(edge_all)
result_img.append(sketch_img)

最後使用 show_img() 展示成果。

總結

本篇使用高斯模糊去除雜訊、索伯算子提取邊界、bitwise_not()進行黑白反轉。
邊界提取是很實用的東西,例如分辨一張圖畫是寶可夢還是數碼寶貝 等。

參考資料

This post is licensed under CC BY 4.0 by the author.