opencv(4.5.3)-python(十四)--形态学转换

2022-12-07 10:16:03 浏览数 (1)

翻译及二次校对:cvtutorials.com

目标

在本章中:

  • • 我们将学习不同的形态学操作,如腐蚀、膨胀、开运算、闭运算等。
  • • 我们将看到不同的函数,如:cv.erode(), cv.dilate(), cv.morphologyEx() 等。

理论

形态学变换是基于图像形状的一些简单操作。它通常是在二进制图像上进行的。它需要两个输入,一个是我们的原始图像,第二个被称为结构化元素或核,它决定了操作的性质。两个基本的形态学运算符是腐蚀和膨胀。然后,它的变体形式,如开运算、闭运算、梯度等也开始发挥作用。我们将在以下图片的帮助下逐一看到它们。

  1. 1. 腐蚀

腐蚀的基本概念就像土壤腐蚀一样,只是它腐蚀了前景物体的边界(总是尽量保持前景为白色)。那么它是怎么做的呢?核在图像中滑动(如二维卷积)。原始图像中的一个像素(1或0)只有在核下的所有像素都是1时才会被认为是1,否则就会被腐蚀(变成0)。

因此,发生的情况是,根据核的大小,所有靠近边界的像素将被丢弃。因此,前景物体的厚度或大小减少了,或者说是图像中的白色区域减少了。这对于去除小的白色噪音(正如我们在色彩空间一章中所看到的),分离两个相连的物体等很有用。

这里,作为一个例子,我将使用一个充满1的5x5核。让我们看看它是如何工作的。

代码语言:javascript复制
import cv2 as cv
import numpy as np
img = cv.imread('j.png',0)
kernel = np.ones((5,5),np.uint8)
erosion = cv.erode(img,kernel,iterations = 1)

结果如下:

2. 膨胀

它与腐蚀刚好相反。这里,一个像素元素是 "1",如果核心下至少有一个像素是 "1"。因此,它增加了图像中的白色区域或增加了前景物体的大小。通常情况下,在去除噪声等情况下,腐蚀之后是膨胀。因为,腐蚀可以去除白色噪音,但它也会缩小我们的物体。所以我们要膨胀它。由于噪音已经消失,它们不会再出现,但我们的对象面积会增加。它在连接一个物体的破碎部分时也很有用。

代码语言:javascript复制
dilation = cv.dilate(img,kernel,iterations = 1)

结果如下:

3. 开运算

开运算只是腐蚀和膨胀的另一个名称。正如我们上面解释的那样,它在去除噪音方面很有用。在这里,我们使用函数cv.morphologyEx()

代码语言:javascript复制
opening = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)

结果如下:

  1. 4. 闭运算

闭运算是开运算的反面,膨胀之后是腐蚀。它在关闭前景物体内部的小孔,或物体上的小黑点时很有用。

代码语言:javascript复制
closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)

结果如下:

5. 形态学梯度

它是图像的膨胀和腐蚀之间的区别。

其结果将看起来像物体的轮廓。

代码语言:javascript复制
gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)

结果如下:

6. 高帽

它是输入图像和图像开运算之间的差异。下面的例子是针对一个9x9的核做的。

代码语言:javascript复制
tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)

结果如下:

7. 黑帽

它是指输入图像和输入图像的闭运算度之差。

代码语言:javascript复制
blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)

结果如下:

结构化元素

在前面的例子中,我们在Numpy的帮助下手动创建了一个结构化元素:矩阵。但在某些情况下,你可能需要椭圆/圆形的核。因此,为了这个目的,OpenCV有一个函数,cv.getStructuringElement()。你可以通过核的形状和大小去定义一个核。

代码语言:javascript复制
# Rectangular Kernel
>>> cv.getStructuringElement(cv.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
>>> cv.getStructuringElement(cv.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
>>> cv.getStructuringElement(cv.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)

其他资源

  • • HIPR2的形态学操作

0 人点赞