二维码这东西现在几乎没人不认识了。扫码点餐、扫码乘车、扫码加好友、扫码看说明书连楼下卖煎饼的大爷摊子前都立着两个码。但有意思的是这个每天被扫几百亿次的黑白方块最初并不是为支付发明的也不是在中国诞生的。它出生在日本一家做汽车零部件的公司里原本只是车间里用来追踪零件的工具。结果几十年后它在中国的土壤上长成了完全不同的物种渗透进了商业、社交、政务、工业的每一个毛细血管。我做了几年跟二维码相关的项目从生成、识别到纠错容错都踩过不少坑今天就把这套东西从头到尾拆一遍它到底怎么编码的、为什么缺一块还能扫出来、用 Python 怎么从零实现一个能跑通的版本以及实际落地时那些文档里不会写的细节。1. 一个车间工具如何变成全民入口1.1 二维码的出身解决一维条码装不下太多信息的窘境上世纪九十年代日本一家做汽车零部件的企业里工程师们在盘点零件时遇到了一个很实际的问题传统一维条码能存的信息太少了一个条码顶多几十个字符而且只能横向读取扫歪一点就废了。零件种类一多条码数量爆炸贴都贴不过来。当时负责这个事的团队负责人带着人折腾了两年最后拿出了一套矩阵式的编码方案也就是后来的 QR CodeQR 是 Quick Response 的缩写意思是快速响应目标就是扫得快、存得多、还能扛点污损。这个设计目标非常关键它直接决定了二维码后面所有的技术选择。存得多所以用了两个方向的编码横向加纵向信息密度比一维码高出一个数量级扫得快所以设计了三个显眼的定位图案让扫描设备一眼就能找到码的位置和角度扛污损所以引入了里德-所罗门纠错码哪怕码面被遮挡、磨损、反光只要损坏比例在容错范围内照样能还原出原始数据。这三点是理解二维码一切行为的基石后面讲原理和实现时你会反复看到它们的身影。1.2 为什么在中国爆发移动互联网和支付场景的双重催化二维码在日本诞生后最初的应用场景一直比较窄主要是工业追踪和物流。真正让它变成全民基础设施的是中国移动互联网的那一波浪潮。智能手机普及了摄像头支付平台需要一个成本极低、印刷方便、又能承载交易信息的载体二维码几乎是完美答案——它不需要芯片、不需要供电、打印一张纸就能用成本趋近于零。我印象很深的是早些年做线下商户系统的时候一个摊位贴一张打印的二维码就能收款比装 POS 机便宜太多推广速度极快。后来社交加好友、公众号关注、小程序跳转、电子发票、健康码全都往二维码上叠。这背后其实是一个很朴素的工程逻辑二维码是连接物理世界和数字世界最便宜的那座桥。你印在纸上、贴在墙上、刻在设备上用户拿手机一扫物理对象就带上了数字身份。这个特性在支付和身份核验场景里价值巨大所以它在中国被用到了极致。1.3 二维码到底能装多少东西版本与容量的对应关系很多人以为二维码容量是固定的其实它有一套版本体系从版本 1 到版本 40版本号越大矩阵越大能装的数据越多。版本 1 是 21×21 的矩阵每升一个版本边长加 4 个模块到版本 40 就是 177×177。容量还跟纠错等级有关纠错等级越高能用来存数据的空间就越少因为要留更多位置给纠错码。下面这张表是我实际做容量规划时常用的参考数字字节模式下的容量单位是字节版本矩阵尺寸L 级纠错M 级纠错Q 级纠错H 级纠错121×211714117537×371068460441057×572742161541192097×9785866648238240177×1772953233116631273选版本的时候有个经验不要一上来就选大版本。版本越大模块越小同样的打印尺寸下每个模块的物理尺寸就越小对打印精度和摄像头分辨率的要求就越高。我见过有人为了多存几十个字节直接跳到版本 10结果贴在小标签上打印出来糊成一团扫半天扫不出来。正确做法是先算清楚数据量选能满足的最小版本再留一点余量给纠错等级别贪大。2. 拆开黑白方块编码流程的每一步在干什么2.1 从字符到比特流模式选择与数据编码二维码编码的第一步是把你要存的内容转成一串比特。但这里有个讲究二维码支持几种不同的编码模式数字模式、字母数字模式、字节模式、汉字模式等。不同模式的编码效率差别很大数字模式每三个数字压成 10 个比特字母数字模式每两个字符压成 11 个比特而字节模式就是一个字节 8 个比特直接放。选对模式能显著减少数据量从而用更小的版本。举个例子存一串纯数字的订单号用数字模式比字节模式能省将近一半空间。实际实现时编码器会先分析输入内容的字符构成自动选最省空间的模式。如果内容混合了数字和字母可能还会做分段编码不同段用不同模式。这一步在 Python 里如果用现成库基本是自动的但如果你要自己实现就得先写一个模式判断的逻辑全数字走数字模式全大写字母加数字走字母数字模式其他走字节模式。判断完之后在比特流最前面加上模式指示符4 个比特和字符计数指示符长度随版本变化这部分叫模式头是解码时识别数据格式的依据。2.2 纠错码的生成里德-所罗门算法为什么能救回损坏的数据数据比特流准备好之后接下来是最核心的一步生成纠错码。二维码用的是里德-所罗门纠错这套算法的本质是在有限域上做多项式运算把原始数据当成多项式的系数然后除以一个生成多项式得到的余数就是纠错码。听起来抽象但它的效果非常直观即使原始数据里有一部分比特被破坏只要破坏的数量在纠错能力范围内接收方就能通过纠错码把原始数据反推出来。这里有个关键概念叫纠错容量。二维码的四个纠错等级 L、M、Q、H 分别对应大约 7%、15%、25%、30% 的数据恢复能力。注意这个百分比指的是码字codeword的比例不是简单的面积比例。H 级能扛住接近三成的码字损坏所以你在码中间贴个 logo、或者码面被划了一道只要没超过这个比例照样能扫。我做过一个测试在 H 级二维码正中间盖住大约四分之一的面积手机依然能识别这就是纠错码的威力。但要注意纠错能力是有边界的而且损坏的位置分布也有影响集中损坏比分散损坏更容易超出局部纠错能力。2.3 矩阵排布定位图案、时序图案与数据填充的规则有了数据码和纠错码接下来要把这些比特铺到矩阵里。这一步不是随便填的矩阵里有几类固定图案必须先占好位置三个角上的定位图案就是那三个大方块用来让扫描器快速定位和判断方向定位图案旁边的一圈分隔符用来把定位图案和数据区隔开还有交替黑白的小方块组成的时序图案用来帮助扫描器确定模块的坐标网格。这些固定图案占完之后剩下的位置才用来填数据。填充的顺序也有讲究是从右下角开始两个模块一组呈之字形向上走遇到固定图案就绕开。这个填充顺序是标准规定的解码时按同样的顺序读回来。我一开始自己实现的时候就是在这个填充顺序上栽了跟头写成了从左到右逐行填结果生成的码怎么都扫不出来后来对着标准文档一行行核对才发现方向搞反了。这种细节看着琐碎但错一个比特整个码就废了所以实现时一定要严格对照规范。2.4 掩码评估为什么你的码有时候看起来“花”得不一样数据填完之后还有一步很多人不知道掩码。因为数据内容不同填出来的矩阵可能出现大片连续的黑色或白色或者出现跟定位图案相似的图形这会干扰扫描器的识别。所以标准定义了 8 种掩码图案每一种都是对数据区做一次异或运算把矩阵打散。编码器会依次用 8 种掩码生成 8 个候选矩阵然后按一套评分规则惩罚连续同色、惩罚 2×2 同色块、惩罚类似定位图案的结构等打分选分数最低的那个作为最终结果。这就是为什么同样内容、不同库生成的二维码看起来花纹可能不一样——它们选的掩码可能不同或者评分实现有细微差异。掩码信息会存在矩阵的特定位置格式信息区解码时读出来再异或回去就能还原。这一步在实际使用中一般不用操心但如果你在做二维码美化、想把码点做成圆形或者嵌入图片就必须理解掩码的作用否则美化之后可能破坏掩码结构导致扫不出来。3. 用 Python 从零跑通一个二维码生成器3.1 工具选型现成库和手写实现的取舍真要用 Python 生成二维码最省事的是qrcode这个库几行代码就能出图底层依赖Pillow做图像输出。它的优点是成熟稳定、参数齐全版本、纠错等级、边框、颜色都能调。如果你只是要在项目里加个生成二维码的功能直接用它就够了没必要重复造轮子。但如果你想真正理解二维码或者有定制化需求比如自定义码点形状、嵌入 logo、控制掩码那就得自己实现核心逻辑或者至少读一遍库的源码。我建议的路径是先用qrcode库跑通观察不同参数下的输出差异然后对照标准文档理解每一步最后尝试手写一个简化版比如只支持字节模式、固定版本 1 到 5。手写的过程会让你对纠错码、填充顺序、掩码这些概念有完全不同的理解这些理解在排查“为什么这个码扫不出来”的时候特别有用。3.2 最小可运行示例生成、保存与参数解读先看一个能直接跑的示例。安装依赖pip install qrcode[pil]生成一个带纠错等级和自定义颜色的二维码import qrcode from qrcode.constants import ERROR_CORRECT_H qr qrcode.QRCode( versionNone, # None 表示自动选择最小可用版本 error_correctionERROR_CORRECT_H, # 最高纠错等级适合嵌入 logo box_size10, # 每个模块对应的像素数 border4, # 边框宽度单位是模块数标准建议至少 4 ) qr.add_data(https://example.com/order/20240601) qr.make(fitTrue) img qr.make_image(fill_colorblack, back_colorwhite) img.save(order_qr.png)这段代码里几个参数值得说清楚。versionNone让库自动算最小版本这是推荐做法避免手动选大了浪费空间。error_correction选 H 级是因为后面可能要往中间贴 logoH 级容错最高贴图后仍能识别。box_size决定输出图片的清晰度打印场景建议不低于 10屏幕展示 4 到 6 就够。border是静区标准要求至少 4 个模块宽很多人为了好看把边框去掉结果扫描器找不到码的边界识别率直线下降这个坑我踩过不止一次。3.3 手写核心逻辑比特流、纠错码与矩阵填充的关键代码如果你想自己实现核心难点在纠错码生成和矩阵填充。下面给一段简化版的纠错码生成逻辑用的是reedsolo库避免自己手写有限域运算from reedsolo import RSCodec def build_codewords(data_bytes, ec_count): # ec_count 是该版本该纠错等级下需要的纠错码字数 rsc RSCodec(ec_count) encoded rsc.encode(data_bytes) return encoded # 前部分是数据码字后部分是纠错码字矩阵填充部分关键是按标准的之字形顺序走。下面是一个填充顺序的伪代码思路帮助理解def fill_matrix(matrix, bits, reserved): size len(matrix) idx 0 col size - 1 upward True while col 0: if col 6: # 第 6 列是垂直时序图案跳过 col - 1 rows range(size - 1, -1, -1) if upward else range(size) for row in rows: for c in (col, col - 1): if not reserved[row][c] and idx len(bits): matrix[row][c] bits[idx] idx 1 upward not upward col - 2这段代码只是示意实际实现还要处理版本信息区、格式信息区、掩码应用等。但它的价值在于让你看清填充的走向从右往左两列一组交替上下遇到时序图案列跳过。我当初就是靠手写这段逻辑才真正搞明白为什么二维码的数据区看起来是那种斜向的纹理。3.4 生成之后怎么验证解码回读与常见失败原因生成完二维码别急着交付一定要做解码回读验证。Python 里可以用pyzbar或者opencv的解码功能把生成的图读回来比对内容是否一致from pyzbar.pyzbar import decode from PIL import Image result decode(Image.open(order_qr.png)) print(result[0].data.decode(utf-8))回读失败最常见的原因有几个边框被裁掉了、模块尺寸太小导致相邻模块粘连、颜色对比度不够比如深灰配浅灰、图片被过度压缩产生噪点。我遇到过一次批量生成的码全部扫不出来排查半天发现是输出时用了有损压缩模块边缘糊了改成 PNG 无损输出后立刻正常。所以生成环节的最后一道验证不能省尤其是批量场景写个脚本自动回读比对能省掉大量返工。4. 落地时才暴露的问题容错、打印与场景适配4.1 纠错等级不是越高越好容量与鲁棒性的平衡新手容易有个误区觉得纠错等级越高越保险一律选 H。但 H 级会占用大量码字空间同样的数据量下版本要往上跳模块变小打印和识别的难度反而增加。正确的做法是按场景选内容短、码面干净、没有遮挡风险的L 或 M 级足够要嵌 logo、码面可能磨损、或者要在户外风吹日晒的才上 Q 或 H。我做过一个对比测试同样一段 50 字节的文本L 级用版本 3 就能装下H 级要跳到版本 5模块数从 29×29 涨到 37×37。如果打印尺寸固定为 2 厘米见方版本 5 的单个模块只有约 0.5 毫米普通喷墨打印就开始糊了。所以选等级的本质是在“能装多少”和“能扛多少”之间找平衡点不是无脑拉满。4.2 打印与材质模块尺寸、对比度与静区的硬性要求二维码落地到物理世界打印质量是决定成败的关键。有几个硬指标单个模块的物理尺寸建议不小于 0.4 毫米低于这个值普通手机摄像头就很难稳定识别前景和背景的对比度要足够黑白是最稳的深色底浅色码也可以但要保证反差静区边框绝对不能省至少留 4 个模块宽。材质方面纸张、塑料、金属激光雕刻都行但要注意反光。光面材质在强光下会产生高光把部分模块“洗白”导致识别失败。我做过一批贴在金属设备上的资产标签最初用了光面不干胶车间灯光一照就扫不出来后来换成哑光材质才解决。另外曲面粘贴要注意码被贴弯了之后模块会变形扫描器虽然有一定形变容忍能力但弯曲过度照样失效这种情况要么减小码的尺寸要么改用直接雕刻。4.3 屏幕展示与远距离扫描动态码和尺寸的取舍屏幕展示二维码和印刷品是两套逻辑。屏幕有刷新率、有亮度、有反光还有缩放问题。做动态码比如支付码定时刷新时要保证刷新过程中码的完整性不能出现半张码的情况。尺寸上屏幕码要考虑用户站多远扫一般经验是码的对角线长度至少是扫描距离的十分之一超过这个距离识别率就明显下降。还有个细节是屏幕亮度。有些设备在强光下屏幕亮度不够码的对比度被环境光冲淡扫不出来。实际项目里我们会在码周围加一圈深色底衬提升局部对比度效果比单纯调高亮度更稳。另外动态码刷新频率别太高一秒刷好几次既没必要也增加识别失败的概率一般十几秒到一分钟刷新一次足够安全。5. 那些文档里不会写的排查经验5.1 扫不出来时的排查链路从码面到解码器逐层排除遇到二维码扫不出来别急着重新生成按链路逐层排查效率最高。我的习惯是从物理层往上走先看码面本身有没有物理损伤、污渍、反光再看打印质量模块边缘是否清晰、有没有粘连然后看静区是否完整接着确认对比度是否足够最后才怀疑内容或编码问题。有一次线上反馈某批码识别率低我按这个链路查物理层没问题打印也清晰最后发现是生成时border设成了 1静区不够部分扫描器找不到边界。改成 4 之后识别率从七成多回到接近百分之百。这个链路的价值在于它把“玄学问题”变成了可逐项验证的清单大部分问题在前三层就能定位。5.2 内容编码的坑中文、特殊字符与长度超限内容编码这块坑不少。中文在字节模式下按 UTF-8 编码一个汉字占 3 个字节如果内容里中文多很容易超出预期版本。更麻烦的是不同解码器对字符集的解释可能不一致有的按 UTF-8 解有的按本地编码解导致扫出来是乱码。稳妥做法是内容里尽量用 ASCII必须用中文时确保生成端和扫描端约定好 UTF-8。长度超限也是常见问题。有人把一整段 JSON 塞进二维码结果自动跳到很大的版本打印出来密密麻麻扫不动。这种情况要么精简内容只放一个短链接或 ID实际数据放服务端要么拆分。我现在的习惯是二维码里只放标识符绝不直接塞大段数据既减小码的复杂度也方便后续内容更新而不用重印码。5.3 安全边界二维码本身不带安全属性别把它当信任凭证最后说个容易被忽视的点。二维码只是一个编码容器它不验证内容真伪也不保证来源可信。扫到一个码你只知道它编码了某段数据不知道是谁生成的、有没有被篡改。所以涉及支付、登录、授权的场景安全逻辑必须放在服务端二维码里只放一次性的、有时效的令牌并且做签名校验。我见过一些实现把用户 ID 直接编进二维码当凭证用这等于把身份信息明文贴在墙上谁扫到都能用。正确做法是码里放随机令牌服务端维护令牌到身份的映射设置过期时间用一次就失效。这个原则说起来简单但实际项目里因为图省事而踩线的不少值得反复提醒。整套东西捋下来二维码的技术内核其实不复杂难的是那些边界条件和场景细节。我个人的体会是把它当成一个“有容错能力的物理到数字的桥”来理解很多设计选择就顺理成章了。真正做项目时生成只是第一步打印、验证、排查、安全这几环才是决定能不能用的关键。
企业数字化 ERP 产品动态
相关推荐
概率论核心公式实战指南:从加法乘法到贝叶斯,解决数据分析与机器学习问题 概率论这门课,很多人学完就忘,考试一过公式全还给老师。但真正做过数据分析、风控建模、AB实验或者机器学习的人都知道,概率论的基本公式不是用来背的,是用来“翻译现实问题”的。你手上任何一个不确定性问题,从推荐系… · 2026/11/13 4:26:28
影响力六大武器解析与实践应用指南 1. 为什么我们需要理解"影响力"2003年,斯坦福大学心理学教授罗伯特西奥迪尼出版了《影响力》这本改变无数人认知的经典著作。作为一本畅销全球三十余年的心理学读物,它揭示了人类行为背后那些鲜为人知却又普遍存在的心理机制。我最初接触这本书… · 2026/11/8 3:33:41
技能不是知识:用技能地图系统化提升个人核心竞争力 一个词,能挖出多少东西?我有段时间特别喜欢这个项目标题——skills。它不是一个具体的应用,也不是某个产品功能,但几乎所有人都在谈。招聘要求里写着一堆技能,个人简介里罗列着各种技能,培训课程也打包成技… · 2026/11/5 23:36:13
安徽电工证什么样的证多少钱 报名别乱选坑了 安徽电工证什么样的证多少钱 报名别乱选坑了 你是不是也遇到过这种情况?手里拿着一堆电工证,但不知道哪个是真的,哪个是假的,更别提去哪报名、多少钱了。其实,安徽电工证什么样的证,直接影响你能不能在工地、工厂或者相关企业上岗。今天就从开封中小施… · 2026/11/14 2:20:29
电监会电工证郑州培训官方回应:怕考不过白交培训费?看这里 电监会电工证郑州培训官方回应:怕考不过白交培训费?看这里 怕考不过白交培训费?这年头,考个证就像闯关,有人一次过,有人连关都闯不进。郑州金水区的不少市政工程从业者,尤其是想从事低压电工、高压电工相关工作的朋友,都对【电监会电工证郑州培训】这… · 2026/11/14 2:20:29
去天津考电工证保姆级教程:实操考试心里没底怕挂科?看完这篇稳过! 去天津考电工证保姆级教程:实操考试心里没底怕挂科?看完这篇稳过! 实操考试心里没底怕挂科?你不是一个人。去天津考电工证的小伙伴们,很多都担心自己操作不规范、考试流程不熟悉,结果一上考场就紧张。别慌!这篇保姆级教程,帮你从报名到考试全流程搞懂… · 2026/11/14 2:20:29
鞍山电工证自己考在哪考 实操考试心里没底怕挂科 鞍山电工证自己考在哪考 实操考试心里没底怕挂科 你是不是也担心自己考鞍山电工证自己考的时候实操考试心里没底怕挂科?别慌,很多电工都经历过这种焦虑,尤其是第一次报考的新人,对考试内容和流程都不太清楚。其实,只要掌握好方法和重点,… · 2026/11/14 2:20:29
电工证周末考试吗内部消息:怕考不过白交培训费的你必须知道的真相 电工证周末考试吗内部消息:怕考不过白交培训费的你必须知道的真相 怕考不过白交培训费?现在很多人想考电工证,但又担心培训费打了水漂,尤其是在南阳卧龙区这种对特种作业证书要求严格的区域。别急, 内部消息 告诉我们,电工证考试其实 不固定在周末… · 2026/11/14 2:20:29
揭阳市电工证怎么考?全国通用证书解决工地复习难题 揭阳市电工证怎么考?全国通用证书解决工地复习难题 工地太忙根本没时间复习考试,你不是一个人。揭阳市电工证作为全国通用的特种作业操作证,是建筑、制造、电力等行业的“通行证”,但很多人在报考、考试、复审过程中踩坑,尤其是对跨省转介、电子证书下载… · 2026/11/14 2:19:29
电工证丢失还能补吗?千万别踩坑,丢了证等于失业 电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/13 22:30:50
电力电缆作业证直播报名入口与办理流程良心建议 电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/13 5:40:45
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/12 23:27:43
有初级电工证怎么工作 2026河南最新政策怎么应对 有初级电工证怎么工作 2026河南最新政策怎么应对 之前考的证在外省能不能转过来?这个问题我每天被问上百次。2026年河南最新政策对证书跨省转移有了明确说明,特别是南阳市的从业者,需要特别关注。… · 2026/11/14 0:00:31
电工证过期了不知道怎么复审?考电工证自学书+官方报名入口全攻略 电工证过期了不知道怎么复审?考电工证自学书+官方报名入口全攻略 证书过期了不知道怎么复审延期?很多人遇到这种情况,要么是工作太忙没时间处理,要么是不知道具体流程,导致证书失效,影响工作和项目进展。其实复审并不难,关键是要找准官方报名入口,掌… · 2026/11/14 0:00:31
为什么要低压电工证实操考试考什么 为什么低压电工证值不值得考?别再被中介骗了 你是不是也经常看到网上有人在问“低压电工证到底值不值得考”?或者在找报名点时,担心被中间人骗钱?这些问题,我懂,我也经历过。作为一名在应急管理行业摸爬滚打多年的从业者,我深知低压电工证不仅是一个从… · 2026/11/14 0:00:31
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 6:12:21
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 6:11:51
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/13 22:31:30