目标

在本教程中:

理论

形态学变换是基于图像形状的一些简单操作。它通常在二值图像上执行。它需要两个输入,一个是我们的原始图像,第二个是决定操作性质的结构元素或内核。两个基本的形态学操作是腐蚀和膨胀。接下来如开,闭,梯度等也会介绍。在下图的帮助下,我们将逐一看到它们:

图片

1、腐蚀

腐蚀的基本概念就像土壤侵蚀一样,只侵蚀前景对象的边界(总是尽量保持前景为白色)。那它有什么作用呢?内核在图像中滑动(如二维卷积)。只有当内核下的所有像素都为 1 时,原始图像中的像素(1 或 0)才会被视为 1,否则会被侵蚀(变为零)。

所以根据内核的大小,边界附近的所有像素都将被丢弃。因此,前景对象的厚度或大小在图像中减少或只是白色区域减少。它有助于消除小的白色噪音(如我们在“颜色空间”一章中所看到的),分离两个连接的对象等。

作为一个例子,我将使用一个 5x5 内核,内核元素均为1。让我们看看它是如何工作的:

  1. mport cv2 as cv
  2. import numpy as np
  3. from matplotlib import pyplot as plt
  4. img = cv.imread('opencv-logo-white.png')
  5. blur = cv.blur(img,(5,5))
  6. plt.subplot(121),plt.imshow(img),plt.title('Original')
  7. plt.xticks([]), plt.yticks([])
  8. plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
  9. plt.xticks([]), plt.yticks([])
  10. plt.show()

结果:

图片

2、膨胀

它与腐蚀正好相反。这里,如果内核下至少有一个像素为“1”,则像素元素为“1”。所以它会增加图像中的白色区域,或者增加前景对象的大小。通常情况下,在去除噪音的情况下,腐蚀后会膨胀。因为,腐蚀消除了白噪声,但它也缩小了我们的对象。所以我们扩大它。由于噪音消失了,它们不会再回来,但我们的目标区域会增加到腐蚀之前的状态。它还可用于连接对象的断开部分。

  1. dilation = cv.dilate(img,kernel,iterations = 1)

结果:

图片

3、开运算

开只是腐蚀的另一个名称,随后是膨胀。正如我们上面所解释的,它对消除噪音很有用。在这里,我们使用 cv.morphologyEx()

  1. opening = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)

结果:

图片

4、闭运算

关闭与打开相反,膨胀后腐蚀。它在填充前景对象内的小孔或对象上的小黑点时很有用。

  1. closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)

结果:

图片

5、形态梯度

它是图像的膨胀和腐蚀之间的差值。

结果将类似于对象的轮廓。

  1. gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)

结果:

图片

6、顶帽

它是原图像和原图像开运算结果的差值。下面是 9x9 核的例子。

  1. tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)

结果:

图片

7、黑帽

它是原图像和原图像的闭的差值。

  1. blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)

结果:

图片

结构元素

在前面的例子中,我们在 numpy 的帮助下手工创建了一个结构参量。它是长方形的。但在某些情况下,您可能需要椭圆/圆形的内核。因此,opencv 有一个函数,cv.getStructuringElement()。只要传递内核的形状和大小,就可以得到所需的内核。

  1. # Rectangular Kernel
  2. >>> cv.getStructuringElement(cv.MORPH_RECT,(5,5))
  3. array([[1, 1, 1, 1, 1],
  4. [1, 1, 1, 1, 1],
  5. [1, 1, 1, 1, 1],
  6. [1, 1, 1, 1, 1],
  7. [1, 1, 1, 1, 1]], dtype=uint8)
  8. # Elliptical Kernel
  9. >>> cv.getStructuringElement(cv.MORPH_ELLIPSE,(5,5))
  10. array([[0, 0, 1, 0, 0],
  11. [1, 1, 1, 1, 1],
  12. [1, 1, 1, 1, 1],
  13. [1, 1, 1, 1, 1],
  14. [0, 0, 1, 0, 0]], dtype=uint8)
  15. # Cross-shaped Kernel
  16. >>> cv.getStructuringElement(cv.MORPH_CROSS,(5,5))
  17. array([[0, 0, 1, 0, 0],
  18. [0, 0, 1, 0, 0],
  19. [1, 1, 1, 1, 1],
  20. [0, 0, 1, 0, 0],
  21. [0, 0, 1, 0, 0]], dtype=uint8)

其他资源

在 HIPR2 的 形态学操作

练习