(四)OpenCV-Python學習—形態學處理


  通過閾值化分割可以得到二值圖,但往往會出現圖像中物體形態不完整,變的殘缺,可以通過形態學處理,使其變得豐滿,或者去除掉多余的像素。常用的形態學處理算法包括:腐蝕,膨脹,開運算,閉運算,形態學梯度,頂帽運算和底帽運算。

1. 腐蝕

   腐蝕操作類似於中值平滑,也有一個核,但不進行卷積運算,而是取核中像素值的最小值代替錨點位置的像素值,這樣就會使圖像中較暗的區域面積增大,較亮的的區域面積減小。如果是一張黑底,白色前景的二值圖,就會使白色的前景物體顏色變小,就像被腐蝕了一樣。

   進行腐蝕操作的核,不僅可以是矩形,還可以是十字形和橢圓形,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()函數進行腐蝕操作,其對應參數如下:

dst=cv2.erode(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.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()
cv2.erode()

2.膨脹

  膨脹操作和腐蝕操作正好相反,是取核中像素值的最大值代替錨點位置的像素值,這樣會使圖像中較亮的區域增大,較暗的區域減小。如果是一張黑底,白色前景的二值圖,就會使白色的前景物體顏色面積變大,就像膨脹了一樣

    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()
cv2.dilate()

 

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()
cv2.morphologyEx()

 

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()

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM