|

【影像處理】如何使用OpenCV進行捲積操作

   
作者:曾成訓(CH.Tseng)

影像處理(image processing)與電腦視覺(computer vision)是兩個讓人常常聯想在一起的名詞,同樣都是接收影像資訊,兩者的差異反映在最終結果:影像處理輸出的是「處理後的影像」,電腦視覺輸出的是「圖像中的資訊」。這兩種不同的技術運用,實際上卻是唇齒相依息息相關,電腦視覺需要影像處理來解析更多的資訊;同樣的,影像處理為了滿足電腦視覺的需求,也發展出各種更深更廣的技術,以期能深入剖析影像,取得更多的特徵與資訊。

今天要帶大家來了解,如何使用 OpenCV 進行捲積(Convolution)的影像處理技術。但在開始之前,我們需要先了解以下幾個電腦術語:

  1. Image Patch:指的是影像中以某一點為中心的一小塊區域(大小如 3×3、5×5 等)。
  2. Low Frequency Information:指平坦、單調、無太多紋理、邊緣、邊角等特徵,例如:「An image patch is said to have low frequency information」。
  3. High Frequency Information:與 Low Frequency 相反,有很多的紋理、邊緣、邊角等特徵。
  4. Low Pass Filtering:Low Pass 指的是 blurring(模糊)、smoothing(平滑)等動作;Low Pass Filtering 指讓影像中 Low Frequency 的資訊通過,阻隔 High Frequency 的部份。
  5. High Pass Filtering:High Pass 指的是 sharpening(銳化)或 edge enhancement(邊緣強化)等動作;High Pass Filtering 指阻卻影像中 Low Pass 的部份,讓 High Pass 的資訊通過。

認識 Image Filtering

當我們需要強化影像中的某些特徵並消除其他不想要的特徵,所採用的方法便是使用特定 kernel,針對整張進行捲積(convolution)操作。舉例來說,模糊(blur)、邊緣偵測(edge detection)、邊緣強化(edge enhancement)、噪點去除(noise removal)等,都是使用 kernel 針對影像進行捲積的結果。

kernel 指的是一個固定尺寸的窗格(如 3×3),在影像處理中,我們稱該窗格為 kernel 或 filter。若由左上到右下移動,使用該 kernel 針對影像重疊區域進行運算,最終便會得出一幅經過 filtered 的新影像,這樣的動作稱為捲積(convolution)。目前最流行的 CNN 進行的就是 image filtering 的工作。

如下圖所示,藍色 grid 為定義的 3×3 kernel,在捲積過程進行中,底下覆蓋區域(圖中的紅色的 grid)與 kernel 進行交乘加總後(下方的 output pixel),將作為輸出新圖中該 kernel 區域的中心點;若由左上至右下重複進行上述步驟,輪巡整張圖片後就會得到右邊的圖形。

使用 kernel 針對影像進行捲積的結果(圖片來源:曾成訓提供)

執行 convolution 後,會發現有一個很明顯的特性,就是輸出的圖片尺寸會比原來的小一圈,一般我們會採取四種方式來處理此特性:

  1. Ignore the boundary pixels:忽略消失的邊界影像,直接使用輸出的圖片。
  2. Zero padding:先在原圖周圍填補一圈為 0 的像素,再進行捲積,使輸出的圖片尺寸不變。
  3. Replicate border:直接複製原圖最邊界的 pixels 到輸出的圖周圍,例如:aaaaaa 🡨 abcdefgh 🡪 hhhhhhh
  4. Reflect border:與 Replicate border 類似,但複製的方式是對稱方式 copy,例如:fedcba 🡨 abcdefgh 🡪 hgfedcb

使用 OpenCV 進行捲積操作

OpenCV 內建了非常方便的捲積指令 filter 2D,只要先定義好使用的 kernel,便可直接進行捲積,我們來試看看。(後文中所指的 kernel 與 filter 都是指用於捲積的過濾窗格)

import numpy as np

import cv2

import imutils

import sys

# cv2.IMREAD_COLOR為imread的預設值,此參數亦可不加。

imageName = "DSCF3454.jpg"

image = cv2.imread(imageName, cv2.IMREAD_COLOR)

#若無指定圖片則結束程式。

if image is None:

print("Could not open or find the image")

sys.exit()

#縮小圖片到較適當尺寸。

image = imutils.resize(image, height=450)

# 設定kernel size為5x5

kernel_size = 5

# 使用numpy建立 5*5且值為1/(5**2)的矩陣作為kernel。

kernel = np.ones((kernel_size, kernel_size), dtype=np.float32) / kernel_size**2

# 顯示矩陣內容,所有值皆為0.04的5x5矩陣

print (kernel)

# 使用cv2.filter2D進行convolute,

result = cv2.filter2D(image, dst=-1, kernel=kernel, anchor=(-1, -1), delta=0, borderType=cv2.BORDER_DEFAULT)

cv2.imshow("Filter", result)

cv2.imshow("Original", image)

cv2.waitKey(0)

  • 程式中定義的 kernel

程式中所使用的 filter 有「模糊化圖片」的功能 ,所產生的 kernel 如下圖所示:

本文為會員限定文章

立即加入會員! 全站文章無限看~

                               

已經是會員? 按此登入

只需不到短短一分鐘...

輸入您的信箱與ID註冊即可享有一切福利!

會員福利
1

免費電子報

2

會員搶先看

3

主題訂閱

4

好文收藏

曾 成訓

Author: 曾 成訓

人到中年就像沒對準的描圖紙,一點一點的錯開,我只能當個Maker來使它復位。

Share This Post On

Submit a Comment

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *