經過閾值化分割能夠獲得二值圖,但每每會出現圖像中物體形態不完整,變的殘缺,能夠經過形態學處理,使其變得豐滿,或者去除掉多餘的像素。經常使用的形態學處理算法包括:腐蝕,膨脹,開運算,閉運算,形態學梯度,頂帽運算和底帽運算。算法
1. 腐蝕ide
腐蝕操做相似於中值平滑,也有一個核,但不進行卷積運算,而是取核中像素值的最小值代替錨點位置的像素值,這樣就會使圖像中較暗的區域面積增大,較亮的的區域面積減少。若是是一張黑底,白色前景的二值圖,就會使白色的前景物體顏色變小,就像被腐蝕了同樣。函數
進行腐蝕操做的核,不只能夠是矩形,還能夠是十字形和橢圓形,opencv提供getStructuringElement()函數來得到核,其參數以下:字體
kernel=cv2.getStructuringElement(shape,ksize,anchor) shape:核的形狀 cv2.MORPH_RECT: 矩形 cv2.MORPH_CROSS: 十字形(以矩形的錨點爲中心的十字架) cv2.MORPH_ELLIPSE:橢圓(矩形的內切橢圓) ksize: 核的大小,矩形的寬,高格式爲(width,height) anchor: 核的錨點,默認值爲(-1,-1),即核的中心點
opencv提供erode()函數進行腐蝕操做,其對應參數以下:spa
dst=cv2.erode(src,kernel,anchor,iterations,borderType,borderValue): src: 輸入圖像對象矩陣,爲二值化圖像 kernel:進行腐蝕操做的核,能夠經過函數getStructuringElement()得到 anchor:錨點,默認爲(-1,-1) iterations:腐蝕操做的次數,默認爲1 borderType: 邊界種類,有默認值 borderValue:邊界值,有默認值
腐蝕操做的代碼和效果以下:3d
能夠看到二值化圖像中白色的opencv字體面積變小了,就像被腐蝕了。注意這是黑底白字,若是是白底黑字,效果會相反,字體反而會膨脹。code
#coding:utf-8 import cv2 as cv img = cv.imread(r"C:\Users\Administrator\Desktop\logo.png") img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY) ret,img_thr = cv.threshold(img_cvt,200,255,cv.THRESH_BINARY_INV) kernel = cv.getStructuringElement(cv.MORPH_RECT,(3,5)) dst = cv.erode(img_thr,kernel,iterations=1) cv.imshow("img",img) cv.imshow("img_thr",img_thr) cv.imshow("dst",dst) cv.waitKey(0) cv.destroyAllWindows()
2.膨脹對象
膨脹操做和腐蝕操做正好相反,是取核中像素值的最大值代替錨點位置的像素值,這樣會使圖像中較亮的區域增大,較暗的區域減少。若是是一張黑底,白色前景的二值圖,就會使白色的前景物體顏色面積變大,就像膨脹了同樣blog
opencv提供dilate()函數進行膨脹操做,其對應參數以下:圖片
dst = cv2.dilate(src,kernel,anchor,iterations,borderType,borderValue) src: 輸入圖像對象矩陣,爲二值化圖像 kernel:進行腐蝕操做的核,能夠經過函數getStructuringElement()得到 anchor:錨點,默認爲(-1,-1) iterations:腐蝕操做的次數,默認爲1 borderType: 邊界種類 borderValue:邊界值
膨脹操做的代碼和效果以下:
能夠看到二值化圖像中白色的opencv字體面積變大了,就像膨脹了
#coding:utf-8 import cv2 as cv img = cv.imread(r"C:\Users\Administrator\Desktop\logo.png") img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY) ret,img_thr = cv.threshold(img_cvt,200,255,cv.THRESH_BINARY_INV) kernel = cv.getStructuringElement(cv.MORPH_RECT,(3,5)) dst = cv.dilate(img_thr,kernel,iterations=1) cv.imshow("img",img) cv.imshow("img_thr",img_thr) cv.imshow("dst",dst) cv.waitKey(0) cv.destroyAllWindows()
3.開運算,閉運算,頂帽,頂帽
開運算:先進行腐蝕操做,後進行膨脹操做,主要用來去除一些較亮的部分,即先腐蝕掉不要的部分,再進行膨脹。
閉運算:先進行膨脹操做,後進行腐蝕操做,主要用來去除一些較暗的部分。
形態學梯度:膨脹運算結果減去腐蝕運算結果,能夠拿到輪廓信息。
頂帽運算:原圖像減去開運算結果。
底帽運算:原圖像減去閉運算結果。
進行開運算,閉運算,頂帽運算,底帽運算,形態學梯度,opencv提供了一個統一的函數cv2.morphologyEx(),其對應參數以下:
dst = cv2.morphologyEx(src,op,kernel,anchor,iterations,borderType,borderValue) src: 輸入圖像對象矩陣,爲二值化圖像 op: 形態學操做類型 cv2.MORPH_OPEN 開運算 cv2.MORPH_CLOSE 閉運算 cv2.MORPH_GRADIENT 形態梯度 cv2.MORPH_TOPHAT 頂帽運算 cv2.MORPH_BLACKHAT 底帽運算 kernel:進行腐蝕操做的核,能夠經過函數getStructuringElement()得到 anchor:錨點,默認爲(-1,-1) iterations:腐蝕操做的次數,默認爲1 borderType: 邊界種類 borderValue:邊界值
使用代碼和對應效果以下:
#coding:utf-8 import cv2 as cv import matplotlib.pyplot as plt img = cv.imread(r"C:\Users\Administrator\Desktop\logo.png") img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY) ret,img_thr = cv.threshold(img_cvt,200,255,cv.THRESH_BINARY_INV) kernel = cv.getStructuringElement(cv.MORPH_RECT,(3,5)) open = cv.morphologyEx(img_thr,cv.MORPH_OPEN,kernel,iterations=1) close = cv.morphologyEx(img_thr,cv.MORPH_CLOSE,kernel,iterations=1) gradient = cv.morphologyEx(img_thr,cv.MORPH_GRADIENT,kernel,iterations=1) tophat = cv.morphologyEx(img_thr,cv.MORPH_TOPHAT,kernel,iterations=1) blackhat = cv.morphologyEx(img_thr,cv.MORPH_BLACKHAT,kernel,iterations=1) images=[img_thr,open,close,gradient,tophat,blackhat] titles=["img_thr","open","close","gradient","tophat","blackhat"] for i in range(6): plt.subplot(2,3,i+1),plt.imshow(images[i],"gray") plt.title(titles[i]) plt.xticks([]), plt.yticks([]) plt.show()
4.應用實例
有以下一張中文圖片,當咱們進行字符切割時,常須要知道其中的漢字是否帶下劃線,方便進行後續處理。
咱們首先想到的多是使用霍夫直線檢測算法,可是直接檢測時,會有不少干擾。咱們能夠經過採用一個橫向的矩陣核,來腐蝕字體,使圖片中只剩下下劃線,而後再進行霍夫直線檢測,這樣干擾小,準確度會高不少。具體實現代碼和效果以下:
#coding:utf-8 import cv2 as cv img = cv.imread(r"C:\Users\Administrator\Desktop\chinese.png") img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY) ret,img_thr = cv.threshold(img_cvt,100,255,cv.THRESH_BINARY) kernel = cv.getStructuringElement(cv.MORPH_RECT,(30,1)) #因爲是1*30的矩陣,字體會被橫向空隙的白色腐蝕掉,而下劃線橫向都是黑色,不會腐蝕 dst = cv.dilate(img_thr,kernel,iterations=1) #因爲是白底黑字,全部進行膨脹操做來去除黑色字體 cv.imshow("img_thr",img_thr) cv.imshow("dst",dst) cv.waitKey(0) cv.destroyAllWindows()