在OpenCV中进行图像预处理

今天,我们进一步深入,并处理在图像处理中常用的形态学操作。形态学操作用于提取区域、边缘、形状等。

什么是形态学操作?

形态学操作是在二值图像上进行的。二值图像可能包含许多不完美之处。特别是由一些简单的阈值操作产生的二值图像(如果你对阈值不熟悉,现在不用担心)可能包含许多噪声和畸变。OpenCV库中提供了不同的形态学操作来处理这些噪声和缺陷。

形态学操作生成与原始图像相同形状的图像。形态学操作将结构元素应用于输入图像。结构元素可以是任何形状。在今天的所有形态学操作中,将比较输入图像的每个像素与相邻像素以生成输出图像。

对于不同的形态学操作,比较方式有所不同。我们将详细讨论这一点。

在深入讨论问题之前,这是我们将在本教程中使用的图片:

在OpenCV中进行图像预处理

在这里,我们导入必要的包,将图像读取为数组,并将其转换为二值图像,正如前面提到的,形态学操作应用于二值图像:

import cv2 
import matplotlib.pyplot as plt
#Reading the image to an array
image = cv2.imread('practice.jpg')

#converting it to a binary image
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

这是’gray’的样子:

在OpenCV中进行图像预处理

我们将使用这个灰度图像来观察形态学操作的工作原理。

在深入示例之前,我想创建一个3×3的内核和一个6×3的内核:

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (33))
kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (63))

我们将在下面的形态学操作中使用这两个内核。如果需要,稍后我们将创建更多的内核。

内核可以是任何形状。你也可以尝试一些其他不同形状的内核,如1×4、4×4、5×5、7×18或更多。根据你的项目,内核的形状和大小可能会产生重大差异。

腐蚀

腐蚀做了它听起来的事情。它侵蚀图像的方式就像水侵蚀河岸一样。在腐蚀操作中,它将一个结构元素从输入图像的左到右、从上到下滑动。如果结构元素内的所有像素都大于0,则保留原始像素值。否则,将像素设置为0。

腐蚀用于去除被视为噪声的小斑点。

以下是腐蚀的语法:

eroded1 = cv2.erode(gray.copy(), kernel, iterations = 1)
cv2.imwrite('erode1.jpg', eroded1)

腐蚀函数cv2.erode()使用图像、结构元素和迭代次数。这里的’iterations’参数是可选的。如果你不提供’iterations’值,它会自动执行一次迭代。

这是’erode1’的样子:

在OpenCV中进行图像预处理

将其与原始图像进行比较。它已经被腐蚀掉了。此外,原始图像中的其他小元素也被去除了。

在任何OCR(光学字符识别)项目中,我们只想识别字母或数字。但图像中可能还有其他更小的字母和元素,可能会混淆你的算法。腐蚀可以消除这些噪声。

如果我们尝试2或3次迭代,它将被更加腐蚀:

eroded2 = cv2.erode(gray.copy(), kernel, iterations = 2)
cv2.imwrite('erode2.jpg', eroded2)

eroded3 = cv2.erode(gray.copy(), kernel, iterations = 3)
cv2.imwrite('erode3.jpg', eroded3)

这是2次和3次迭代的结果:

在OpenCV中进行图像预处理
在OpenCV中进行图像预处理

你可以看到,随着迭代次数的增加,图像变得越来越腐蚀。因此,如果你需要提取粗体并且周围有很多噪声的字母,可以通过侵蚀图像来消除噪声。

膨胀

膨胀与腐蚀的作用恰恰相反。它增加前景,从而有助于连接断裂部分。在膨胀中,如果结构元素中的任何像素大于0,则将像素值设置为白色或255。这里我们使用1和3次迭代进行膨胀,以查看差异并了解其工作原理。

dilated1 = cv2.dilate(gray.copy(), kernel, iterations=1)
cv2.imwrite('dilate1.jpg', dilated1)

dilated3 = cv2.dilate(gray.copy(), kernel, iterations=3)
cv2.imwrite('dilate3.jpg', dilated3)

这是膨胀1次迭代(第二个图像)和3次迭代(第三个图像)的图像。原始灰度图像在顶部。

在OpenCV中进行图像预处理
在OpenCV中进行图像预处理
在OpenCV中进行图像预处理

