形態學操作 1.連通性
在圖像中,最小的單位是像素,每個像素周圍有8個鄰接像素,常見的鄰接關系有3種:4鄰接、8鄰接和D鄰接。分別如下圖所示:
4鄰接:像素p(x,y)的4鄰域是:(x+1,y);(x-1,y);(x,y+1);(x,y-1)
D鄰接:像素p(x,y)的D鄰域是:對角上的點 (x+1,y+1);(x+1,y-1);(x-1,y+1);(x-1,y-1),
8鄰接:像素p(x,y)的8鄰域是: 4鄰域的點 + D鄰域的點
2.形態學操作
形態學轉換是基于圖像形狀的一些簡單操作。它通常在二進制圖像上執行。腐蝕和膨脹是兩個基本的形態學運算符。然后它的變體形式如開運算,閉運算,禮帽黑帽等。
2.1 腐蝕和膨脹
腐蝕和膨脹是最基本的形態學操作,腐蝕和膨脹都是針對白色部分(高亮部分)而言的。
膨脹就是使圖像中高亮部分擴張,效果圖擁有比原圖更大的高亮區域;腐蝕是原圖中的高亮區域被蠶食,效果圖擁有比原圖更小的高亮區域。膨脹是求局部最大值的操作,腐蝕是求局部最小值的操作。
1)腐蝕
具體操作是:用一個結構元素掃描圖像中的每一個像素形態學圖像處理的基本運算,用結構元素中的每一個像素與其覆蓋的像素做“與”操作,如果都為1,則該像素為1,否則為0。如下圖所示,結構A被結構B腐蝕后:
腐蝕的作用是消除物體邊界點,使目標縮小,可以消除小于結構元素的噪聲點。
cv.erode(img,kernel,iterations)
參數:
img: 要處理的圖像
kernel: 核結構
iterations: 腐蝕的次數,默認是1
2)膨脹
具體操作是:用一個結構元素掃描圖像中的每一個像素,用結構元素中的每一個像素與其覆蓋的像素做“與”操作,如果都為0,則該像素為0,否則為1。如下圖所示,結構A被結構B腐蝕后:
作用是將與物體接觸的所有背景點合并到物體中,使目標增大,可添補目標中的孔洞。
cv.dilate(img,kernel,iterations)
參數:
img: 要處理的圖像
kernel: 核結構
iterations: 腐蝕的次數,默認是1
示例
我們使用一個5*5的卷積核實現腐蝕和膨脹的運算:
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 讀取圖像
img = cv.imread("./image/image3.png")
# 2 創建核結構
kernel = np.ones((5, 5), np.uint8)
# 3 圖像腐蝕和膨脹
erosion = cv.erode(img, kernel) # 腐蝕
dilate = cv.dilate(img,kernel) # 膨脹
# 4 圖像展示
fig,axes=plt.subplots(nrows=1,ncols=3,figsize=(10,8),dpi=100)
axes[0].imshow(img)
axes[0].set_title("原圖")
axes[1].imshow(erosion)
axes[1].set_title("腐蝕后結果")
axes[2].imshow(dilate)
axes[2].set_title("膨脹后結果")
plt.show()
2.2 開閉運算
開運算和閉運算是將腐蝕和膨脹按照一定的次序進行處理。 但這兩者并不是可逆的,即先開后閉并不能得到原來的圖像。
1)開運算
開運算是先腐蝕后膨脹,其作用是:分離物體,消除小區域。特點:消除噪點,去除小的干擾塊,而不影響原來的圖像。
2)閉運算
閉運算與開運算相反,是先膨脹后腐蝕,作用是消除/“閉合”物體里面的孔洞,特點:可以填充閉合區域。
示例
使用10*10的核結構對卷積進行開閉運算的實現。
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 讀取圖像
img1 = cv.imread("./image/image5.png")
img2 = cv.imread("./image/image6.png")
# 2 創建核結構
kernel = np.ones((10, 10), np.uint8)
# 3 圖像的開閉運算
cvOpen = cv.morphologyEx(img1,cv.MORPH_OPEN,kernel) # 開運算
cvClose = cv.morphologyEx(img2,cv.MORPH_CLOSE,kernel)# 閉運算
# 4 圖像展示
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,8))
axes[0,0].imshow(img1)
axes[0,0].set_title("原圖")
axes[0,1].imshow(cvOpen)
axes[0,1].set_title("開運算結果")
axes[1,0].imshow(img2)
axes[1,0].set_title("原圖")
axes[1,1].imshow(cvClose)
axes[1,1].set_title("閉運算結果")
plt.show()
2.3 禮帽和黑帽
禮帽運算
原圖像與“開運算“的結果圖之差,如下式計算:
因為開運算帶來的結果是放大了裂縫或者局部低亮度的區域,因此,從原圖中減去開運算后的圖,得到的效果圖突出了比原圖輪廓周圍的區域更明亮的區域,且這一操作和選擇的核的大小相關。
禮帽運算用來分離比鄰近點亮一些的斑塊。當一幅圖像具有大幅的背景的時候形態學圖像處理的基本運算,而微小物品比較有規律的情況下,可以使用頂帽運算進行背景提取。
黑帽運算
為”閉運算“的結果圖與原圖像之差。數學表達式為:
黑帽運算后的效果圖突出了比原圖輪廓周圍的區域更暗的區域,且這一操作和選擇的核的大小相關。
黑帽運算用來分離比鄰近點暗一些的斑塊。
cv.morphologyEx(img, op, kernel)
參數:
img: 要處理的圖像
op: 處理方式:若進行開運算,則設為cv.,若進行閉運算,則設為cv.
: 核結構
示例
import numpy as np
import cv2 as cv
import matplotlib.pyplot as plt
# 1 讀取圖像
img1 = cv.imread("./image/image5.png")
img2 = cv.imread("./image/image6.png")
# 2 創建核結構
kernel = np.ones((10, 10), np.uint8)
# 3 圖像的禮帽和黑帽運算
cvOpen = cv.morphologyEx(img1,cv.MORPH_TOPHAT,kernel) # 禮帽運算
cvClose = cv.morphologyEx(img2,cv.MORPH_BLACKHAT,kernel)# 黑帽運算
# 4 圖像顯示
fig,axes=plt.subplots(nrows=2,ncols=2,figsize=(10,8))
axes[0,0].imshow(img1)
axes[0,0].set_title("原圖")
axes[0,1].imshow(cvOpen)
axes[0,1].set_title("禮帽運算結果")
axes[1,0].imshow(img2)
axes[1,0].set_title("原圖")
axes[1,1].imshow(cvClose)
axes[1,1].set_title("黑帽運算結果")
plt.show()