python-opencv Tutorials 一码人翻译(14)图像处理----形态转换

目标

在这一章,

我们将学习不同的形态操作,如侵蚀、扩张、打开、关闭等。

我们将看到不同的功能,如 cv.erode()cv.dilate()cv.morphologyEx()等。

理论

形态转换是基于图像形状的一些简单操作。它通常是在二进制图像上执行的。它需要两个输入,一个是我们的原始图像,第二个是构造元素或内核,它决定了操作的性质。两种基本的形态运算符是侵蚀和扩张。然后它的变形形式,如开口,闭合,梯度等也开始发挥作用。我们将逐一看到它们,并提供以下图片:

  • 1。侵蚀

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

所以发生的是,边界附近的所有像素都将根据内核的大小而被丢弃。因此,前景对象的厚度或大小会减少或简单地减少图像中的白色区域。它有助于消除小的白色噪音(正如我们在彩色空间章节中看到的),分离两个连接的物体,等等。

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

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('j.png',0)
kernel = np.ones((5,5),np.uint8)
erosion = cv.erode(img,kernel,iterations = 1)

plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(erosion ),plt.title('erosion')
plt.xticks([]), plt.yticks([])
plt.show()

  • 2。扩张

它正好与侵蚀相反。在这里,一个像素元素是“1”,如果内核下至少有一个像素是“1”。所以它增加了图像的白色区域或者前景物体的大小增加了。通常情况下,在噪音去除的情况下,侵蚀之后是扩张。因为,侵蚀消除了白色的噪音,但它也使我们的物体收缩。所以我们扩张。既然噪音消失了,它们就不会回来了,但是我们的目标区域会增加。它在连接一个物体的破碎部分时也很有用。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('oj.png',0)
kernel = np.ones((5,5),np.uint8)
dilation = cv.dilate(img,kernel,iterations = 1)

plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(dilation ),plt.title('dilation')
plt.xticks([]), plt.yticks([])
plt.show()

  •  
  • 3。开放

开放只是侵蚀的另一个名字,接着是扩张。正如我们上面所解释的,它在消除噪声方面很有用。这里我们使用的是函数,cv.morphologyEx()

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('oj.png',0)
kernel = np.ones((5,5),np.uint8)
opening = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)

plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(opening ),plt.title('opening')
plt.xticks([]), plt.yticks([])
plt.show()

  • 图像
  • 4所示。关闭

封闭是开放的逆转,扩张之后是侵蚀。它对于关闭前台对象中的小洞或对象上的小黑点是很有用的。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('cj.png',0)
kernel = np.ones((5,5),np.uint8)
closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)

plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(closing ),plt.title('closing')
plt.xticks([]), plt.yticks([])
plt.show()

  • 5。形态学梯度

这就是图像的扩张和侵蚀的区别。

结果看起来就像这个物体的轮廓。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('j.png')
kernel = np.ones((5,5),np.uint8)
gradient = cv.morphologyEx(img, cv.MORPH_GRADIENT, kernel)

plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(gradient  ),plt.title('gradient')
plt.xticks([]), plt.yticks([])
plt.show()

  • 6。高顶礼帽

它是输入图像和图像的打开之间的区别。下面的例子是为9x9内核完成的。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('j.png')
kernel = np.ones((5,5),np.uint8)
tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)

plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(tophat ),plt.title('tophat')
plt.xticks([]), plt.yticks([])
plt.show()

  • 7。黑帽

这是输入图像的关闭和输入图像之间的区别。

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt

img = cv.imread('j.png')
kernel = np.ones((5,5),np.uint8)
blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)

plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blackhat  ),plt.title('blackhat ')
plt.xticks([]), plt.yticks([])
plt.show()

结构化元素

我们在前面的例子中手动创建了一个结构化的元素,帮助Numpy。它是矩形。但在某些情况下,你可能需要椭圆/圆形的内核。因此,OpenCV有一个函数,cv.getstruct ingelement()。你只要传递内核的形状和大小,就会得到想要的内核。

# 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)

猜你喜欢

转载自blog.csdn.net/qq_41905045/article/details/81335275