基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)

腐蚀与膨胀

图像的腐蚀与膨胀互为逆向操作,通常用于处理二值图像(黑白图,以黑色为底面背景),因此需要先进行二值化处理,腐蚀和膨胀通俗的理解就是,在指定大小的卷积核内,如果该卷积核内全为黑色或全为白色,则该卷积核内像素值不变,但若是既有黑色又有白色,即在图像边缘处,那么膨胀操作则会将该卷积核内所有白色像素点都赋值变为黑色,以此将图像向内腐蚀掉一圈,而膨胀操作则相反,会将卷积核内的黑色像素点赋值成2白色,以此让图像膨胀一圈。

膨胀与腐蚀的函数介绍

kernel = np.ones((3,3),uint8):定义要处理的卷积核大小和卷积核的类型。

erosion = cv2.erode(img_test3,kernel,iterations = 1):对图像进行膨胀操作,img_test是要进行处理的图像,kernel是通过上一个函数定义好的卷积核,而iterations则是腐蚀操作的循环次数(可以将卷积核设置为(1,1),然后不断调整循环次数来实现精细化的腐蚀,以达到更好的腐蚀效果)。

dilate_1 = cv2.dilate(img_test,kernel,iterations = 1):对图像进行膨胀操作,这里的参数跟上面的参数作用一样,只是改了函数名而已。(同样可以将卷积核设置为(1,1),不断改变循环次数,以达到更好的膨胀效果)。

应用:腐蚀操作一般用于消去图像中不需要的粘连部分,而膨胀操作则用于填充图像内的空白部分,同时也可以恢复图像由于进行腐蚀操作后缩小的面积,在下面的代码实例中会有体现。

代码实例

import cv2#导入包
import numpy as np
import matplotlib.pyplot as plt
img_test3 = cv2.imread("test3.png")#读入图像
cv2.imshow("test3",img_test3)#展示图片
cv2.waitKey(0)
cv2.destroyAllWindows()#关闭窗口
kernel = np.ones((3,3),np.uint8)#设定处理的内核
erosion = cv2.erode(img_test3,kernel,iterations = 1)#腐蚀操作
cv2.imshow("erosion",erosion)#展示图片
cv2.waitKey(0)
cv2.destroyAllWindows()#关闭窗口
pie = cv2.imread("pie.png")
cv2.imshow("pie",pie)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((30,30),np.uint8)#设定要处理的内核大小
erosion_1 = cv2.erode(pie,kernel,iterations = 1)#循环腐蚀1次
erosion_2 = cv2.erode(pie,kernel,iterations = 2)#循环腐蚀2次
erosion_3 = cv2.erode(pie,kernel,iterations = 3)#循环腐蚀3次
All = np.hstack((erosion_1,erosion_2,erosion_3))#拼接图像
cv2.imshow("All",All)
cv2.waitKey(0)
cv2.destroyAllWindows()
img_test3 = cv2.imread("test3.png")
cv2.imshow("test3",img_test3)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((3,3),np.uint8)#设定要处理的内核大小
erosion_test3 = cv2.erode(img_test3,kernel,iterations = 1)#腐蚀图像
cv2.imshow("erosion_test3",erosion_test3)#展示腐蚀后的图像
cv2.waitKey(0)
cv2.destroyAllWindows()#关闭窗口
dilate_test3 = cv2.dilate(erosion_test3,kernel,iterations = 1)#对腐蚀过的图像进行膨胀处理
cv2.imshow("dilate",dilate_test3)#展示膨胀后的图像
cv2.waitKey(0)
cv2.destroyAllWindows()#关闭窗口
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)#循环膨胀三次后的图像
All = np.hstack((dilate_1,dilate_2,dilate_3))#拼接以上三幅图像
cv2.imshow("All",All)#展示图片
cv2.waitKey(0)
cv2.destroyAllWindows()#关闭窗口

运行结果

这是原图,可以看到上面有一些多出来的粘连部分

基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)_第1张图片

进行腐蚀操作后的图像,可以看到,我们用腐蚀操作成功去除了边缘的粘连部分,但同时字体笔画也由于受到了腐蚀而变细了

基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)_第2张图片

对上图进行膨胀操作,可以看到,我们恢复了被腐蚀前笔画的粗细,同时也去除掉了原图的粘连部分,这种操作称为开运算,能够在尽量不改变原图的情况下去除图像的粘连。(在下面会有详细的介绍)

基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)_第3张图片

 以下是循环腐蚀1~3次之后的图像对比

基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)_第4张图片

 以下是循环膨胀1~3次之后的图像对比

基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)_第5张图片

 通过上面两幅图可以看出,不管是腐蚀还是膨胀,都不是等比例的进行,它们最终都会趋近于矩形(因为卷积核就是矩形的),并且进行腐蚀再膨胀后的图像跟原图是存在细微差别的,比如中间的部分空洞可能已经消失了等等。

开运算和闭运算 

所谓开运算在上面的代码其实已经使用过了,只是opencv本身便带有可以进行腐蚀后再膨胀的函数,不需要我们自己写那么多代码。开运算在原图的基础上就是用于消除图像的一些粘连部分的一种方式。

而闭运算则相反,是先进行膨胀,再进行腐蚀的一种操作。它主要用于填充图像中的空洞部分,在opencv中同样有一个专门的函数进行闭运算。

