[圖像處理] 進階二值化閥值處理技巧 (上)

Ben Hsu
10 min readMay 4, 2023

--

Otsu 是針對整張圖片的二值化閥值選擇方法,但當圖像出現汙染時,Otsu 不容易得到好的結果,需要先對圖像進行預處理,再進行二值化閥值篩選。本文為系列文上篇,說明在圖像出現雜訊時,應先使用濾波器進行預處理;而圖像帶有陰影時,則使用自適應濾波器進行分割。下篇則會討論Otsu的應用實例以及自適應閥值與邊緣分割的關係。文末提供python程式碼。

目錄

  1. 前言 — 特殊情況下的二值化分割處理
  2. 帶有隨機雜訊圖像的閥值篩選
    2.1 未加入雜訊
    2.2 加入雜訊後
    2.3 為什麼出現雜訊會影響二值化結果?
  3. 陰影、漸層圖像的閥值篩選:局部、自適應閥值
  4. 小結
  5. Reference

1. 前言 — 特殊情況下的二值化分割處理

這篇文章說明圖像分割的進階應用,當圖片出現汙染或要進行細微亮點物件分割時,可以怎樣處理?包含圖片帶有雜訊或陰影的二值化處理,分別對應到濾波、自適應閥值及圖像梯度等技巧。本篇文章需要先對二值化算法有一些了解,如果不清楚可以先看這篇文章

2. 帶有隨機雜訊圖像的閥值篩選

2.1 未加入雜訊

隨機雜訊是一種常見的圖像汙染,我們用圖1(a) 來說明,加入雜訊對Otsu分割會有怎樣的影響。未加入雜訊前,如圖1 (b),將閥值定在200,可以乾淨的將圓形分割,分割結果如圖1 (c)。

圖1. 由左而右依序為 (a) 圓形;(b) 灰度值分布圖;(c) 圖像分割結果

2.2 加入雜訊後

圖2. (±50 灰度值) 、圖3. (±100 灰度值)列出加入不同雜訊的分割結果與分佈圖,可以看到圖2(c) 灰度值±50雜訊的分割結果邊緣輪廓不完整,但圖2(b) 分布圖仍可以找到一個不錯的分割點在180附近;但圖3(c) 灰度值±100的雜訊,因為雜訊的灰度值已經與中央的圓形重疊,所以圓外也有許多點被切割進去。

圖2. 由左而右依序為 (a) 圓形加入±50 灰度值;(b) 灰度值分布圖;(c) 圖像分割結果
圖3. 由左而右依序為 (a) 圓形加入±100 灰度值;(b) 灰度值分布圖;(c) 圖像分割結果

2.3 為什麼出現雜訊會影響二值化結果?

雜訊是否會影響分割結果,取決於加入的雜訊是否會影響數值的分布。從圖1 (b) ,可以看到圖像的灰度值分布在兩個區間,分別介於70–160,與240–250。兩分布差值約為90,表示當雜訊超過±45時,會讓兩個分佈的界線消失,無法準確分割出圖形。

上述隨機雜訊的問題,可以使用中值濾波器來處理,中值濾波可過濾範圍內的離群值,有效處理隨機雜訊。圖4.、圖5. 分別是對平均±50雜訊、平均±100雜訊圖像經過中值濾波處理的切割情形。與圖2. 未濾波前進行比較,可以看到濾波後的分布圖 (圖4(a)、圖5(a))更接近沒有雜訊的分布圖 (圖1(b)),切割結果也都獲得改善。

圖4. 由左而右依序為 (a) 雜訊50 中值濾波後的灰度值分布圖 (b) 後的圖像分割結果
圖5. 由左而右依序為 (a) 雜訊 100 中值濾波後的灰度值分布圖 (b) 圖像分割結果
import cv2
import urllib
import urllib.request
import numpy as np

import matplotlib
import matplotlib.pyplot as plt

req = urllib.request.urlopen('https://i.imgur.com/QP0rp2R.jpg')
arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
img = cv2.imdecode(arr, -1)
img = cv2.resize(img, (500, 500))
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

