Qraft

二维码读取速度的极限 - 一秒能扫多少次

智能手机的扫描速度 - 感觉与实测的差距

用手机扫二维码时,结果几乎是瞬间显示出来的。但在这个「几乎瞬间」的内侧,好几道处理正高速地接连发生:摄像头取得一帧画面,从图像中检测定位图案,做几何校正,对模块逐个取样,再施加纠错把数据解出来。这一整串处理在一般的手机上只需极短的时间。

可用性研究者雅各布·尼尔森在 1993 年的著作中,认为用户感到「瞬间」的界线约为 0.1 秒(100 毫秒),普通手机处理二维码甚至让人感觉比这条线还短。也就是说,当我们觉得「一下就读出来了」的时候,手机内部实际已经跑完了海量的运算。

反过来,有时会觉得「怎么半天读不出来」,那多半不是解码慢,而是前面的步骤反复失败:对焦没合上、光线不足让黑白的分界糊掉、或者手抖导致画面拖影,定位图案一直找不到。这种情况下手机其实在每秒重试几十次,只是每一次都没能走到解码那一步。

瓶颈在哪里

限制二维码读取速度的因素,大致可以归为三项。

1. 摄像头的帧率:手机摄像头通常以 30 fps(每秒 30 帧)取得画面,也就是说二维码的图像最快也只能每约 33 毫秒取得一次。60 fps 的摄像头能把这个间隔缩到约 16 毫秒,但帧率再高,图像处理跟不上也就没有意义。

2. 定位图案的检测:要在画面里找出三个定位图案,必须扫过整幅图像,计算量因此很大,分辨率越高扫得越久。效率高的算法一般采用两段式:先把图像缩小后粗扫,找到候选位置再用原分辨率精确检测。

3. 纠错的解码:里德-所罗门码的解码包含有限域上的多项式运算,数据量越大计算时间越长。纠错级别为 H 的大容量二维码,解码的耗时也可能变长。

值得注意的是,这三项之中拖慢速度最明显的往往不是解码,而是第二项的检测。解码的耗时大体由数据量决定,比较好预估;检测则取决于画面里有什么,背景越杂乱,需要排除的候选就越多。这也是为什么把二维码放在干净的底色上、四周留足静区,实际扫起来会明显更快。

取得画面30 fps 时约每 33 毫秒 1 次
检测定位图案要扫过整幅图像
几何校正
模块采样
纠错数据量越大越耗时
解码
一次读取的处理顺序,警示色的字标出左右速度的 3 处。

工业用高速扫描设备的世界

在工厂的生产线上,需要对传送带上高速流过的产品每秒扫描数十次二维码。这个领域要求的速度与手机相差一个量级,用的是专门的工业扫描设备。

工业用固定式扫描设备中,有的产品每秒能读取 60 次以上的二维码。为此,专用的图像处理芯片(FPGA 或 ASIC)在硬件层面并行完成定位图案的检测与解码 —— 与靠通用 CPU 做软件处理的手机相比,架构根本不同。

另外,激光扫描设备主要用于条形码(一维码),二维码的读取用的是摄像头(图像传感器)方式的读取设备。

理论上的速度极限

二维码读取速度的理论上限,不是由光速决定的,而是由图像处理的计算量决定的。以最小的版本 1(21×21 模块)为例,用优化过的算法处理时,单次解码所需的计算量估计约为 10 万次运算。考虑到一般 CPU 每秒可处理数十亿次运算,理论上每秒可以完成数万次解码。

但现实中还有摄像头的帧率、图像的传输速度、内存的访问速度等计算之外的瓶颈,所以永远达不到理论值。即便使用专用硬件,现实的上限一般也就在每秒数百次左右。

这个速度已经远远超出了人的知觉。人眼能分辨出单独一帧的速度是有限的,每秒数百次的扫描对人来说,与「一直在扫」是一回事。

速度与准确性的取舍

一味追求读取速度,就有牺牲准确性的风险。为缩短图像处理时间而降低分辨率,小模块的黑白判定会变得含糊,误读的概率随之上升;把纠错处理简化掉,对污损与破损的耐受力也会下降。

速度与准确性之间的这道取舍,最佳的平衡点取决于用途。在工厂的流水线上,有时会采用「冗余扫描」:对同一个二维码扫多次,靠多数一致来定结果。比起把单次扫描的准确性从 99% 提到 99.9%,扫三次、取其中两次以上一致的结果,在兼顾速度与准确性上有时更有利。

放到日常场景里,这层取舍其实也用得上。想让顾客扫得顺畅,与其纠结「读取要多快」,不如把码印得大一点、把纠错级别调得高一点、把周围的静区留够 —— 这些做法同时提高了成功率与实际感受到的速度。真正让人等的从来不是解码本身,而是反复对不上的那几秒。