目标
在这一章当中
- 我们将学习不同的形态操作,如腐蚀,膨胀,开运算,闭运算等。
- 我们将看到不同的功能,如:,,等
理论
形态学变换是基于图像形状所进行一些简单操作。它通常是在二值化图像上进行处理。它需要两个输入,一个是我们的原始图像,另一个是决定操作性质的结构元素或内核。两个基本的形态学算子是腐蚀和膨胀。然后它的变体构成了开运算,闭运算,梯度等。我们会以下图为例进行逐一的介绍。
1.侵蚀
腐蚀的基本思想就像土壤腐蚀一样,它腐蚀了前景物体的边界(前景一般为白色)。那么它是怎么做到的呢?内核在图像中滑动(如2D卷积)。如果与卷积所对应的原图像的所有像素值都是1,那么中心元素就保持着原来的像素值,否则就变为零。
那么这会产生什么影响呢。根据卷积核的大小,靠近前景附近的所有像素都将被丢弃。因此,前景物体的厚度或大小会减小,或者图像中的白色区域会减少。这对于消除小的白噪声是有用的(正如我们在彩色空间章节看到的那样),同时也可以用来分离两个连接的物体等等。
在这里,作为一个例子,我将使用一个5x5的内核。让我们看看它是如何工作的:
程序:
import cv2 as cvimport numpy as np
img = cv.imread('j.png',0)
kernel = np.ones((5,5),np.uint8)
erosion = cv.erode(img,kernel,iterations = 1)
#image,kernel,number of times erosion is applied.
cv.imshow('src',erosion)
cv.waitKey(0)
结果:
2.膨胀
这与腐蚀正好相反。这里,如果与内核相对应的图像至少一个像素是'1',那么中心元素的像素值就是'1'。所以它增加了图像中的白色区域或增加了前景物体的大小。通常情况下,在噪音消除的情况下,腐蚀会伴随着扩张。因为腐蚀会消除白色噪音,但它也会缩小我们的目标。所以我们膨胀它。由于噪音消失了,他们不会回来,但我们的物体面积增加了。它在连接对象的分开部分时也很有用。
程序:
import cv2 as cv
import numpy as np
img = cv.imread('j.png',0)
kernel = np.ones((5,5),np.uint8)
dilation = cv.dilate(img,kernel,iterations = 1)
#image,kernel,number of times erosion is applied.
cv.imshow('src',dilation)
cv.waitKey(0)
结果:
3.开运算
开运算是先进行腐蚀,然后在进行膨胀。正如我们上面所解释的那样,它在消除噪音方面很有用这里我们使用函数
程序:
import cv2 as cv
import numpy as np
img = cv.imread('opening.png',0)
kernel = np.ones((5,5),np.uint8)
opening = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)
#image,kernel,number of times erosion is applied.
cv.imshow('src',img)
cv.imshow('fin',opening)
cv.waitKey(0)
结果:
4.闭运算
与开运算相反,闭运算是先进行膨胀,然后再进行腐蚀。这对于消除前景物体内的小孔或物体上的小黑点很有用。
程序:
import cv2 as cv
import numpy as np
img = cv.imread('closing.png',0)
kernel = np.ones((5,5),np.uint8)
closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)
#image,kernel,number of times erosion is applied.
cv.imshow('src',img)
cv.imshow('fin',closing)
cv.waitKey(0)
结果:
5.形态梯度
就是图像膨胀和腐蚀的查。结果将看起来像前景对象的轮廓。
程序:
import cv2 as cv
import numpy as np
img = cv.imread('j.png',0)
kernel = np.ones((5,5),np.uint8)
gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)
#image,kernel,number of times erosion is applied.
cv.imshow('src',img)
cv.imshow('fin',gradient)
cv.waitKey(0)
结果:
6.高顶
这是输入图像和图像经开运算后的查。下面的例子是为9x9内核完成的。
程序:
import cv2 as cv
import numpy as np
img = cv.imread('j.png',0)
kernel = np.ones((9,9),np.uint8)
opening = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)
tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)
#image,kernel,number of times erosion is applied.
cv.imshow('src',img)
cv.imshow('open',opening)
cv.imshow('fin',tophat)
cv.waitKey(0)
结果:
7.黑帽
这是输入图像和输入图像经闭运算的差。
程序:
import cv2 as cv
import numpy as np
img = cv.imread('j.png',0)
kernel = np.ones((9,9),np.uint8)
closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)
blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)
#image,kernel,number of times erosion is applied.
cv.imshow('src',img)
cv.imshow('open',closing)
cv.imshow('fin',blackhat)
cv.waitKey(0)
结果:
结构元素
在Numpy的帮助下,我们在前面的例子中手动创建了一个结构元素。它是矩形的。但在某些情况下,您可能需要椭圆形/圆形的内核。所以为此,OpenCV有一个函数。您只需传递内核的形状和大小,即可获得所需的内核。
程序:
import cv2 as cv
import numpy as np
# Rectangular Kernel
print(cv.getStructuringElement(cv.MORPH_RECT,(5,5)))
print(" ")
# Elliptical Kernel
print(cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5)))
print(" ")
# Cross-shaped Kernel
print(cv.getStructuringElement(cv.MORPH_CROSS,(5,5)))
结果: