二维码被撕掉一角,为什么还能扫出来

科普编码冷知识

奶茶店门口的二维码贴纸被磨掉一个角,照样能扫。海报中间压着一个圆形 logo,也照样能扫。第一次注意到这件事的时候,我以为是手机的识别算法足够聪明,把缺的部分”猜”了出来。

不是猜的。那些缺掉的信息,本来就在图里的别处存了一份。

三个方块负责的不是数据

一张二维码里,哪些格子不是数据

先看最显眼的部分:三个角上的”回”字形方块。它们不存任何数据,只干一件事——告诉扫码器”这里有个二维码,而且它是这么歪的”。

这三个方块叫定位图案(finder pattern),设计上有个很讲究的地方:沿任何一条直线穿过它,黑白像素的长度比恒定是 1:1:3:1:1。横着扫是这个比例,竖着扫是这个比例,斜着 45 度扫还是这个比例。所以扫码器不需要你把手机摆正——它只要在画面里找到三处满足这个比例的地方,三点定一个平面,整张码的方向、倾斜、透视变形就全解出来了。

1:1:3:1:1,一个统计出来的比例

为什么偏偏是 1:1:3:1:1?这是 1994 年二维码的发明者原昌宏在 DENSO WAVE(丰田系的零部件厂商)做的一件笨功夫:他和同事把手边能找到的印刷品——报纸、传单、包装盒、票据——统统拿来统计,找出黑白交替长度比中出现频率最低的那一种。结论就是 1:1:3:1:1。选最罕见的图案,是为了让扫码器几乎不可能在背景里认错。

顺带说一句这套东西的来历:原昌宏是在午休下围棋时想到的,黑子白子摆在纵横的格子上,本身就是一种二维排列的信息。当时的目标很具体——汽车零件的条形码一次只能存二十来个字符,产线上一个箱子要贴好几条码,工人得挨个扫。他要的是”扫一次就够,而且要快十倍”。QR 就是 Quick Response。

30% 被毁掉还能读,靠的是里德-所罗门码

纠错等级不是越高越好

真正回答标题那个问题的,是纠错。

二维码有四个纠错等级:L 约 7%、M 约 15%、Q 约 25%、H 约 30%。这个百分比的意思是,整张码里最多有这么多比例的码字损坏、被遮挡或者干脆消失,原始数据仍然能被完整还原出来。不是模糊恢复,是精确还原成原来那串字节。

背后的算法叫里德-所罗门纠错码(Reed–Solomon),同一套数学也用在 CD、DVD 和深空探测器的通信里。它的思路不是简单地把数据抄两份,而是把数据当成一个多项式的系数,然后额外记录这个多项式在若干个点上的取值。解码时只要拿到的点数够,就能反解出唯一的那条多项式——哪几个点丢了不重要。

代价是面积。H 级的抗损能力最强,但同样的数据要用更多的模块来装,整张码的格子会变密。格子一密,在同样的打印尺寸和拍摄距离下,每个格子占的像素就变少,反而更容易糊掉。所以纠错等级并不是越高越好,它是一个”抗遮挡”和”抗模糊”之间的取舍。

这也解释了中间盖 logo 的做法:它不是什么黑科技,就是主动花掉纠错预算。遮住的面积如果控制在纠错能力以内,扫码器会把那块当成损坏区域修复回来。但有两条线不能碰——logo 不能压到三个定位图案,也不能压到定位图案旁边那圈记录版本与纠错等级的格式信息。那部分坏了,扫码器连”这张码该怎么读”都不知道,纠错还没开始就已经结束了。

为什么两张内容相同的码长得不一样

同一个网址为什么能画出八张不同的码

再说一个容易被忽略的机制:掩码(mask)。

假如某段数据编码出来恰好是一大片连续的白,或者出现了一块很像定位图案的东西,扫码器就容易失去参照、认错方向。为了避开这种情况,二维码规范定义了 8 种掩码图案——本质是 8 个固定的棋盘/条纹式公式,用来跟数据区做异或。

生成器的做法是:8 种全试一遍,每一种按规范给出的几条规则打”罚分”(连续五个以上同色要扣分,2×2 的同色块要扣分,出现酷似 1:1:3:1:1 的假定位图案要重罚,黑白比例失衡也要扣分),最后挑罚分最低的那一版输出。用了哪一种,会写在格式信息里告诉扫码器。

所以你用不同的工具生成同一个网址的二维码,图案可能完全不同——它们只是选了不同的掩码。而”这张码看起来黑白很均匀”不是审美,是罚分机制的结果。

生成二维码时真正有用的几条

把上面的原理翻译成可操作的:

  • 内容越短,格子越大,越好扫。 二维码从版本 1(21×21 模块)到版本 40(177×177 模块)。同样印成 3 厘米见方,版本 5 的每个格子有版本 30 的六倍宽。长网址请先短链。
  • URL 全大写能显著变小。 二维码有个”字母数字模式”,只支持 0-9、A-Z 和九个符号,每字符只花 5.5 比特;一旦出现小写字母就要退回字节模式,每字符 8 比特。HTTPS://EXAMPLE.COM/ABC 比同样长度的小写版本省掉近三分之一的容量。域名和 scheme 本来就大小写不敏感,这一条是白捡的。
  • 默认用 M,别无脑选 H。 屏幕上展示、纸面干净的场景,M(15%)足够;只有印在会被磨损、弯折、沾油的地方,或者确实要盖 logo,才值得上 Q 和 H。
  • 留白不是设计余量,是规范要求。 码的四周要留至少 4 个模块宽的静区(quiet zone)。紧贴着边框排版,是扫不出来最常见的原因之一。
  • 别把二维码当信任凭证。 人眼无法预读一个二维码指向哪里,这就是”quishing”(二维码钓鱼)成立的全部基础——在公共场所的原码上贴一张自己的贴纸,成本几乎为零。扫开之后先看域名再操作,这是唯一有效的防线。

它本来可以不是免费的

最后一件值得记的事:DENSO WAVE 拥有二维码的核心专利(日本专利第 2938338 号),但公开声明不对符合标准的用法行使权利,并把规格公开。2000 年 6 月,二维码成为 ISO/IEC 18004 国际标准。

今天满大街的收款码、健康码、菜单码、门票码,都建立在这个”不收钱”的决定上。一项 1994 年为了让产线工人少扫几次而设计的技术,因为放弃了收费,最终变成了公共基础设施。


参考:DENSO WAVE 官方技术说明、QR Code 标准化说明、Thonky 的二维码掩码教程、原昌宏的开发回忆。