OpenCV-Python 形态学处理

 

 

通过阈值化分割可以得到二值图像,但往往会出现图像中物体形态不完整,残缺,可以通过形态学(morphology)处理,使其变得丰满,或者去除掉多余的像素。常用的形态学处理算法包括:腐蚀(erode)膨胀(dilate)开运算(Open)闭运算(Close)形态学梯度顶帽运算(tophat)底帽运算(blackhat)

 

1. 腐蚀

腐蚀操作类似于中值平滑,也有一个核,但不进行卷积运算,而是取核中像素值的最小值代替锚点位置的像素值,这样就会使图像中较按的区域面积增大,较量的区域面积减小。如果是一张黑底,白色前景的二值图,就会使白色的前景物体颜色变小,就像被腐蚀了一样。

锚点即卷积核平移过程中原始图片正在计算的点。

进行腐蚀操作的核,不仅可以是矩形,还可以是十字形和椭圆形,opencv提供getStructuringElement()函数来获得核,其参数如下:

1 kernel=cv2.getStructuringElement(shape,ksize,anchor)
2         shape:核的形状
3                 cv2.MORPH_RECT: 矩形
4                 cv2.MORPH_CROSS: 十字形(以矩形的锚点为中心的十字架)
5                 cv2.MORPH_ELLIPSE:椭圆(矩形的内切椭圆)
6                 
7         ksize: 核的大小,矩形的宽,高格式为(width,height)
8         anchor: 核的锚点,默认值为(-1,-1),即核的中心点

opencv提供erode()函数进行腐蚀操作,其对应参数如下:

1 dst=cv2.erode(src,kernel,anchor,iterations,borderType,borderValue):
2         src: 输入图像对象矩阵,为二值化图像
3         kernel:进行腐蚀操作的核,可以通过函数getStructuringElement()获得
4         anchor:锚点,默认为(-1,-1)
5         iterations:腐蚀操作的次数,默认为1
6         borderType: 边界种类,有默认值
7         borderValue:边界值,有默认值

腐蚀操作的代码和效果如下:

   可以看到二值化图像中白色的opencv字体面积变小了,就像被腐蚀了。注意这是黑底白字,如果是白底黑字,效果会相反,字体反而会膨胀。

 1 #coding:utf-8
 2 
 3 
 4 import cv2 as cv
 5 
 6 img = cv.imread(r"logo.png")
 7 img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
 8 ret,img_thr = cv.threshold(img_cvt,200,255,cv.THRESH_BINARY_INV)
 9 kernel = cv.getStructuringElement(cv.MORPH_RECT,(3,5))
10 dst = cv.erode(img_thr,kernel,iterations=1)
11 
12 cv.imshow("img",img)
13 cv.imshow("img_thr",img_thr)
14 cv.imshow("dst",dst)
15 cv.waitKey(0)
16 cv.destroyAllWindows()
17 
18 cv2.erode()

 

 

2. 膨胀

膨胀操作刚好跟腐蚀操作相反,也是有一个核,取核中像素值最大的点代替锚点位置的像素值,这样会使图像中较亮的区域增大,较暗的区域减小。如果是一张黑底,白色前景的二值图像,就会是白色的前景物体颜色面积变大,就像膨胀了一样。

opencv提供dilate()函数进行膨胀操作,其对应参数如下:

1 dst = cv2.dilate(src,kernel,anchor,iterations,borderType,borderValue)
2         src: 输入图像对象矩阵,为二值化图像
3         kernel:进行腐蚀操作的核,可以通过函数getStructuringElement()获得
4         anchor:锚点,默认为(-1,-1)
5         iterations:腐蚀操作的次数,默认为1
6         borderType: 边界种类
7         borderValue:边界值

膨胀操作的代码和效果如下:

    可以看到二值化图像中白色的opencv字体面积变大了,就像膨胀了

 1 #coding:utf-8
 2 
 3 
 4 import cv2 as cv
 5 
 6 
 7 img = cv.imread(r"C:\Users\Administrator\Desktop\logo.png")
 8 img_cvt = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
 9 ret,img_thr = cv.threshold(img_cvt,200,255,cv.THRESH_BINARY_INV)
10 kernel = cv.getStructuringElement(cv.MORPH_RECT,(3,5))
11 dst = cv.dilate(img_thr,kernel,iterations=1)
12 
13 cv.imshow("img",img)
14 cv.imshow("img_thr",img_thr)
15 cv.imshow("dst",dst)
16 cv.waitKey(0)
17 cv.destroyAllWindows()
18 
19 cv2.dilate()

 

 3. 开运算、闭运算、顶帽、底帽

开运算(OPEN): 先进行腐蚀操作,后进行膨胀操作。主要是用来去除一些较亮的部分,即先腐蚀掉不要的部分,再进行膨胀。

闭运算(CLOSE): 先进行膨胀操作,后进行腐蚀操作。主要是用来去除掉一些较暗的部分

形态学梯度(GRADIENT): 膨胀运算结果减去腐蚀运算结果,可以拿到轮廓信息

顶帽运算(TOPHAT):原图像减去开运算结果, 可以得到噪声

黑帽运算(BLACKHAT):闭运算结果减去原图像(注意顺序别搞反了),可以得到原始图中的小黑点

进行开运算,闭运算,顶帽运算,底帽运算,形态学梯度,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()

 

posted @ 2022-05-19 10:12  IllidanStormrage  阅读(427)  评论(0编辑  收藏  举报