二维码识别与解码
上传图片或用摄像头扫出二维码内容,并在图上框出二维码的四个定位角。网址、Wi-Fi 串、vCard 名片会被拆成结构化字段。
可以点「选择图片」、把图片拖到这个面板里,或者直接按 Ctrl + V 粘贴剪贴板里的截图。大图会先缩到最长边 1600 像素再识别。
下面是识别用的画布,绿框是当前选中的码,橙框是同时认出的其他码。
图片预览
还没有选图片。选好之后这里会显示画布,识别到的二维码会用方框圈出来。
使用说明
二维码把数据编成一格一格的黑白模块,识别时先找三个角上的定位图案,再由它们定出网格,把每个模块读成 0 或 1,最后按 Reed-Solomon 纠错码把错误拉回来。版本从 1 到 40,版本越高模块越多、能装的内容越多,同一个内容在版本高时反而更密。纠错等级 L、M、Q、H 分别能容错约 7%、15%、25%、30% 的损坏,代价是多出来的冗余数据也要占模块,所以同样的内容在 H 档会排得更密、更难认。
扫不出来通常不是算法问题,而是采样太糊。识别前会把过大的图等比缩到最长边 1600 像素以内,缩得太狠反而会丢模块细节,所以缩放只在最长边超过这个值时发生,绝不放大。真正伤识别率的是:码在画面里占比太小、对着屏幕拍出现摩尔纹、纸张反光盖掉一片模块、拍摄角度过斜导致模块被透视压缩,以及截图时被自动压缩的模糊。把码单独裁出来只留码本身,或者让码在画面里多占些面积,效果最明显。
摄像头那条路要先申请权限,拿到的是 MediaStream,视频帧每 400 毫秒画到画布上一次并缩到最长边 960 像素再识别。分辨率不设更高是因为每一帧都要完整跑一遍识别,画面越大越慢,帧率掉下来反而来不及对焦。摄像头那一帧不做分块扫描:分块一轮要扫十几个区域,逐帧跑根本追不上,所以实时模式只做整图一次识别。点停止或者离开页面会逐个轨道调用 stop,摄像头指示灯才会真的熄灭。
Wi-Fi 串的格式是 WIFI:S:网络名;T:WPA;P:密码;H:true;;,S 是 SSID、T 是加密方式、P 是密码、H 表示是不是隐藏网络,字段里的分号要用反斜杠转义。vCard 是联系人名片格式,FN 是全名、N 是「姓;名」的结构化姓名、ORG 是公司与部门、TEL 与 EMAIL 后面可以带 TYPE 标注手机还是办公室,折行的续行以一个空格开头,遇到 QUOTED-PRINTABLE 编码还要先解码。这两类都要按字段拆开看才好用,直接读一串原文很容易看漏。
一张图里有多个码时,识别库一次只返回其中一个,甚至因为几个定位图案互相干扰而一个都认不出。这一页的做法是先整体扫一遍,失败后再按竖切、横切和网格分块找,把结果按位置去重合并,最多认 8 个。框是用识别库给出的四个角点连成的四边形,所以码倾斜时框也是斜的。另外提醒一句:这里只负责读出内容,不判断内容是否安全,二维码指向的网址可能是钓鱼站,不明来源的码建议先看清域名再打开。要生成二维码用二维码生成,要一维条码用条码生成,只想拿到图片的编码数据用图片转 Base64。
常见问题
为什么这张二维码扫不出来?
最常见的原因是码在图里太小、拍摄反光或者角度太斜。识别前会把大图缩到最长边 1600 像素以内,码在画面里占比越小,黑白模块糊得越厉害,越容易失败。把二维码单独裁出来只留码本身再传进来,成功率会明显提高。
一次能识别图里的多个二维码吗?
能,靠两轮扫描做到。第一轮整图扫,绝大多数图只有一个码,一次就命中;整图扫不出来时再按竖切、横切和网格分块找,把不同位置的码逐个认出来,一次最多认 8 个。分块扫描比整图慢得多,所以只在第一轮失败时才会跑。
识别到的 Wi-Fi 密码能直接用吗?
能。密码是从 WIFI 串的 P 字段里原样取出来的,复制后手输到手机或电脑上即可。要注意二维码里的密码是明文的,任何拿到这张图的人都能读出来,所以公共场合张贴的 Wi-Fi 码不该顺带写上办公网络或带额外权限的口令。
框出来的位置和码的位置对不上怎么办?
框按的是识别那张画布的像素坐标。大图会先等比缩小到最长边 1600 像素再识别,框画在同一张缩放后的画布上,所以和显示出来的图是对齐的。码倾斜得厉害时,四个角点连成的本来就是一个斜着的四边形,会贴着码的边框走。
摄像头扫码为什么要限制分辨率?
因为每一帧都要完整跑一遍识别,画面越大越慢。这里把抓到的帧缩到最长边 960 像素再算,每 400 毫秒扫一次,既跟得上手抖,也不会把 CPU 占满。想扫更远的码,让码在取景框里多占些面积,比一味提高分辨率有效得多。
图片和摄像头画面会上传吗?
不会。图片在本机解码成像素后直接交给识别库,整个过程不发网络请求,断网也能用。摄像头画面同样只在本地逐帧分析,不录制也不外传,点「停止」或者离开页面就会调用 track.stop 释放摄像头,指示灯随之熄灭。
纠错级别越高越难扫吗?
不一定,但级别高确实会把同样内容排在更多模块里。纠错等级高代表冗余数据多,码更密、模块更小,在同样尺寸下反而更难认;好处是被遮挡、磨损、折痕时更容易被修复。印刷品常用中档,屏幕显示用低档就够,有遮挡风险才上高档。