OpenCV(5):图像腐蚀与膨胀,卷积的概念

 图像腐蚀:

图像腐蚀的作用就是去掉毛刺,一般用于二值图像。

假设我们现在有一张二值图像:

我们现在对上图进行腐蚀操作,去除文字周围的毛边。 

在OpenCV中用于图像腐蚀的方法是cv2.erode(输入图像,卷积核,迭代次数)

import cv2
import numpy as np

#读取图像
img = cv2.imread('Hello.png')

#写一个展示图像的方法
def cv_show(title,img):
    cv2.imshow(title,img)
    cv2.waitKey(0) 
    cv2.destroyAllWindows()
    return

# cv_show('img',img)

kernel = np.ones((3,3),dtype = np.uint8)#定义卷积核
erode = cv2.erode(img,kernel,iterations = 2)#调用腐蚀方法,迭代两次

cv_show('erode',erode)#展示腐蚀后的图像

 返回结果是:

 图像腐蚀的原理是在图形矩阵中,用卷积核(和前一张说的滤波核是一个东西)去逐像元判定。

假设卷积核是一个3*3的矩阵,如果一个像元邻近卷积核中所有的像素都是白色或者都是黑色,那么这个点就没事,如果一个点邻近3*3个像素中既有白色又有黑色,那么这个点就会被腐蚀掉。

这种方法所造成的结果就是对于二值图像(图像矩阵中只有两种值的图像),它的边界就会被腐蚀,因为只有边界的像素邻域中财包含了两种值。iteration参数代表迭代次数,迭代一次就会腐蚀一次图像边界。而卷积核的大小也会影响腐蚀,卷积核越大,迭代一次腐蚀的边界越深。

详见下图:

 图像膨胀

和图像腐蚀相反,图像的膨胀是用于放大二值图的特征。
opencv中的cv2.dilate()方法用于图像的膨胀。参数和腐蚀一致,依次为输入图像,卷积核,迭代次数
图像的膨胀本质上执行的操作和侵蚀有点类似。侵蚀是对图像的边界赋予黑色,而放大是赋予白色。

import cv2
import numpy as np

#读取图像
img = cv2.imread('Hello.png')

#展示图像的方法
def cv_show(title,img):
    cv2.imshow(title,img)
    cv2.waitKey(0) 
    cv2.destroyAllWindows()
    return

#定义卷积核
kernel = np.ones((3,3),dtype = np.uint8)
#图像膨胀
dilate = cv2.dilate(img, kernel, iterations = 2)
cv_show('dilate',dilate)

返回结果:

 可以发现图像的边缘扩大了,也可以说图像的特征放大了。

图像膨胀的原理和图像腐蚀几乎一致,只不过最后赋值不同,腐蚀赋予黑色,膨胀赋予白色,当然不一定是黑色和白色,还得看你的二值图具体是哪两个值,我这是0和255,对应就是黑白。

图像卷积:

那么通过前一张的滤波学习和本章的开闭运算的学习,想必大家也应该有些了解什么是卷积了。

通过下图帮助理解。图像的本质就是矩阵,有一维矩阵(灰度图),有三维矩阵(RGB图像,全色图像),有多光谱图像(很多维)。卷积就是对图像矩阵本身经过卷积核运算,计算出一个新的矩阵。卷积核就是下图红色的框。在红框内的元素通过一系列计算(不同算法计算方式不同),会得出一个新的值,那么按照步长为一依次计算可以得出一个新的矩阵,这个矩阵就是你需要的新的图像。

开运算:

图像的腐蚀除了去除毛刺之外,本身也会消除一些原有图像的特征,就是你需要图像的边缘也被侵蚀了。看下图是侵蚀前后的对比,可以发现虽然去除了毛边,但是‘Hello World’本身也变细了。

解决这个问题的方法是:先将图像腐蚀,去除毛边,然后用图像膨胀,将图像本被侵蚀的特征放大。

上代码:

import cv2
import numpy as np

img = cv2.imread('Hello.png')
#显示图图像的方法
def cv_show(title,img):
    cv2.imshow(title,img)
    cv2.waitKey(0) 
    cv2.destroyAllWindows()
    return
#开运算:先侵蚀再膨胀
def clean(img):
    kernel = np.ones((3,3),dtype = np.uint8)
    erode = cv2.erode(img,kernel,iterations = 2 )#图像腐蚀
    dilate = cv2.dilate(erode, kernel, iterations = 2)#图像膨胀
    return dilate

#调用开运算
dilate = clean(img)

#展示图片
cv_show('dilate',dilate)

返回:

 对比之前图像腐蚀的操作,可以发现被腐蚀的图像边缘都已经恢复了,而被消除的毛刺并没有回来。

那么本身OpenCV中已经封装好了相关的代码,不需要我们再自己定义开运算方法。

OpenCV中的方法是cv2.morphologyEx(src, op, kernel), src传入图像,op指图形运算方式,kernel卷积核。

其中最重要的就是op参数,op =  cv2.MORPH_OPEN就表示进行开运算。

import cv2
import numpy as np

def cv_show(title,img):
    cv2.imshow(title,img)
    cv2.waitKey(0) 
    cv2.destroyAllWindows()
    return

img = cv2.imread('Hello.png')
kernel = np.ones((5,5),dtype = np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN,kernel)#开运算

cv_show('open',opening)

闭运算

闭运算和开运算的原理相反,先膨胀,再腐蚀。

闭运算主要是针对图像中的小洞洞。开运算去除了毛刺,但是对于图像的洞洞无法解决。因为洞洞先缩小在放大没用,只有先放大,把洞洞堵上,再缩小,恢复原样才行。

就比如下图。如果先腐蚀,再膨胀,只会把洞洞(图像中黑色的点)先放大后缩小,但是如果先膨胀,消除洞洞,在腐蚀,将图像膨胀过后的边缘腐蚀掉,就可以去除洞洞,这就是闭运算。

 闭运算同样是用cv2.morphologyEx(src, op, kernel)方法,区别是此时op=cv2.MORPH_CLOSE

上代码:

import cv2
import numpy as np

def cv_show(title,img):
    cv2.imshow(title,img)
    cv2.waitKey(0) 
    cv2.destroyAllWindows()
    return

img = cv2.imread('dongdong.png')
kernel = np.ones((5,5),dtype = np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_CLOSE,kernel)#闭运算

cv_show('open',opening)

返回

 可以看出洞洞被消除了,本身椭圆形的大小也没有变化

猜你喜欢

转载自blog.csdn.net/m0_50317149/article/details/129768790