QuaggaJS在给定图像中定位条形码的工作原理

这篇博文将介绍QuaggaJS在给定图像中定位条形码的工作原理,QuaggaJS是一种用JavaScript编写的高级条形码读取器。gitHub地址

在下面的图片中,蓝色矩形突出显示了条形码的位置,并显示了一条红线,说明扫描成功。这篇博文将介绍蓝色矩形及其确定方式。
在这里插入图片描述

一、介绍

条形码定位器的主要目的是在图像中找到看起来像条形码的图案。条形码通常以黑条和中间的空白为特征。条形码的整体大小取决于编码信息的数量(Code128);但是,条形码也可以固定宽度(EAN13)。

二、步骤

1. 创建图像的二进制表示

创建一个二进制图像(需要条形码与背景的分离效果较好)

最简单的方法是将全局阈值设置为127,并为每个像素确定比阈值亮(> =
127)还是暗(<127)。尽管此方法可能是最简单的实现方法,但结果通常并不令人满意,因为它没有考虑整个图像的照度变化。

为了解决图像中亮度的变化,Otsu的方法更好一些,该方法对源图像的直方图进行操作,并尝试将前景与背景分离。
在这里插入图片描述

2. 将图像切成网格(20 x 15个单元)

二进制图像作为一个整体没有提供太多有关其内容的信息。为了理解图像中包含的结构,必须将图像分成较小的部分,然后将其相互独立地描述。并将所得的描述与我们的假设**(彼此接近且方向相似的直线)**进行比较,并考虑将其作进一步处理或丢弃。
当假定图像的长宽比为4:3时,将二进制图像切成20 x 15个单元的网格工作良好。
检测每一行中小格中的线,如果大多数线彼此平行,则将计算平均角度。

在这里插入图片描述

3. 提取每个细胞的骨架

首先将宽度标准化为1px,这是借助称为骨架化的方法完成的。 此方法尝试消除每个条形的重量。只要有未处理的像素,我就可以通过连续腐蚀和膨胀内容来实现此任务。

该图像清楚地显示了条形码的位置,并且代码条减小到了其最小宽度1px。 由于算法的特性,在条形码的边界上引入了一些伪像。但是,这应该不会给我们带来太大的麻烦,因为我们允许正在处理的数据中存在一定的错误。

  • 将骨架分成几部分
  • 组件标签
  • 计算每个零件的旋转
  • 确定电池质量(旋转均匀性)
  • 查找旋转相似的连接单元
  • 创建连接单元的边界框

在这里插入图片描述

4. 组件标记

为了确定每个单元格是否包含平行线,必须将骨架化内容(理想情况下包含感兴趣区域的直线)分离为单独的片段(线)。这可以通过应用一种称为连接组件标记的技术来实现,该技术将给定的区域分割成单独的元件。在条形码模式的情况下,一个单元格中的所有行都被分割成一行,然后通过它们的旋转来加权。

由于组件标记在计算方面通常相当昂贵,因此快速算法对于创建实时应用程序至关重要。经过一定的研究,我找到了Fu Chang,Chun Jen Chen和Chi Jen Lu在CodeProject上的论文“基于轮廓跟踪技术的线性时间分量标注算法”的一个实现。

应用组件标记算法后,结果如图:
在这里插入图片描述如前所述,每一个细胞都是单独处理的,这就是为什么每一种颜色在整个细胞中重复使用的原因。单元中每个组件的颜色都是唯一的,表示算法给定的标签。下图显示了两个提取单元的放大版本。左一个表示可能的条形码区域,而右一个不包含太多,但噪声。
在这里插入图片描述每个标签可以被视为条形码模式的可能条。为了能够对这种表示进行分类,需要计算每个条的定量值,然后将其与其他组件进行比较。

5. 确定组件的方向

单元内单个元件的方向由中心图像矩计算。这种方法通常用于提取有关二值图像方向的信息。在这种情况下,二值图像由标记的组件表示。每个分量都可以看作是它自己的二值图像,其中的中心图像矩可以被计算出来。

如下式所示,二值图像的方向(表示为θ)可由其中心矩(μ)确定。
根据原始矩阵M,质心(x,y) 等计算,由于我们需要高达二阶的图像矩,下面的列表显示了每个矩的计算。x和y上的和表示整个图像上的迭代,而I(x,y)表示x,y位置的像素值。在这种情况下,值可以是0或1,因为我们在二值图像上操作。

在此步骤之后,将为每个组件指定一个具有确定角度值的属性。

6. 测定细胞质量

现在,每个单元都包含具有各自方向的组件,我们可以开始根据这些属性对单元进行分类。
首先,不含或只含一种成分的细胞被立即丢弃,不用于进一步加工。此外,未覆盖至少6px(M00)的组件不包括在有关受影响单元的任何后续计算中。此预过滤列表用作确定单个单元中组件角度均匀性的基础。

对于条形码,单元格中的每个组件应彼此平行。但是,由于噪声、失真和其他影响,情况并非总是如此。

应用简单的聚类技术,找出包含条形码模式的组件之间的相似性。首先,对所有的角度按一定的阈值进行聚类,然后选择成员数最多的聚类。只有当这个簇的成员大小大于初始集的3/4时,这个单元才被认为是条形码模式的一部分。

从现在起,此单元格称为修补程序,其中包含以下信息:

  • 索引(网格中的唯一标识符)
  • 定义单元的边界框
  • 所有组件及其相关力矩
  • 平均角度(从簇计算)
  • 指向方向的向量
    下图突出显示了分类为条形码模式的补丁(单元)。
    在这里插入图片描述从上图中可以看出,有些细胞被错误地归类为条形码模式的一部分。只需找到相邻区域(由多个细胞组成)并丢弃所有剩余区域,即可检测到这些假阳性。

7. 查找连接的单元格

基本上,细胞可以被认为是条形码的一部分,如果他们是邻居和共享共同的属性。这个分组是通过一个简单的递归组件标记算法来完成的,该算法使用方向相似性进行操作。

为了将组件视为标签的成员,其向量必须指向与其相邻向量相同的方向。考虑到变形和其他几何影响引起的偏差,方向偏差可高达5%。下图显示了连接的单元格,其中颜色定义了到特定组的链接。

在这里插入图片描述唯一一组包含多个块的是黄色块。有时甚至相邻细胞的颜色也不同。如果这些组件块的方向差异过大(>5%),就会发生这种情况。

8. 选择组

接下来,我们将尝试识别那些最有可能包含条形码的组。由于一个图像中可以同时存在多个条形码,因此首先对组进行排序,然后根据其成员数(补丁)进行过滤。
在这里插入图片描述在该示例中,仅黄色区域保留下来了,进入下一步骤;

8. 创建边界框

最后,可以获得概述条形码位置所需的所有信息。在最后一步中,将创建一个最小边界框,该边界框跨越一个组中的所有补丁块。首先,计算包含补丁块的平均角度,然后用该平均角度旋转细胞。然后,通过使用所有补丁块的最外角来计算边界框。

最后,将边界框反向旋转以将其变换回原点。结果如下图所示。

在这里插入图片描述如上图所示,边界框正好位于打印条形码图案的位置。

感谢你阅读我的阅读,我希望你喜欢它,就像当我学习新事物时感受到的每一次乐趣。

参考

猜你喜欢

转载自blog.csdn.net/qq_40985985/article/details/110819454