前言
身在物流行业,扫描条码的场景很多。为了改造 ZBar 使其返回条码方向(条码与水平线的夹角),阅读了 ZBar 的源码。总结一下。(没有弄清楚所有细节,只说说我弄清楚的部分)
主流程
应该大家都知道 ZBar 是 Z 字型扫描的。(为什么要 Z 字型扫描?不清楚。)一次扫描一行或者一列,在扫描过程中做滤波,EWMA,指数加权移动平均,可以消除部分噪声影响,然后计算梯度变化,确定边缘,计算当前边缘与上一边缘的距离作为一个条码元素( element,bar 或者 space)的宽度,这些元素宽度放在一个滑动窗口数组中,以 Code 128 为例,这个数组的长度是 6,因为 Code 128 是 3 个 bar 加 3 个 space 表示一个字元。每个字元宽度是最窄 element 的 11 倍,各个 element 根据类型(bar、space)以及所占份数(宽度是最窄 element 的几倍)被应设成二机制数,(举例来说,x 代表一份宽度的 bar,o 代表一份宽度的 space,xxxoxxooo 被映射成 111011000),根据二进制数查表,得到字符。在对这个宽度数组进行解码的时候使用了一个叫 like-edge measurement 也叫 similar-edge measurement 的机制进行计算,操作上是,计算第 0 和第 1 element 的宽度和 a、第 1 和第 2 element 的宽度和 b、… 第 4 和 第 5 element 的宽度和,可以解决一部分因为边界模糊而导致的宽度误差。识别到终止符的时候组装字符返回结果,再次识别出某结果,该结果quality 加 1(quality 可以理解成 votes,可以考虑在 quality 大于某个阈值时提前结束识别,减少不必要的计算。)