原理
形态变换是根据图片的形状进行的简单运算。一般被用在二值图像上。它需要两个输入,一个是我们的原始图片,另一个是被叫做结构元素或者是核,用来决定运算的类型。两个基本的形态运算是腐蚀和Dilation.其他的变形如开,合,梯度等也会有。我们来看看他们在下面这张图上的表现。
![](https://img.haomeiwen.com/i1784254/1e9b30000e6146e6.png)
1. 腐蚀
腐蚀的基本理念就和土壤腐蚀一样,它会腐蚀掉前景的边缘(所以前景应该用白色)。核腐蚀掉图片。原始图片里的一个像素(1或者0)只有在核下的所有像素都是1的时候才被认为是1.否则它就被腐蚀掉了(变成0)
根据核的大小来决定在边界附近的多少像素会被丢弃掉,所以前景物体的厚度或大小会缩小,或者说白色区域会减小。这个在移除小的白色噪点时很有用。
在下面的例子里,我用给一个5x5的核,来看看如何工作的:
import cv2
import numpy as np
img = cv2.imread('j.png',0)
kernel = np.ones((5,5), np.uint8)
erosion = cv2.erode(img,kernel,iterations=1)
结果:
![](https://img.haomeiwen.com/i1784254/558fc0e7125eca31.png)
2.膨胀
这个就是腐蚀的反义词,在核下只要有至少一个像素是1,像素的值就是1.所以它会增加图片上白色区域的范围或者前景物体的大小。一般来说,在去噪过程中,腐蚀后会再膨胀。因为腐蚀去掉了白噪点,但是它也缩小了我们的对象,所以我们再膨胀它,由于噪点已经没了,它不会回来,我们的物体区域会增加。在把分隔对象连起来也很有用。
dilation = cv2.dilate(img,kernel,iterations=1)
![](https://img.haomeiwen.com/i1784254/2c3bcdf8de74f148.png)
3. 开
开就是腐蚀之后再膨胀的另一个名字。我们使用函数cv2.morphologyEx()
opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)
结果:
![](https://img.haomeiwen.com/i1784254/75d45bd481d28068.png)
4.闭
闭是开的反义词,膨胀之后再腐蚀,在用来关闭前景对象里的小洞或小黑点很有用。
closing = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
![](https://img.haomeiwen.com/i1784254/63124b82362e2e82.png)
5.形态梯度
这个和腐蚀以及膨胀不同,结果看上去像是物体的轮廓。
gradient = cv2.morphologyEx(img,cv2.MORPH_GRADIENT,kernel)
结果:
![](https://img.haomeiwen.com/i1784254/fb02be58fd7dc009.png)
6.顶帽
这个是输入图片和图片的开运算结果的差别,下面是9x9的核的
tophat=cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel)
结果:
![](https://img.haomeiwen.com/i1784254/fe69f4c2c9695feb.png)
7.黑帽
这是输入图片的闭的结果和输入图片的差别。
blackhat=cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)
结果:
![](https://img.haomeiwen.com/i1784254/e5d3a41a5cd65529.png)
结构元素
我们通过Numpy人工创建了结构元素。是个矩形,但是有些情况下,你可能会需要椭圆/圆型的核。为了这个目的,OpenCV有一个函数cv2.getStructuringElement()。你把形状和核的大小作为参数传给它,你就可以得到想要的核。
# Rectangular Kernel
>>>cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
array([[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1]],dtype=uint8)
# Elliptical Kernel
>>>cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
array([[0,0,1,0,0],
[1,1,1,1,1],
[1,1,1,1,1],
[1,1,1,1,1],
[0,0,1,0,0]],dtype=uint8)
# Cross-shaped Kernel
>>>cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
array([[0,0,1,0,0],
[0,0,1,0,0],
[1,1,1,1,1],
[0,0,1,0,0],
[0,0,1,0,0]],dtype=uint8)
网友评论