二十 形態學操作
阿新 • • 發佈:2018-11-01
介紹
形態學操作其實就是改變物體的形狀,比如腐蝕就是”變瘦”,膨脹就是”變胖”,看下圖就明白了
形態學操作一般作用於二值化圖,來連線相鄰的元素或分離成獨立的元素。腐蝕和膨脹是針對圖片中的白色部分!
主要是應用在二值影象分析中,灰度影象亦可。
可以看做膨脹是將白色區域擴大,腐蝕是將黑色區域擴大
一、膨脹與腐蝕
相關函式
def getStructuringElement(shape, ksize, anchor=None): # real signature unknown; restored from __doc__
第一個引數shape:表示核心的形狀,有三種形狀可以選擇
矩形:MORPH_RECT; 交叉形:MORPH_CORSS; 橢圓形:MORPH_ELLIPSE;
第二個引數ksize:是核心的尺寸(n,n)
第三個引數anchor:錨點的位置
getStructuringElement函式會返回指定形狀和尺寸的結構元素。
1、腐蝕erode
腐蝕的效果是把圖片”變瘦”,其原理是在原圖的小區域內取區域性最小值。因為是二值化圖,只有0和255,所以小區域內有一個是0該畫素點就為0,這樣原圖中邊緣地方就會變成0,達到了瘦身目的。
OpenCV中用cv2.erode()
函式進行腐蝕,只需要指定核的大小就行:
img = cv2.imread('j.bmp', 0) kernel = np.ones((5, 5), np.uint8) erosion = cv2.erode(img, kernel) # 腐蝕
這個核也叫結構元素,因為形態學操作其實也是應用卷積來實現的。結構元素可以是矩形/橢圓/十字形,可以用cv2.getStructuringElement()
來生成不同形狀的結構元素,比如:
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) # 矩形結構 kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) #橢圓結構 kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5)) # 十字形結構
程式碼實現
1 import cv2 as cv 2 import numpy as np 3 4 def erode_image(image): 5 print(image.shape) 6 gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY) 7 ret , binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU) #大律法獲取二值影象 8 cv.imshow('binary',binary) 9 kernel = cv.getStructuringElement(cv.MORPH_RECT,(3,3)) #可以修改卷積核大小來增加腐蝕效果,越大腐蝕越強 10 dst = cv.erode(binary,kernel) 11 cv.imshow('erode_demo',dst) 12 13 img = cv.imread('1.jpg') 14 cv.imshow('input image',img) 15 erode_image(img) 16 cv.waitKeyEx(0) 17 cv.destroyAllWindows()
2、膨脹dilate
膨脹與腐蝕相反,取的是區域性最大值,效果是把圖片”變胖”:
dilation = cv2.dilate(img, kernel) # 膨脹
程式碼實現
1 import cv2 as cv 2 import numpy as np 3 4 #膨脹就是白色部分變多 5 def dilate_image(image): 6 print(image.shape) 7 gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY) 8 ret , binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU) #大律法獲取二值影象 9 cv.imshow('binary',binary) 10 kernel = cv.getStructuringElement(cv.MORPH_RECT,(3,3)) #可以修改卷積核大小來增加腐蝕效果,越大膨脹越強 11 dst = cv.dilate(binary,kernel) 12 cv.imshow('dilate_demo',dst) 13 14 img = cv.imread('1.jpg') 15 cv.imshow('input image',img) 16 dilate_image(img) 17 cv.waitKeyEx(0) 18 cv.destroyAllWindows()
3、可以不進行灰度處理,對彩色圖片進行處理
(1)膨脹
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5)) dst = cv.dilate(src,kernel) cv.imshow("result",dst)
(2)腐蝕
kernel = cv.getStructuringElement(cv.MORPH_RECT, (5, 5)) dst = cv.erode(src,kernel) cv.imshow("result",dst)
二、開閉運算
1、開
先腐蝕後膨脹叫開運算(因為先腐蝕會分開物體,這樣容易記住),其作用是:分離物體,消除小區域。
特點:消除噪點,去除小的干擾塊,而不影響原來的影象
這類形態學操作用cv2.morphologyEx()
函式實現:
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5)) # 定義結構元素 img = cv2.imread('j_noise_out.bmp', 0) opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) # 開運算
程式碼實現
1 import cv2 as cv 2 import numpy as np 3 4 def camp(val1,val2): 5 pv = val1 + val2 6 if pv > 255: 7 return 255 8 elif pv < 0: 9 return 0 10 else: 11 return pv 12 13 def open_demo(image): 14 gray = cv.cvtColor(image,cv.COLOR_BGR2GRAY) #(h,w) = (576,1024) 15 print(gray.shape) 16 for i in range(1000): 17 h = np.random.random_integers(0,gray.shape[0]-1) #因為返回的是閉區間內的隨機整數,h是從0開始的,所以要減1 18 w = np.random.random_integers(0,gray.shape[1]-1) 19 value = np.random.random_integers(0,255) #隨機新增的畫素值 20 gray[h,w] = camp(gray[h,w],value) 21 ret , binary = cv.threshold(gray,0,255,cv.THRESH_BINARY|cv.THRESH_OTSU) 22 cv.imshow('binary',binary) 23 kernel = cv.getStructuringElement(cv.MORPH_RECT,(3,3)) 24 open = cv.morphologyEx(binary,cv.MORPH_OPEN,kernel) #開操作,先腐蝕後膨脹,會消除一些為1的白色噪點 25 cv.imshow('open_demo',binary) 26 27 img = cv.imread('1.jpg') 28 cv.imshow('input image',img) 29 open_demo(img) 30 cv.waitKey(0) 31 cv.destroyAllWindows()
2、閉
閉運算則相反:先膨脹後腐蝕(先膨脹會使白色的部分擴張,以至於消除/“閉合”物體裡面的小黑洞,所以叫閉運算)
img = cv2.imread('j_noise_in.bmp', 0) closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) # 閉運算
程式碼實現
如果我們的目標物體外面有很多無關的小區域,就用開運算去除掉;如果物體內部有很多小黑洞,就用閉運算填充掉