目标
在本章中,
理论
形态学转换是基于图像形状的一些简单操作。它通常在二值图像上执行。它需要两个输入,一个是我们的原始图像,另一个称为结构元素或内核,决定操作的性质。两个基本形态学算子是侵蚀和膨胀。然后,它的变体形式如开启、闭合、梯度等也会发挥作用。我们将借助以下图像逐一查看它们
图像
1. 侵蚀
侵蚀的基本思想就像土壤侵蚀一样,它侵蚀前景色对象的边界(总是尝试将前景色保持为白色)。那么它做了些什么?内核滑动通过图像(与 2D 卷积一样)。只有内核下方的所有像素都为 1,原始图像中的像素(1 或 0)才被认为是 1,否则它被侵蚀(变为 0)。
因此,发生的事情是,根据内核的大小,所有边界附近的像素都将被丢弃。因此,前景色对象的厚度或大小减小,或者图像中的白色区域减小。它可用于移除小的白色噪声(如我们在色彩空间章节中看到的),分离两个连接的对象等。
在此,作为一个示例,我将使用一个充满 1 的 5x5 内核。让我们看看它是如何工作的
import cv2 as cv
import numpy as np
img =
cv.imread(
'j.png', cv.IMREAD_GRAYSCALE)
assert img is not None, "file could not be read, check with os.path.exists()"
kernel = np.ones((5,5),np.uint8)
erosion =
cv.erode(img,kernel,iterations = 1)
CV_EXPORTS_W Mat imread(const String &filename, int flags=IMREAD_COLOR)
从文件中加载图像。
void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())
使用特定结构元素腐蚀图像。
结果
图像
2. 膨胀
它是腐蚀的反面。这里,如果内核下的至少一个像素为“1”,则像素元素为“1”。因此,它会增加图像中的白色区域或前景对象的大小。通常,在像去除噪声等情况下,膨胀后接腐蚀。因为,腐蚀会去除白色噪声,但它也会使我们的物体缩小。因此我们对它进行膨胀。由于噪声已经消失,因此它们不会回来,但我们的对象区域会增加。它还可用于连接对象的断开部分。
dilation =
cv.dilate(img,kernel,iterations = 1)
void dilate(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())
使用特定结构元素膨胀图像。
结果
图像
3. 开运算
开运算只是“腐蚀后再膨胀”的另一种说法。它可用于去除噪声,如上所述。这里我们使用函数,cv.morphologyEx()
void morphologyEx(InputArray src, OutputArray dst, int op, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, const Scalar &borderValue=morphologyDefaultBorderValue())
执行高级形态学变换。
结果
图像
4. 闭运算
闭运算是开运算的逆运算,先膨胀后腐蚀。它可用于闭合前景对象内部的小孔或对象上的小黑点。
结果
图像
5. 形态学梯度
它是图像的膨胀和腐蚀之间的差异。
结果将看起来像对象的轮廓。
结果
图像
6. 顶帽
它是输入图像与其开运算之间的差异。以下示例针对 9x9 内核完成。
结果
图像
7. 黑帽算法
它是在输入图像和闭合输入图像之间的差。
结果
图像
形态学结构元素
在之前的示例中,我们使用 Numpy 手动创建了结构元素。它是矩形形状。但在某些情况下,你可能需要椭圆形/圆形内核。为此,OpenCV 有一个函数cv.getStructuringElement()。你只需要传递内核的形状和大小,便可得到所需的内核。
[[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]]
[[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]]
[[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]]
Mat getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1))
返回指定大小和形状的结构元素,用于形态学运算。
附加资源
- 形态学运算 in HIPR2
练习