一瓶水在收银台前一晃,听见“嘀”的一声,商品名和价格就出现了。看起来像扫码枪认出了整瓶水,实际完成的是一条更具体的链:读出编号,再用编号找到商品资料。

把这件事拆开,可以看见印刷标准、光学、电路、算法和门店系统怎样接在一起。

一支手持扫码枪放在收银台支架上,旁边有留白标签的纸盒,后方是模糊的收银屏幕。
扫码场景的概念插画,标签留白以避免虚构条码;下文的EAN-13图案由标准编码规则直接生成。

先有商品编号,收银台才有东西可查

常见零售商品可以使用GTIN,也就是全球贸易项目代码来标识。相同商品规格的许多件商品,可以印同一个GTIN;它通常标识的是这一种销售商品,不是这一瓶水独有的身份证。[1]

编号与价格也要分开。对于普通GTIN商品,门店用编号关联商品名、售价、促销和库存等资料。同一个编号在不同门店、不同促销期间,价格可以不同。称重商品和店内码还有自己的编码规则,不能把所有场景一概而论。

下面使用6901234567892做教学计算。它符合示例的校验规则,不表示这里确认了一个实际注册商品,更不代表它真的卖12.80元。

EAN-13,为什么十三位数字只画十二组

EAN-13是一种常见的条码符号,用黑白条空来表示13位编号。这里的基础单位叫“模块”,可以把它理解成横向最窄的一格;几格相连,就形成较宽的黑条或白空。

不算左右留白,它的结构是:

部分占用模块数作用
起始护栏3帮助确定码制结构和边界
左侧六组字符6×7每组按相应编码表表示一个数字
中间护栏5分开左右两半
右侧六组字符6×7每组按右侧编码表表示一个数字
结束护栏3完成结构边界

总数是3 + 42 + 5 + 42 + 3 = 95个模块。左右的静区是另外保留的空白,让读码器能把条码与包装上的其他图案区分开。[2]

从6901234567892生成的EAN-13条码按标准L/G/R编码确定性生成。首位6通过左六位LGGGLL奇偶模式表示。左右静区分别保留11和7模块;正文条码区95模块,校验位2。号码仅作教学计算,不声称分配给实际商品。EAN-13编码示例690123456789295个模块,不含左右静区
按GS1的EAN-13规则确定性生成,包含95个编码模块及两侧静区,全部95位编码与独立ReportLab编码器一致;号码仅作教学,不声称已分配给某个真实商品。图示不作为印刷尺寸或条码质量认证。

十三位中,第一位没有单独再占一组七模块。它通过左侧六组所采用的奇偶编码组合来表示。示例首位是6,对应的组合是LGGGLL,后面再分别读取左侧901234和右侧567892。

L、G、R可以理解成三套相关的字符表示。比如9的L码是0001011,0的G码是0100111,5的R码是1001110。数字并不是把同一个七格图案在任何地方都照抄一遍;读码器要同时考虑位置和编码组合。[2]

扫码枪先“看见”的,是反射光

在合适的照明下,白色区域反射较强,黑色区域反射较弱。传感器把反射变化变成电信号,后面的电路与算法再从信号中提取条空信息。[3]

线性激光读码器可以用扫描光束扫过条码;影像式读码器则利用照明、镜头和图像传感器获取图像,再寻找条码区域。CCD、CMOS及不同光源的具体组合因设备而异,不是每把扫码枪都靠同一束激光工作。

现实信号也没有印刷图案那么整齐。包装反光、距离变化、污渍和倾斜,都可能使信号偏暗、起伏或模糊。放大、滤波、增益调整和阈值判断等处理,帮助把它变成可分析的黑白区域、边缘和宽度。

对沿线扫描的信号来说,条空会体现为不同的时间宽度;对图像来说,则体现为像素中的空间宽度。两种方式最终都要恢复标准码制中的模块关系。

从黑白条空,恢复一串数字

译码时,一般要先找到静区与护栏,再估计基本模块宽度,把实际测到的宽窄归一到标准结构。然后按每组字符及奇偶模式查表,组合成完整编号。

它可以使用图像处理来定位、校正,却不需要先理解包装上的品牌图案,再猜这是什么商品。可读的标准条码已经把信息放在了约定的位置。

读出数字后,还要检查位数、结构与校验位。示例编号的前十二位是690123456789:

  1. 从左起,奇数位置的数字之和为6+0+2+4+6+8=26。
  2. 偶数位置的数字之和为9+1+3+5+7+9=34。
  3. 加权后为26+3×34=128。
  4. 取使总和到达下一个10的倍数所需的数字,得到(10−8) mod 10=2。

所以末位校验数字是2。最后再取一次模10,是为了让本来已经整除10时得到0,避免算出一个不能放进单个数字位置的10。[4]

校验能帮助发现许多读取或输入错误,但不能任意还原损坏的数字,更不能证明条码一定没被伪造。无法可靠读取时,设备通常会换扫描线、换帧或继续尝试,而不是把一个猜测结果交给收银系统。

“嘀”之后,还要经过门店系统

成功译码后,扫码枪通过主机接口输出数字串。USB HID可以表现得像键盘输入,串口可以传送数据,也有通过厂商SDK接入的方式。具体使用哪一种,由设备和收银系统决定。[5]

POS系统再用这串数字查询商品资料。假设门店资料中给示例编号登记了12.80元,收银界面就能显示对应商品,计算促销、税额并加入账单。生成交易流水、何时扣减库存,则按结账流程和业务规则执行,不是条码自己完成的动作。

成功译码提示音还可以配置。有些“嘀”只是在告诉你编号读到了,并不能单凭这声提示确认门店已经查到资料,或付款已经成功。[6]

日常那次几乎不用等待的扫码,把编号分配、条码印刷、光学采样、信号处理、译码校验和数据库查询压缩在很短的时间里。具体速度仍受设备、印刷质量、角度及系统响应影响,0.1秒不是每次结账都必须达到的固定保证。