二维码读取速度的极限 - 一秒能扫多少次
智能手机的扫描速度 - 感觉与实测的差距
用手机扫二维码时,结果几乎是瞬间显示出来的。但在这个「几乎瞬间」的内侧,好几道处理正高速地接连发生:摄像头取得一帧画面,从图像中检测定位图案,做几何校正,对模块逐个取样,再施加纠错把数据解出来。这一整串处理在一般的手机上耗时约 30 至 100 毫秒。
人感到「瞬间」的界线一般认为在 100 毫秒左右,而普通手机处理二维码的速度正好压在这条线以下。也就是说,当我们觉得「一下就读出来了」的时候,手机内部实际已经跑完了数千万次运算。
反过来,有时会觉得「怎么半天读不出来」,那多半不是解码慢,而是前面的步骤反复失败:对焦没合上、光线不足让黑白的分界糊掉、或者手抖导致画面拖影,定位图案一直找不到。这种情况下手机其实在每秒重试几十次,只是每一次都没能走到解码那一步。
瓶颈在哪里
限制二维码读取速度的因素,大致可以归为三项。
1. 摄像头的帧率:手机摄像头通常以 30 fps(每秒 30 帧)取得画面,也就是说二维码的图像最快也只能每约 33 毫秒取得一次。60 fps 的摄像头能把这个间隔缩到约 16 毫秒,但帧率再高,图像处理跟不上也就没有意义。
2. 定位图案的检测:要在画面里找出三个定位图案,必须扫过整幅图像,计算量因此很大,分辨率越高扫得越久。效率高的算法一般采用两段式:先把图像缩小后粗扫,找到候选位置再用原分辨率精确检测。
3. 纠错的解码:里德-所罗门码的解码包含有限域上的多项式运算,数据量越大计算时间越长。纠错级别为 H 的大容量二维码,单是解码就可能耗掉数毫秒。
值得注意的是,这三项之中拖慢速度最明显的往往不是解码,而是第二项的检测。解码的耗时大体由数据量决定,比较好预估;检测则取决于画面里有什么,背景越杂乱,需要排除的候选就越多。这也是为什么把二维码放在干净的底色上、四周留足静区,实际扫起来会明显更快。
工业用高速扫描设备的世界
在工厂的生产线上,需要对传送带上高速流过的产品每秒扫描数十次二维码。这个领域要求的速度与手机相差一个量级,用的是专门的工业扫描设备。
工业用固定式扫描设备中,有的产品每秒能读取 60 次以上的二维码。为此,专用的图像处理芯片(FPGA 或 ASIC)在硬件层面并行完成定位图案的检测与解码 —— 与靠通用 CPU 做软件处理的手机相比,架构根本不同。
要求更快时,则会用到激光扫描设备。激光不取整幅图像,而是逐行扫过二维码的模块,图像处理的额外开销因此大幅减少。代价是激光扫描设备对与二维码之间的距离和角度有要求,不像手机摄像头那样随便怎么举都行。
理论上的速度极限
二维码读取速度的理论上限,不是由光速决定的,而是由图像处理的计算量决定的。以最小的版本 1(21×21 模块)为例,用优化过的算法处理时,单次解码所需的计算量约为 10 万次运算。考虑到一般 CPU 每秒可处理数十亿次运算,理论上每秒可以完成数万次解码。
但现实中还有摄像头的帧率、图像的传输速度、内存的访问速度等计算之外的瓶颈,所以永远达不到理论值。即便使用专用硬件,现实的上限一般也就在每秒数百次左右。
这个速度已经远远超出了人的知觉。人眼能分辨出单独一帧的界线一般认为在 60 fps 附近,每秒数百次的扫描对人来说,与「一直在扫」是一回事。
速度与准确性的取舍
一味追求读取速度,就有牺牲准确性的风险。为缩短图像处理时间而降低分辨率,小模块的黑白判定会变得含糊,误读的概率随之上升;把纠错处理简化掉,对污损与破损的耐受力也会下降。
速度与准确性之间的这道取舍,最佳的平衡点取决于用途。在工厂的流水线上,有时会采用「冗余扫描」:对同一个二维码扫多次,靠多数一致来定结果。比起把单次扫描的准确性从 99% 提到 99.9%,扫三次、取其中两次以上一致的结果,在兼顾速度与准确性上有时更有利。
放到日常场景里,这层取舍其实也用得上。想让顾客扫得顺畅,与其纠结「读取要多快」,不如把码印得大一点、把纠错级别调得高一点、把周围的静区留够 —— 这些做法同时提高了成功率与实际感受到的速度。真正让人等的从来不是那几毫秒的解码,而是反复对不上的那几秒。