图像腐蚀:
图像腐蚀的作用就是去掉毛刺,一般用于二值图像。
假设我们现在有一张二值图像:
我们现在对上图进行腐蚀操作,去除文字周围的毛边。
在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)
返回
可以看出洞洞被消除了,本身椭圆形的大小也没有变化