一瓶水在收银台前一晃,听见“嘀”的一声,商品名和价格就出现了。看起来像扫码枪认出了整瓶水,实际完成的是一条更具体的链:读出编号,再用编号找到商品资料。
把这件事拆开,可以看见印刷标准、光学、电路、算法和门店系统怎样接在一起。

先有商品编号,收银台才有东西可查
常见零售商品可以使用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]
十三位中,第一位没有单独再占一组七模块。它通过左侧六组所采用的奇偶编码组合来表示。示例首位是6,对应的组合是LGGGLL,后面再分别读取左侧901234和右侧567892。
L、G、R可以理解成三套相关的字符表示。比如9的L码是0001011,0的G码是0100111,5的R码是1001110。数字并不是把同一个七格图案在任何地方都照抄一遍;读码器要同时考虑位置和编码组合。[2]
扫码枪先“看见”的,是反射光
在合适的照明下,白色区域反射较强,黑色区域反射较弱。传感器把反射变化变成电信号,后面的电路与算法再从信号中提取条空信息。[3]
线性激光读码器可以用扫描光束扫过条码;影像式读码器则利用照明、镜头和图像传感器获取图像,再寻找条码区域。CCD、CMOS及不同光源的具体组合因设备而异,不是每把扫码枪都靠同一束激光工作。
现实信号也没有印刷图案那么整齐。包装反光、距离变化、污渍和倾斜,都可能使信号偏暗、起伏或模糊。放大、滤波、增益调整和阈值判断等处理,帮助把它变成可分析的黑白区域、边缘和宽度。
对沿线扫描的信号来说,条空会体现为不同的时间宽度;对图像来说,则体现为像素中的空间宽度。两种方式最终都要恢复标准码制中的模块关系。
从黑白条空,恢复一串数字
译码时,一般要先找到静区与护栏,再估计基本模块宽度,把实际测到的宽窄归一到标准结构。然后按每组字符及奇偶模式查表,组合成完整编号。
它可以使用图像处理来定位、校正,却不需要先理解包装上的品牌图案,再猜这是什么商品。可读的标准条码已经把信息放在了约定的位置。
读出数字后,还要检查位数、结构与校验位。示例编号的前十二位是690123456789:
- 从左起,奇数位置的数字之和为
6+0+2+4+6+8=26。 - 偶数位置的数字之和为
9+1+3+5+7+9=34。 - 加权后为
26+3×34=128。 - 取使总和到达下一个10的倍数所需的数字,得到
(10−8) mod 10=2。
所以末位校验数字是2。最后再取一次模10,是为了让本来已经整除10时得到0,避免算出一个不能放进单个数字位置的10。[4]
校验能帮助发现许多读取或输入错误,但不能任意还原损坏的数字,更不能证明条码一定没被伪造。无法可靠读取时,设备通常会换扫描线、换帧或继续尝试,而不是把一个猜测结果交给收银系统。
“嘀”之后,还要经过门店系统
成功译码后,扫码枪通过主机接口输出数字串。USB HID可以表现得像键盘输入,串口可以传送数据,也有通过厂商SDK接入的方式。具体使用哪一种,由设备和收银系统决定。[5]
POS系统再用这串数字查询商品资料。假设门店资料中给示例编号登记了12.80元,收银界面就能显示对应商品,计算促销、税额并加入账单。生成交易流水、何时扣减库存,则按结账流程和业务规则执行,不是条码自己完成的动作。
成功译码提示音还可以配置。有些“嘀”只是在告诉你编号读到了,并不能单凭这声提示确认门店已经查到资料,或付款已经成功。[6]
日常那次几乎不用等待的扫码,把编号分配、条码印刷、光学采样、信号处理、译码校验和数据库查询压缩在很短的时间里。具体速度仍受设备、印刷质量、角度及系统响应影响,0.1秒不是每次结账都必须达到的固定保证。