OpenCV 扩张

Salman Mehmood 2024年2月15日
OpenCV 扩张

本文将解释像侵蚀和扩张这样的形态变换概念,我们使用它们在 OpenCV 中的图像中从给定对象的边界添加和删除像素。

在 OpenCV 中使用侵蚀和扩张对图像应用形态变换

形态变换是在二值图像上执行的基于图像的操作。它需要两个输入,一个是原始图像,第二个是内核。

内核决定操作的性质。两个基本的形态学算子是侵蚀和扩张,我们也有它的一些变体,例如开闭等。

让我们通过一个例子来理解侵蚀和扩张。

侵蚀和扩张

侵蚀就像土壤侵蚀一样;它侵蚀了前景物体的边界。考虑这张 L 的图像,其中白色部分是数字 1,从 OpenCV 标准的角度来看,它也可以视为数字 255。

侵蚀会移除给定图像中对象边界处的像素。在图像中移除该对象 L 的边界后,在应用侵蚀后它会变薄。

从技术上讲,内核在图像中滑动,就像在 2D 卷积中一样。原始图像中的一个像素,无论是 1 还是 0,只有在内核下的所有像素都为 1 时才会被认为是 1;否则,它会被侵蚀或归零,因此根据内核的大小丢弃边界。

扩张与侵蚀相反;它将像素添加到给定图像中对象的边界。我们可以看到图像中 L 或物体 L 的边界在膨胀后变得更厚。

从技术上讲,如果内核下至少有一个像素为 1,则一个像素元素为 1,其结果将增加图像中的白色区域或前景对象的大小。

因此,如果你有一张想要去除噪声的图像,你可以先应用侵蚀操作,然后再进行膨胀,因为侵蚀会去除白噪声,但也会缩小我们的对象;这就是我们进行膨胀的原因,从而保留原始图像。它也可用于连接对象的破损部分。

侵蚀和扩张变化

形态变换有开、关等变化;打开是一个我们先应用侵蚀然后再膨胀的过程。关闭正好相反,我们应用膨胀然后侵蚀。

让我们使用 OpenCV 实现几个操作。我们需要导入所需的库。

在这一行中,我们使用 imread() 函数读取我们的图像,并将图像的路径作为参数提供,并将其存储在名为 imagedata_original 的变量中。

imagedata_original = cv2.imread("input.png")

在这段代码中,我们使用 numpy``ones() 函数定义 5x5 像素的内核,内核的数据类型是无符号 int

kernel = np.ones((5, 5), np.uint8)

我们使用 erode() 函数在下一行应用侵蚀。它需要几个参数,如原始图像、内核和迭代。

iterations 建议你要运行侵蚀过程的次数。如果你增加这个数字,你正在增加侵蚀的影响。

erosion_op = cv2.erode(imagedata_original, kernel, iterations=1)

我们将使用 dilate() 函数将膨胀应用于图像对象。参数类似于 erode() 函数中定义的参数。

dilation_op = cv2.dilate(imagedata_original, kernel, iterations=1)

现在我们将使用 morphologyEx() 函数来应用开运算。这个函数接受像输入图像 MORPH_OPEN 这样的参数,它表示要应用的打开操作,以及我们上面定义的内核。

opening_op = cv2.morphologyEx(imagedata_original, cv2.MORPH_OPEN, kernel)

我们给出下一条指令,将关闭操作应用于 morphologyEx() 函数。

closing_op = cv2.morphologyEx(imagedata_original, cv2.MORPH_CLOSE, kernel)

完整的源代码:

import cv2
import numpy as np
import matplotlib.pyplot as plot

FIG = plot.figure(figsize=(6, 5))

imagedata_original = cv2.imread("input.png")

FIG.add_subplot(2, 3, 1)
plot.imshow(imagedata_original)
plot.axis("off")
plot.title("original imagge")

kernel = np.ones((5, 5), np.uint8)

erosion_op = cv2.erode(imagedata_original, kernel, iterations=1)
FIG.add_subplot(2, 3, 2)
plot.imshow(erosion_op)
plot.axis("off")
plot.title("Erossion operatiopn")

dilation_op = cv2.dilate(imagedata_original, kernel, iterations=1)
FIG.add_subplot(2, 3, 3)
plot.imshow(dilation_op)
plot.axis("off")
plot.title("Dilation operatiopn")

opening_op = cv2.morphologyEx(imagedata_original, cv2.MORPH_OPEN, kernel)
FIG.add_subplot(2, 3, 4)
plot.imshow(opening_op)
plot.axis("off")
plot.title("Opening operatiopn")

closing_op = cv2.morphologyEx(imagedata_original, cv2.MORPH_CLOSE, kernel)
FIG.add_subplot(2, 3, 5)
plot.imshow(closing_op)
plot.axis("off")
plot.title("Clossing operatiopn")

plot.tight_layout()
plot.show()

让我们使用 matplotlib 在图像中运行并查看具有不同操作的不同输出。

侵蚀和扩张不同的输出

大多数人可能会感到困惑,为什么当从边界移除像素时,侵蚀图像中的文本显得很粗?为什么膨胀图像的文本在向对象的边界添加像素时显得很薄。

这是因为 OpenCV 将白色部分视为对象本身,而不是将黑色文本视为图像中的对象。因此,当我们应用侵蚀操作时,它会从黑色边界中移除白色像素,这就是黑色文本边界变粗的原因。

膨胀操作将白色像素添加到黑色文本的边界;这就是黑色文本变薄的原因。

作者: Salman Mehmood
Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn

相关文章 - Python OpenCV