二维码破了一块为什么还能扫?——错误纠正的秘密

TL;DR

二维码不是把文字简单涂成黑白格,而是加入了可计算的冗余。本文从定位图形、数据码字和掩模讲起,解释 Reed–Solomon 错误纠正、四档容错率、交错排列与 Logo 留白的边界。

二维码不是把文字简单涂成黑白格,而是加入了可计算的冗余。本文从定位图形、数据码字和掩模讲起,解释 Reed–Solomon 错误纠正、四档容错率、交错排列与 Logo 留白的边界。

二维码破了一块为什么还能扫?——错误纠正的秘密

二维码中间贴上一个 Logo、边角被挡住、打印机把几个小方块印糊了,为什么手机仍然可能识别?答案不是扫码器“猜得很聪明”,而是二维码在编码时主动加入了冗余数据。ISO/IEC 18004 对 QR Code 的格式、编码、尺寸、错误纠正规则和参考解码算法都有定义。ISO/IEC 18004:2024

二维码的黑白小方块叫 module。它们不只是装数据,还承担定位、校准、格式描述、掩码和错误纠正等任务。扫码器先要确定“这张图的坐标系在哪里”,然后才能把小方块还原成数据。

扫码器第一眼看到的不是文字

一个 QR Code 大致包含几类区域:

  • 定位图形:三个角上的大方块,帮助识别方向和尺寸。
  • 校准图形:在较大版本中帮助纠正透视和几何变形。
  • 时序图形:辅助确定模块之间的网格间距。
  • 格式信息:描述错误纠正等级和掩码模式。
  • 数据与纠错码字:真正承载内容和恢复信息的区域。

因此,二维码被遮挡时并不是所有区域都同等重要。遮住定位图形,扫码器可能连网格都找不到;遮住一部分数据区域,则可能仍然有机会通过纠错恢复。

错误纠正到底加了什么

二维码通常把内容编码成 codeword,再通过 Reed–Solomon 码计算出额外的纠错 codeword。它们不是原文的简单复制,而是根据有限域上的计算产生的校验信息。

可以把它类比成一组考试答案和校验关系:如果其中少量答案被擦掉或改坏,剩余答案与校验关系仍然可能推回原来的值。解码器先把图像转成 0 和 1,再根据数据 codeword 与纠错 codeword 的关系定位错误并修复。

二维码有四个常见错误纠正等级,等级越高,能够承受的损坏比例通常越大,但能放入的原始数据越少。这个比例是整体设计能力的近似,不是“任意位置损坏这么多百分比都一定能读”。损坏是否集中、是否破坏定位图形、打印对比度和透视角度都会影响结果。

为什么要交错排列

如果纠错码只对应一整段连续数据,那么二维码被划掉一条长条时,可能恰好损坏同一段数据,恢复压力很大。实际编码会把数据和纠错信息分成块并进行交错,让空间上的一片损坏尽量分散到多个逻辑块中。

这解释了一个常见现象:同样面积的遮挡,分散的小污点可能比一条贯穿码图的黑色划痕更容易恢复。错误纠正不仅取决于“坏了多少”,还取决于“坏在哪里、以什么形状坏”。

掩码不是加密

二维码在放置数据后,会尝试若干 mask pattern,把部分模块按规则翻转,让最终图案避免大面积同色、长直线或类似定位图形的结构。扫码器通过格式信息知道使用了哪种掩码,再把它反向还原。

掩码的目的主要是提高可扫描性和降低误判,不是为了隐藏内容。任何拿到二维码图像的人,仍然可以按标准解码。把二维码当成“视觉加密”会产生错误的安全感。

为什么加 Logo 不能随便加

Logo 通常覆盖的是数据区域,并依赖较高错误纠正等级留下的冗余。但实际能否扫描还受到 Logo 面积、边缘是否清晰、背景对比度、打印质量和扫码器算法影响。高等级并不等于可以无限遮挡,更不能保证遮住定位图形后仍然工作。

如果二维码承载的是支付、登录或门禁信息,二维码的纠错能力只负责“恢复数据”,不负责验证数据是否可信。业务仍然需要签名、过期时间、服务端校验和重放防护。

一句话带走

二维码之所以耐损,是因为它把一部分容量换成了冗余校验。扫码器并不是看着残缺图案猜答案,而是在定位、解掩码、读码字和数学纠错之后,尽力恢复一份仍然满足校验关系的数据。

延伸阅读

KEEP READING