### 幫圖片加個雜訊
noise_ar_100 = np.random.uniform(-100, 100, 500*500).reshape([500,500])
img_gray_addnoise100 = cv2.add(img_gray, noise_ar_100, dtype=cv2.CV_8UC3)

### 圖像分布情形
def image_hist_plot(image, n):
plt.imshow(image, cmap='gray', vmin=0, vmax=255);plt.axis('off')
plt.show()
plt.hist(image.ravel(), 256, [0,256])
plt.ylim(0, n)
plt.show()

image_hist_plot(img_gray_addnoise100, 2000)

### Otsu分割情形
def Otsu_result_plot(img):
ret, th = cv2.threshold(img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
regions = np.digitize(img.astype(np.int), bins=np.array([ret]))
plt.imshow(regions, cmap='gray'); plt.axis('off')
plt.show()

Otsu_result_plot(img_gray_addnoise100)

3. 陰影、漸層圖像的閥值篩選:局部、自適應閥值

圖6(a) 是一個有陰影的漸層圓型,這個陰影的出現,讓Otsu切割的結果不完整,如圖6(b),當遇到這種圖片亮度不均的情形,就需要針對不同亮度的區域進行閥值篩選。

下面的範例將針對單一點進行閥值篩選,再套用至整張圖像。

圖6 由左而右依序為 (a) 帶有陰影的圓形;(b) 陰影圖像切割結果

例如,決定圖7(a) 紅色點 (x, y) 的閥值,需要經過下列步驟:

  1. 設定一個 kernel size,如圖7(a) 紅框的大小可以是3×3、5×5、7×7。
  2. 使用紅框內的灰度值,計算平均數mu(x, y) 作為基準值。此處平均數可以替換為其他統計量。
  3. 設定一個常數 c 作為閥值的偏移量
  4. 紅色點 (x, y) 的閥值 可以表示為 T(x, y) = mu(x, y) + c
  5. 比較紅色點 (x, y) 的灰度值是否超過 T(x, y),超過則定義為分割點
  6. 重複1–5步驟,掃過整張圖片,結果如圖7 (b)
圖7. 由左而右依序為 (a) 區域門檻篩選示意圖;(b) 自適應閥值篩選結果
### 讀入照片
req = urllib.request.urlopen('https://imgur.com/AX3EH43.jpg')
arr = np.asarray(bytearray(req.read()), dtype=np.uint8)
img = cv2.imdecode(arr, -1)
img = cv2.resize(img, (500, 500))
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

### 製作漸層圖像
n1, n2 = 50, 200
N = n2 - n1
linear_gradient_ar = np.array(list(range(n1, n2)) * N).reshape([N, N]).astype('float32')
linear_gradient_ar = cv2.resize(linear_gradient_ar, (500, 500))
plt.imshow(img_gray_addgrad, cmap='gray', vmin=0, vmax=255);plt.axis('off')
plt.show()

### Otsu分割
cut_value, th = cv2.threshold(img_gray_addgrad, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

### 繪製切割結果 => 結果不理想
ret, dst = cv2.threshold(img_gray_addgrad, cut_value, 255, cv2.THRESH_BINARY)
plt.imshow(dst, cmap='gray', vmin=0, vmax=255);plt.axis('off')

### 自適應閥值結果
def adaptiveThreshold_plot(para):
dst_mean = cv2.adaptiveThreshold(img_gray_addgrad, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, para ,3)
plt.imshow(dst_mean, cmap='gray', vmin=0, vmax=255);plt.axis('off')
plt.show()

### 比較不同參數下自適應閥值結果
adaptiveThreshold_plot(15)
adaptiveThreshold_plot(31)
adaptiveThreshold_plot(61)
adaptiveThreshold_plot(121)

4. 小結

本文說明了雜訊會對二值化分割帶來的影響,並說明使用中值濾波器時,能改善分割效果。而亮度在圖像上不均勻時,應該使用自適應閥值,對圖像上的每個位置設置各別的閥值。下篇將使用案例展示Otsu與自適應閥值的差異,並討論自適應閥值與sobel、Laplacian濾波器的差異。

5. Reference

  1. Gonzalez, Rafael C. Digital image processing. Pearson education india, 2018.
  2. OpenCV adaptiveThreshold

--

--