函数介绍

opening = cv2.morphologyEx(img_test3,cv2.MORPH_OPEN,kernel):开运算,img_test3是要进行处理的图片,cv2.MORPH_OPEN表示要进行的是开运算(先腐蚀后膨胀),kernel则跟上面的函数一样,是定义好的卷积核。

 closing = cv2.morphologyEx(img_test3,cv2.MORPH_CLOSE,kernel):闭运算,这里的函数参数跟上一个函数作用一样,cv2.MORPH_OPEN表示要进行的是闭运算(先膨胀后腐蚀)。

代码实例

import cv2
import numpy as np
import matplotlib.pyplot as plt
img_test3 = cv2.imread("test3.png")#读入图像
cv2.imshow("test3",img_test3)#展示图片
cv2.waitKey(0)
cv2.destroyAllWindows()#关闭窗口
kernel = np.ones((3,3),np.uint8)#设定要处理的内核大小
opening = cv2.morphologyEx(img_test3,cv2.MORPH_OPEN,kernel)#开运算,先腐蚀后膨胀,能够去除图像中粘连的部分
cv2.imshow("open",opening)
cv2.waitKey(0)
cv2.destroyAllWindows()
kernel = np.ones((3,3),np.uint8)#设定要处理的卷积核大小
closing = cv2.morphologyEx(img_test3,cv2.MORPH_CLOSE,kernel)#闭运算,先膨胀后腐蚀,能够填补图像中间的空隙
cv2.imshow("close",closing)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果

开运算

基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)_第6张图片

闭运算:效果不明显,但是如果该图像中间有空洞存在,那么我们可以明显的看到空洞被填

上了。

 基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)_第7张图片

 梯度运算

原理:将图像分别进行膨胀和腐蚀,然后两者相减,则可以得到该图像的轮廓,而opencv中同样提供了进行梯度运算的函数。

函数介绍

gradient = cv2.morphologyEx(pie,cv2.MORPH_GRADIENT,kernel):这里的pie是将要进行处理的二值图像,cv2.MORPH_GRADIENT表示进行梯度运算,kernel则是定义好的卷积核。

代码示例

import cv2
import numpy as np
import matplotlib.pyplot as plt
pie = cv2.imread("pie.png")
cv2.imshow("pie",pie)#展示原图
cv2.waitKey(0)
cv2.destroyAllWindows()#关闭窗口
#梯度运算,通过膨胀减去腐蚀得到轮廓
kernel = np.ones((3,3),np.uint8)#设定卷积核大小
gradient = cv2.morphologyEx(pie,cv2.MORPH_GRADIENT,kernel)#梯度运算
cv2.imshow("gradient",gradient)#展示处理后的图像
cv2.waitKey(0)
cv2.destroyAllWindows()#关闭窗口

运行结果

原图

基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)_第8张图片

处理后得到的图像轮廓

基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)_第9张图片

 礼帽与黑帽

礼帽:将图像先进行开运算,再以原始图像减去开运算的结果,我们就可以得到图像被腐蚀掉的粘连部分,或者说原图中灰度较亮的区域,所以也称白顶帽变换。

黑帽:将图像先进行闭运算,再将闭运算的结果减去原始图像,作用我们就可以得到原图像中被填充的空洞部分,也就是图像中件较暗的空洞区域,所以又称黑底帽变换。

函数介绍

tophat = cv2.morphologyEx(img_test3,cv2.MORPH_TOPHAT,kernel):礼帽运算,cv2.MORPH_TOPHAT表示进行的是礼帽运算,即原图像-开运算。

blackhat = cv2.morphologyEx(img_test3,cv2.MORPH_BLACKHAT,kernel):黑帽运算,cv2.MORPH_BLACKHAT表示进行的是黑帽运算,即闭运算-原图像。

代码示例

import cv2
import numpy as np
import matplotlib.pyplot as plt
img_test3 = cv2.imread("test3.png")#读入图像
cv2.imshow("test3",img_test3)#展示图片
cv2.waitKey(0)
cv2.destroyAllWindows()#关闭窗口
#礼帽,原始图像-开运算,得到的就是被腐蚀掉的粘连部分
kernel = np.ones((3,3),np.uint8)#设定卷积核大小
tophat = cv2.morphologyEx(img_test3,cv2.MORPH_TOPHAT,kernel)#礼帽运算
cv2.imshow("tophat",tophat)
cv2.waitKey(0)
cv2.destroyAllWindows()
#黑帽运算,闭运算-原始图像,得到的是膨胀之前原始图像中比较暗的部分,即中间的空洞
kernel = np.ones((7,7),np.uint8)#设定卷积核大小
blackhat = cv2.morphologyEx(img_test3,cv2.MORPH_BLACKHAT,kernel)#黑帽运算
cv2.imshow("blackhat",blackhat)
cv2.waitKey(0)
cv2.destroyAllWindows()

运行结果

原图

基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)_第10张图片

礼帽,可以看到图像粘连部分被剔除出来了

基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)_第11张图片

黑帽,我们得到了迪哥中间微小的空洞部分

基于python的opencv图像形态学处理(图像腐蚀与膨胀操作以及礼帽与黑帽)_第12张图片

你可能感兴趣的:(笔记,opencv,python,计算机视觉,numpy)