(四)OpenCV-Python学习—形态学处理

  经过阈值化分割能够获得二值图,但每每会出现图像中物体形态不完整,变的残缺,能够经过形态学处理,使其变得丰满,或者去除掉多余的像素。经常使用的形态学处理算法包括:腐蚀,膨胀,开运算,闭运算,形态学梯度,顶帽运算和底帽运算。算法

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

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