Opencv3基础操作3——图像形态学处理

形态学腐蚀操作

腐蚀操作通常处理只有二值的图像(比如黑白),这里的例子就是一个值为255(白色),一个是1(黑色)。
先导入必要的库:

import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB

导入图像:

img = cv2.imread('dige.png')

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

来看一下事例图:
在这里插入图片描述
可以看到,这两个字有很多“毛刺”,如何去掉呢,就是用腐蚀操作(腐蚀操作可以理解为减肥)。下面我们看看腐蚀操作的代码和执行腐蚀操作后图像的样子。

kernel = np.ones((3,3),np.uint8) 
erosion = cv2.erode(img,kernel,iterations = 1)#第一个参数是导入的图片,第二个参数是filter过滤器,第三个参数是迭代次数,即执行几次腐蚀操作

cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:
在这里插入图片描述
可以发现毛刺被去掉了,并且字的笔画变细了。下面我们解释一下原理。
我们先倒入一张圆:

pie = cv2.imread('pie.png')

cv2.imshow('pie', pie)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:
在这里插入图片描述
腐蚀原理是这样的,我们先选择一个filter,这里我们选择全为1(其实这个过滤器的值并不需要特别考虑,暂时认为是1即可)的33矩阵,然后当我们检测到边缘点的时候,比如下图中的蓝色点,在这个33的过滤器中,含有黑色区域,那么这个点就会被腐蚀掉,变成黑色。
在这里插入图片描述
当如果这几个小方格都是白色,则这个点就不会变,比如下面的绿色点。
在这里插入图片描述
然后腐完就可以得到下面这张图(红色区域代表被腐蚀了的面积):
在这里插入图片描述
我们引入代码,看看多迭代几次的效果:

kernel = np.ones((30,30),np.uint8) 
erosion_1 = cv2.erode(pie,kernel,iterations = 1)
erosion_2 = cv2.erode(pie,kernel,iterations = 2)
erosion_3 = cv2.erode(pie,kernel,iterations = 3)
res = np.hstack((erosion_1,erosion_2,erosion_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:
在这里插入图片描述
随着迭代的增加,可见白色区域越来越小。
腐蚀程度还跟过滤器的大小有关,如果过滤器越大,那么腐蚀的可能性就越大,过滤器越小,腐蚀的可能性就越小,对照腐蚀原理,读者应该可以快速想出原因。

形态学膨胀操作

膨胀操作就相当于腐蚀操作的逆操作(增肥)。
导入图像:

img = cv2.imread('dige.png')

cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

此图像还是上面拿着图:
在这里插入图片描述
我们先做腐蚀操作,去掉“毛边”:

kernel = np.ones((3,3),np.uint8) 
dige_erosion = cv2.erode(img,kernel,iterations = 1)

cv2.imshow('erosion', erosion)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
就像前面所说的,腐蚀操作不仅去掉了“毛刺”,还使笔画变细了,我们可以使用膨胀操作,把它变回来:

kernel = np.ones((3,3),np.uint8) 
dige_dilate = cv2.dilate(dige_erosion,kernel,iterations = 1)

cv2.imshow('dilate', dige_dilate)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:
在这里插入图片描述
他的膨胀原理也是一样,比如这个黄色的点,当这些小格子中有白色的点,那么我就变成白色。
在这里插入图片描述
我们看一下多迭代几次的效果:

pie = cv2.imread('pie.png')

kernel = np.ones((30,30),np.uint8) 
dilate_1 = cv2.dilate(pie,kernel,iterations = 1)
dilate_2 = cv2.dilate(pie,kernel,iterations = 2)
dilate_3 = cv2.dilate(pie,kernel,iterations = 3)
res = np.hstack((dilate_1,dilate_2,dilate_3))
cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:
在这里插入图片描述

开运算

开运算相当于把腐蚀和膨胀联系在一起,先腐蚀,再膨胀。

# 开:先腐蚀,再膨胀
img = cv2.imread('dige.png')

kernel = np.ones((5,5),np.uint8) 
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)#cv2.MORPH_OPEN为开运算

cv2.imshow('opening', opening)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:
在这里插入图片描述

闭运算

闭运算为开操作的逆运算,先膨胀,再腐蚀。

# 闭:先膨胀,再腐蚀
img = cv2.imread('dige.png')

kernel = np.ones((5,5),np.uint8) 
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)

cv2.imshow('closing', closing)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:
在这里插入图片描述
闭运算操作不会把“毛刺”去掉。

梯度运算

梯度运算就是膨胀-腐蚀得到的边界面积信息,我们直接来看例子。
先对图像进行膨胀和腐蚀操作:

# 梯度=膨胀-腐蚀
pie = cv2.imread('pie.png')
kernel = np.ones((7,7),np.uint8) 
dilate = cv2.dilate(pie,kernel,iterations = 5)
erosion = cv2.erode(pie,kernel,iterations = 5)

res = np.hstack((dilate,erosion))

cv2.imshow('res', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:
在这里插入图片描述
然后进行梯度操作:

gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)
#cv2.MORPH_GRADIENT为梯度运算
cv2.imshow('gradient', gradient)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:
在这里插入图片描述

礼帽

礼帽 = 原始输入-开运算结果。
按照上面的例子,开运算后不带“毛刺”了,礼帽运算后,就只剩下“毛刺”了。

#礼帽
img = cv2.imread('dige.png')
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)#cv2.MORPH_TOPHAT礼帽
cv2.imshow('tophat', tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:

在这里插入图片描述

黑帽

黑帽 = 闭运算-原始输入。
按上面的例子,闭运算后边界可能比原图膨胀一点点,那么减去原始图像,可能就只剩下一点点边界。

#黑帽
img = cv2.imread('dige.png')
blackhat  = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, kernel)#cv2.MORPH_BLACKHAT黑帽
cv2.imshow('blackhat ', blackhat )
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果:
在这里插入图片描述

原创文章 3 获赞 2 访问量 332

猜你喜欢

转载自blog.csdn.net/Hai__hello/article/details/105522212
今日推荐