膨脹與腐蝕一般用於二值圖,也很好理解。但是對於灰度圖,顯然也存在腐蝕與膨脹,這是如何進行的呢?
可以使用OpenCV中的庫函數cv2.erode和cv2.dilate,但這次是探究其中的原理。
灰值形態學
結構元素(structure element)
$5 \times 5$結構元素示例:
(2)歐幾里得距離(Euclidean distance)
0 | 1 | 1 | 1 | 0 |
1 | 2 | 2 | 2 | 1 |
1 | 2 | 2 | 2 | 1 |
1 | 2 | 2 | 2 | 1 |
0 | 1 | 1 | 1 | 0 |
(2)城市街區距離(city block distance)
0 | 0 | 1 | 0 | 0 |
0 | 1 | 2 | 1 | 0 |
1 | 2 | 3 | 2 | 1 |
0 | 1 | 2 | 1 | 0 |
0 | 0 | 1 | 0 | 0 |
(3)棋盤距離(Chess board distance)
1 | 1 | 1 | 1 | 1 |
1 | 2 | 2 | 2 | 1 |
1 | 2 | 3 | 2 | 1 |
1 | 2 | 2 | 2 | 1 |
1 | 1 | 1 | 1 | 1 |
腐蝕(Erosion)
灰度圖像的腐蝕運算的數學定義為:
$(f\oplus b) = max\{f(s-x,t-y) + b(x,y)|(s-x,t-y) \in D_f;(x,y) \in D_b \}$
即加上權重后取最大值。
膨脹(Dilation)
數學定義:
$(f\circledast b) = min\{f(s-x,t-y) - b(x,y)|(s-x,t-y) \in D_f;(x,y) \in D_b \}$
即減去權重取最小值
在灰度形態學中,一般選擇平坦的結構元素。所謂“平坦”,就是指結構元素的高度為零,即b的值全為0,則上面兩個公式可以重寫為:
$$(f\oplus b) = max\{f(s-x,t-y)|(s-x,t-y) \in D_f;(x,y) \in D_b \}$$
$$(f\circledast b) = min\{f(s-x,t-y)|(s-x,t-y) \in D_f;(x,y) \in D_b \}$$
代碼
(寫得太丑了)
def my_dilation(img, kernel): ret = img.copy() l1 = int((kernel.shape[0] - 1) / 2) l2 = int((kernel.shape[1] - 1) / 2) for i in range(l1,img.shape[0]-l1): for j in range(l2,img.shape[1]-l2): values = [] for k1 in range(-l1, l1 + 1): for k2 in range(-l2, l2 + 1): v = int(img[i+k1][j+k2]) + int(kernel[k1+l1][k2+l2]) if v > 255: v = 255 values.append(v) ret[i][j] = max(values) return ret def my_erosion(img, kernel): ret = img.copy() l1 = int((kernel.shape[0] - 1) / 2) l2 = int((kernel.shape[1] - 1) / 2) for i in range(l1,img.shape[0]-l1): for j in range(l2,img.shape[1]-l2): values = [] for k1 in range(-l1, l1 + 1): for k2 in range(-l2, l2 + 1): v = int(img[i+k1][j+k2]) - int(kernel[k1+l1][k2+l2]) if v > 255: v = 255 values.append(v) ret[i][j] = min(values) return ret
參考鏈接:https://blog.csdn.net/guoyk1990/article/details/8134134