上一篇介紹了 Adaptive Threshold。
現在,我們已經可以把圖片分成前景和背景。
不過,有時候會發現結果常常沒有想像中漂亮。
例如文字旁邊多了一些小黑點,或是有些地方出現零星的白點。
甚至原本完整的物體,中間還出現了一些小洞。
雖然完成了二值化,但圖片看起來還是很凌亂。
這時候,就需要有一個方法把這些小瑕疵整理乾淨。
這就是今天要介紹的 Morphology(形態學)。
Morphology 處理的是物體的形狀。
它會觀察每個 Pixel 周圍的區域,決定這個 Pixel 應不應該保留下來。
因此它經常出現在 Threshold、Segmentation、OCR 等流程之後。
目的就是讓結果更乾淨、更完整。
Morphology 有一個很重要的概念。
叫做 Structuring Element(結構元素)。
它其實就是一個小小的模板。
例如最常見的是:
1 1 1
1 1 1
1 1 1
或是
0 1 0
1 1 1
0 1 0
Morphology 每次處理圖片時,都會把這個模板放到每個 Pixel 上,然後觀察周圍的情況。
因此 Structuring Element 可以想像成 Morphology 用來觀察附近 Pixel 的放大鏡。
第一個操作叫做 Erosion。
它會讓白色區域慢慢縮小。
假設原本有一個小方塊:
□□□□□
□□□□□
□□□□□
做一次 Erosion 可能變成:
□□□
□□□
因為邊界附近的 Pixel 沒有足夠多的白色鄰居,所以被移除了。
Erosion 很適合:
例如:
如果圖片中只有一兩個孤立 Pixel,Erosion 很快就會把它們消除。
但是如果做太多次,真正的物體也會一起變小,甚至完全消失。
另一個操作叫做 Dilation。
它剛好和 Erosion 相反。
Dilation 會讓白色區域慢慢長大。
例如。
□□□
□□□
做一次 Dilation 可能變成:
□□□□□
□□□□□
□□□□□
因此,物體的邊界會向外擴張。
Dilation 很適合:
例如 OCR 前常常會先做 Dilation。
讓原本快斷掉的文字重新連接,提高辨識成功率。
OpenCV 也提供了型態學的對應函式。
先建立一個 Structuring Element。
import cv2
import numpy as np
kernel = np.ones((3, 3), np.uint8)
接著做一次 Erosion。
eroded = cv2.erode(binary, kernel, iterations=1)
以及 Dilation。
dilated = cv2.dilate(binary, kernel, iterations=1)
其中 iterations 代表重複執行的次數。
次數越多,效果越明顯。
顯示結果:
plt.figure(figsize=(12, 4))
plt.subplot(1, 3, 1)
plt.imshow(binary, cmap="gray")
plt.title("Binary")
plt.axis("off")
plt.subplot(1, 3, 2)
plt.imshow(eroded, cmap="gray")
plt.title("Erosion")
plt.axis("off")
plt.subplot(1, 3, 3)
plt.imshow(dilated, cmap="gray")
plt.title("Dilation")
plt.axis("off")
plt.tight_layout()
plt.show()
執行結果如下:

| 操作 | 效果 | 常見用途 |
|---|---|---|
| Erosion | 白色區域縮小 | 去除小白點、分離物體 |
| Dilation | 白色區域擴大 | 補裂縫、連接線條、填補缺口 |
它們看起來互相相反,但其實經常一起使用。
很多 Morphology 操作都是由它們組合而成。
今天介紹了 Morphology。
它針對二值化後的結果,調整物體的形狀。
其中,Erosion 會讓物體縮小,適合去除雜訊。
Dilation 則會讓物體擴大,適合填補缺口與連接斷裂。
不過,如果我們想同時做到 去除小雜訊,但又不要讓物體永久縮小,或是 **填補小洞,但又不要讓整個物體一直變胖,只靠 Erosion 或 Dilation 都做不到。
下一篇,我們就來看看如何把這兩個操作組合起來,介紹 Opening 與 Closing,以及更多常見的 Morphology 方法。