OpenCV 4.13.0
开源计算机视觉库 (Open Source Computer Vision)
正在加载...
正在搜索...
未找到匹配项
使用形态学操作提取水平线和垂直线

上一篇教程: 击中击不中 (Hit-or-Miss)
下一篇教程: 图像金字塔

原作者Theodore Tsesmelis
兼容性OpenCV >= 3.0

目标

在本教程中,你将学习如何:

  • 通过创建自定义内核,应用两种非常常见的形态学算子(即膨胀和腐蚀),从而提取水平和垂直轴上的直线。为此,你将使用以下 OpenCV 函数:

    • erode()
    • dilate()
    • getStructuringElement()

    在本示例中,目标是从乐谱中提取音符。

原理

形态学操作

形态学是一组基于预定义的结构元素(也称为内核)处理图像的图像处理操作。输出图像中每个像素的值取决于输入图像中对应像素及其邻域的比较结果。通过选择内核的大小和形状,可以构建对输入图像中特定形状敏感的形态学操作。

两种最基本的形态学操作是膨胀(dilation)和腐蚀(erosion)。膨胀会增加图像中目标的边界像素,而腐蚀则恰恰相反。添加或移除像素的数量分别取决于用于处理图像的结构元素的大小和形状。通常,这两项操作遵循的规则如下:

  • 膨胀 (Dilation):输出像素的值是结构元素大小和形状范围内所有像素的最大值。例如,在二值图像中,如果内核范围内的输入图像像素中有任何一个值为 1,则输出图像的对应像素也将被设置为 1。后者适用于任何类型的图像(如灰度图、BGR 等)。
二值图像上的膨胀
灰度图像上的膨胀
  • 腐蚀 (Erosion):腐蚀操作则相反。输出像素的值是结构元素大小和形状范围内所有像素的最小值。请看下面的示例图:
二值图像上的腐蚀
灰度图像上的腐蚀

结构元素

如上所述,在任何形态学操作中,用于探测输入图像的结构元素都是最重要的部分。

结构元素是一个仅由 0 和 1 组成的矩阵,可以具有任意形状和大小。通常它比被处理的图像小得多,而值为 1 的像素定义了邻域。结构元素的中心像素(称为原点)标识了当前正在处理的目标像素。

例如,下图展示了一个 7x7 大小的菱形结构元素。

菱形结构元素及其原点

结构元素可以有许多常见的形状,如直线、菱形、圆盘、周期线和圆形,以及不同的尺寸。你通常会选择与输入图像中想要处理/提取的对象具有相同大小和形状的结构元素。例如,要在图像中查找线条,可以创建一个线性结构元素,稍后你将看到这一点。

代码

本教程的代码如下所示。

解释 / 结果

此处获取图像。

加载图像

灰度化

灰度图转二值图像

输出图像

现在我们准备应用形态学操作来提取水平和垂直线,从而将音符从乐谱中分离出来。但首先,让我们初始化用于该目的的输出图像

结构元素

正如在原理部分所指定的,为了提取我们想要的对象,我们需要创建相应的结构元素。既然我们要提取水平线,那么相应的结构元素将具有以下形状:

在源代码中,这由以下代码片段表示

垂直线同理,使用相应的结构元素:

同样地,代码表示如下:

细化边缘 / 结果

如你所见,目标基本达成了。然而,此时你会注意到音符的边缘有点粗糙。因此,我们需要细化边缘以获得更平滑的结果