一、原理
無論是膨脹還是腐蝕,都是對白色區域(明亮區域)而言的。膨脹或者腐蝕操作都會有一個核,核的形狀可以是圓形或者正方形,核在輸入圖像上滑動。膨脹是用核與二值圖像元素做“與”運算,如果都為0,那麼目标像素點為0,否則為1,這樣的将會擴大1的區域,達到膨脹白色區域(明亮區域)的目的。腐蝕操作則相反,如果核與其覆寫區域都為1,那麼目标像素點為1,否則為0,這樣達到的效果是白色區域(明亮區域)會被削減,即腐蝕。

二、對灰階圖或者二值圖
對于灰階圖和二值圖:
膨脹:
膨脹可以擴大細節性特征,如:
左圖是原圖,我們可以看到周邊其實是有一小圈紅色圈的,經過膨脹操作後,即右圖,紅色圈更明顯了。而且也符合膨脹原理,右圖更加強調了明亮區域。
而且膨脹還有去除噪聲的作用,如下圖:
左邊是原圖,經過膨脹操作後,很多小點都沒了,當然比較大的點還是有的,(下面會有更好的解決方法)。但是也可以通過修改疊代次數來解決這個問題,疊代次數就是核在在圖檔上周遊的次數,若疊代次數為1,那核就會從左到右,上到下劃完整張圖檔一次,若疊代次數是 2,則會滑2次。一般預設的疊代次數是1。那我們看看把疊代次數修改成2後的效果:
黑洞是沒了,但是可以看到,整個 j 也大了不少,因為膨脹了兩次嘛。
腐蝕:
腐蝕可以去掉細節性特征:
如下圖:
我們可以看到,一些毛刺沒了,但是 j 也變得更小了,當然腐蝕也是可以增加疊代次數的。
我們看到下圖,通過一次疊代後,一些細線沒了。
然後我們試試把疊代次數改成8.
我們可以看到,連比較粗的線條都沒有了。
三,對RGB圖:
膨脹:
對于RGB圖而言,膨脹會更多地保留明暗區域。(疊代次數為1)
疊代次數為5:
腐蝕:
對于RGB圖而言,腐蝕則是更多地保留暗區域:(疊代次數為1)
疊代次數為5:
四,膨脹和腐蝕代碼:
膨脹代碼:
import cv2
import numpy as np
src = cv2.imread(r'C:\Users\Administrator\Desktop\pic\car.jpg')
kernel = np.ones((5,5),np.uint8) #設定核的尺寸為 5x5
dialate = cv2.dilate(src,kernel,iterations=5)
cv2.imshow("src",src)
cv2.imshow("result",dialate)
cv2.waitKey(0)
cv2.destroyAllWindows()
腐蝕代碼:
import cv2
import numpy as np
src = cv2.imread(r'C:\Users\Administrator\Desktop\pic\car.jpg')
kernel = np.ones((5,5),np.uint8) #設定核的尺寸為 5x5
erosion = cv2.erode(src,kernel,iterations=1)
#print(erosion)
cv2.imshow("src",src)
cv2.imshow("result",erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()
五,開運算和閉運算
1)開運算:先對圖像腐蝕後膨脹。
作用:消除主體外的瑕疵部分,但不改變主體物體大小,不像腐蝕,雖然腐蝕可以消除瑕疵部分,但是主體部分也會變小。
但是開運算不适宜消除主體内的瑕疵:
可以看到,對主體内的瑕疵,開運算的效果并不行。
對于RGB圖檔,開運算的先腐蝕再膨脹,會使明亮部分丢失,是以圖檔會比較凸顯顔色較暗的特征:
代碼:
import cv2
import numpy as np
src = cv2.imread(r'C:\Users\Administrator\Desktop\pic\holej.jpg')
kernel = np.ones((5,5),np.uint8) #設定核的尺寸為 5x5
res = cv2.erode(src,kernel,iterations=1) #腐蝕
res = cv2.dilate(res,kernel,iterations=1) #膨脹
cv2.imshow("src",src)
cv2.imshow("result",res)
cv2.waitKey(0)
cv2.destroyAllWindows()
2)閉運算:先對圖像膨脹後腐蝕
作用:用來填充物體内的小空洞,連接配接鄰近的物體,連接配接斷開的輪廓線,平滑其邊界的同時不改變面積。
但是可以見到還是有瑕疵,我們接着把,腐蝕和膨脹的疊代次數提高到2:
可以看到瑕疵空洞已經沒了。
對于RGB圖檔,閉運算的先膨脹再腐蝕,會使明亮部分增強,是以圖檔會比較凸顯顔色較亮的特征:
代碼:
import cv2
import numpy as np
src = cv2.imread(r'C:\Users\Administrator\Desktop\pic\car.jpg')
#src = cv2.resize(src,(512,512))
kernel = np.ones((5,5),np.uint8) #設定核的尺寸為 5x5
res=src
res = cv2.dilate(res,kernel,iterations=1)
res = cv2.erode(res,kernel,iterations=1)
cv2.imshow("src",src)
cv2.imshow("result",res)
cv2.waitKey(0)
cv2.destroyAllWindows()
六、黑帽和頂帽
1)黑帽:
黑帽圖像 = 閉運算圖像 - 原圖像
作用:得到前景中的瑕疵(小孔)
對于RGB圖檔:
代碼:
import cv2
import numpy as np
def black_hat_demo(image):
'黑帽'
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
kernel = np.ones((5, 5), np.uint8)
open = cv2.erode(cv2.dilate(gray,kernel,iterations=2),kernel,iterations=2)
cv2.imshow("close",open)
#黑帽處理
dst=cv2.morphologyEx(gray,cv2.MORPH_BLACKHAT,kernel,iterations=2)
cv2.imshow('black_hat',dst)
src = cv2.imread(r'C:\Users\Administrator\Desktop\pic\holej.jpg')
cv2.imshow("src", src)
black_hat_demo(src)
cv2.waitKey(0)
cv2.destroyAllWindows()
2)頂帽
頂帽圖像 = 原始圖像 - 開運算圖像
作用:得到前境外的瑕疵
對于RGB圖檔:
代碼:
import cv2
import numpy as np
def top_hat_demo(image):
'頂帽'
gray=cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
kernel = np.ones((5, 5), np.uint8)
open = cv2.dilate(cv2.erode(gray, kernel, iterations=2), kernel, iterations=2)
cv2.imshow("open", open)
dst = cv2.morphologyEx(gray, cv2.MORPH_TOPHAT, kernel, iterations=2)
cv2.imshow('top_hat', dst)
src = cv2.imread(r'C:\Users\Administrator\Desktop\pic\car.jpg')
src = cv2.resize(src,(512,512))
cv2.imshow("src", src)
top_hat_demo(src)
cv2.waitKey(0)
cv2.destroyAllWindows()