如果我们将顶部的原始图像与经过一次膨胀的第二个图像进行比较,会有一些微小的差异,经过3次迭代后,差异变得更加显著。根据你的项目,你可以使用尽可能多的迭代次数。

开运算

开运算也是从图像中去除噪声的另一种方法。它在一次迭代中执行腐蚀后进行膨胀。这里有两个示例,我使用了之前准备好的内核和内核1:

opening1 = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel)
cv2.imwrite('open1.jpg', opening1)

opening2 = cv2.morphologyEx(gray, cv2.MORPH_OPEN, kernel1)                         )
cv2.imwrite('open2.jpg', opening2)

这里,我将原始图像放在顶部,然后是’opening1’操作的图像,底部是’opening2’操作的图像。

在OpenCV中进行图像预处理
在OpenCV中进行图像预处理
在OpenCV中进行图像预处理

正如你所看到的,在使用3×3内核的中间图片中,左下角的小文本消失了,在使用大小为6×3的kernel1的底部图片中,添加了一个黑色阴影。

闭运算

闭运算与开运算相反。在闭运算中,首先进行膨胀,然后进行腐蚀。

让我们看一些示例:

closing1 = cv2.morphologyEx(gray.copy(), cv2.MORPH_CLOSE, kernel, iterations=1)
cv2.imwrite('close1.jpg', closing1)

closing3 = cv2.morphologyEx(gray.copy(), cv2.MORPH_CLOSE, (33), iterations=3)
cv2.imwrite('close3.jpg', closing3)

与之前一样,我将原始灰度图像放在顶部进行比较,然后是’closing1’和’closing2’的输出图像。

在OpenCV中进行图像预处理
在OpenCV中进行图像预处理
在OpenCV中进行图像预处理

形态梯度

形态梯度对于检测对象的轮廓非常有用。它可用于边缘检测。基本上,它是膨胀操作和腐蚀操作之间的差异。

这是使用kernel和kernel1的两个示例:

grad1 = cv2.morphologyEx(gray.copy(), cv2.MORPH_GRADIENT, kernel)
cv2.imwrite('grad1.jpg', grad1)

grad2 = cv2.morphologyEx(gray.copy(), cv2.MORPH_GRADIENT, kernel1)
cv2.imwrite('grad3.jpg', grad2)

这是’grad1’和’grad2’的输出图像:

在OpenCV中进行图像预处理
在OpenCV中进行图像预处理

正如你所看到的,不同形状的内核提供了两种不同类型的输出。

顶帽/白帽

顶帽操作是原始二值图像与开运算之间的差异。当你需要从黑色背景中找到亮区域时,它很有帮助。

对于这个操作,我们将使用不同的输入图像和其他操作:

这是输入图像:

在OpenCV中进行图像预处理

这辆车的车牌比车身更亮。让我们看看如何提取出那个白色区域。和往常一样,我们应该将其转换为灰度图像,并定义两个不同的内核。

image = cv2.imread('car.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (235))

kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT, (358))

我尝试了一些不同形状的内核,然后使用了这两个内核大小。请随意尝试一些其他内核大小并比较结果。

tophat1 = cv2.morphologyEx(gray.copy(), cv2.MORPH_TOPHAT, kernel1)
cv2.imwrite('tophat1.jpg', tophat1)

这是输出图像:

在OpenCV中进行图像预处理

看,它检测到了车牌从车身上的亮区域。

黑帽

黑帽操作与顶帽相反。

blackhat1 = cv2.morphologyEx(gray.copy(), cv2.MORPH_BLACKHAT, kernel)
cv2.imwrite('blackhat1.jpg', blackhat1)

这是黑帽操作的输出:

在OpenCV中进行图像预处理

如果你注意到,它聚焦于车牌上的字母。

经过顶帽操作后,检测到了车牌区域,经过黑帽操作后,突出显示了白色车牌上的黑色字母。

因此,如果我们想要检测车牌上的数字,我们将执行顶帽操作,然后是黑帽操作。

结论

本文试图通过示例解释一些众所周知的形态学操作。在将来的一些文章中,我将使用它们来解决一些实际问题。那将更有趣。

☆ END ☆
作者:磐怼怼,微信搜索「uncle_pn」,欢迎添加小编微信「 woshicver」,每日朋友圈更新一篇高质量博文

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至1393616908@qq.com 举报,一经查实,本站将立刻删除。

(0)

相关推荐

发表回复

登录后才能评论