|
1 |
| -# opencv-js-qrcode |
2 |
| -# 纯JS识别照片或图片中的二维码 |
3 |
| -**场景**: 最近在做一个功能,通过识别发票照片获取发票数据用以匹配开票数据存档。 |
4 |
| -在搜索了各种库踩了一堆坑后,发现微信开源过他们的二维码扫码引擎c++版本,一阵折腾后编译出js版本,整理一下分享出来。本文介绍的方法主要的特点是: |
| 1 | +# OpencvQr |
| 2 | +## 纯JS识别照片或图片中的二维码 |
| 3 | +本库的主要特点是: |
5 | 4 | * 纯前端处理,无须调用后端OCR API等接口;
|
6 | 5 | * 可处理标准正方形的二维码,最重要的是可以处理照片上的二维码;二维码变形、旋转都可以识别;
|
7 | 6 | * 基于opencv 编译后的webassembly版本,编译添加了微信开源的wechat_qrcode,有极高的识别率。
|
8 | 7 |
|
9 | 8 |
|
10 |
| -在线测试(使用发票照片测试):https://leidenglai.github.io/opencv-js-qrcode/ |
| 9 | +在线测试:https://leidenglai.github.io/opencv-js-qrcode/ |
11 | 10 |
|
12 | 11 | **demo源码: [leidenglai/opencv-js-qrcode · GitHub](https://github.com/leidenglai/opencv-js-qrcode)**
|
13 | 12 |
|
14 | 13 | ## 加载二维码识别引擎
|
15 |
| -本文中采用的是自定义编译的opencv库,添加了三方组件wechat_qrcode微信二维码引擎,并且去掉不需要的库。 |
16 |
| -开始找了很多”强大的二维码识别库“,结果发现基本都不识别照片,或者失败率低,只能识别标准的qrcode。后来发现c++的opencv并且可编译为wsam版本。由于没有任何c++基础,在将wechat_qrcode编译进opencv时异常痛苦,好在后来找到一篇blog:编译微信二维码引擎到webAssembly实践 | 虚幻 ,感谢qwertyyb。 |
| 14 | +本库中采用的是自定义编译的opencv库作为继承,添加了三方组件wechat_qrcode微信二维码引擎,并且去掉不需要的库。封装一些基本方法方便使用。 |
17 | 15 |
|
18 |
| -在编译好OpenCV后,导出opencv.js,文件比较大进过优化大约有5 |
19 |
| -M,所以使用时需要异步加载。opencv加载后就能通过window.cv调用到opencv的相关方法;此时并不意味着我们能正常运行使用了,因为我们还需要加载二维码扫码引擎的模型文件: |
20 |
| -``` javascript |
21 |
| -async function loadModels() { |
22 |
| - const detect_proto = "detect.prototxt"; |
23 |
| - const detect_weight = "detect.caffemodel"; |
24 |
| - const sr_proto = "sr.prototxt"; |
25 |
| - const sr_weight = "sr.caffemodel"; |
26 |
| - |
27 |
| - if (qrcode_detector != undefined) { |
28 |
| - updateStatus("Model Existed"); |
29 |
| - } else { |
30 |
| - const dp = await utils.fetchModelsData(detect_proto); |
31 |
| - const dw = await utils.fetchModelsData(detect_weight); |
32 |
| - const sp = await utils.fetchModelsData(sr_proto); |
33 |
| - const sw = await utils.fetchModelsData(sr_weight); |
34 |
| - |
35 |
| - cv.FS_createDataFile("/", "detect.prototxt", dp, true, false, false); |
36 |
| - cv.FS_createDataFile("/", "detect.caffemodel", dw, true, false, false); |
37 |
| - cv.FS_createDataFile("/", "sr.prototxt", sp, true, false, false); |
38 |
| - cv.FS_createDataFile("/", "sr.caffemodel", sw, true, false, false); |
39 |
| - |
40 |
| - qrcode_detector = new cv.wechat_qrcode_WeChatQRCode( |
41 |
| - "detect.prototxt", |
42 |
| - "detect.caffemodel", |
43 |
| - "sr.prototxt", |
44 |
| - "sr.caffemodel" |
45 |
| - ); |
46 |
| - updateStatus("OpenCV Model Created"); |
47 |
| - } |
48 |
| -} |
| 16 | +### NPM |
| 17 | + |
| 18 | +``` sh |
| 19 | +npm install opencv-qr --save |
49 | 20 | ```
|
50 | 21 |
|
51 |
| -这些文件为wechat_qrcode引擎的 CNN models,Detector model 和 Super scale model。将模型文件加载成功后转换为 `Uint8Array` 加载到引擎中,然后调用`new cv.wechat_qrcode_WeChatQRCode( “detect.prototxt”, “detect.caffemodel”, “sr.prototxt”, “sr.caffemodel” )`实例化返回引擎实例。 |
52 |
| -官方model文件 [GitHub - WeChatCV/opencv_3rdparty: OpenCV - 3rdparty](https://github.com/WeChatCV/opencv_3rdparty/tree/wechat_qrcode) |
53 | 22 |
|
54 |
| -作为对比,demo中添加了git上star比较多的jsqr库一同对照测试。 |
| 23 | +``` javascript |
| 24 | +// ES6 import |
| 25 | +import OpencvQr from "opencv-qr"; |
55 | 26 |
|
56 |
| -## 识别二维码 |
57 |
| -因为demo特定需求,发票二维码基本在左上角,所以在canvas加载图片时只截取左上角图片,提高引擎识别效率。 |
58 |
| -<img width="562" alt="CleanShot 2022-05-23 at 17 24 28@2x" src="https://user-images.githubusercontent.com/11383747/169796294-993433c3-3e97-46a9-8651-8fd76152ca27.png"> |
| 27 | +// CommonJS require |
| 28 | +const OpencvQr = require("opencv-qr"); |
59 | 29 |
|
60 |
| -OpenCV识别结果: |
61 |
| - |
62 |
| -将二维码信息和二维码区域都正确的处理,OpenCV耗时: 224.42822265625 ms。 |
| 30 | +// 加载模型文件,模型文件请自行保存在静态目录 |
| 31 | +const cvQr = new OpencvQr({ |
| 32 | + dw: "http://xxx.com/models/detect.caffemodel", |
| 33 | + sw: "http://xxx.com/models/sr.caffemodel", |
| 34 | +}); |
63 | 35 |
|
64 |
| -而jsqr是处理不了这样的图片的。 |
| 36 | +``` |
65 | 37 |
|
| 38 | +### Browser |
66 | 39 |
|
67 |
| -**识别旋转的二维码** |
68 |
| - |
69 |
| -照片被旋转了90度且不太清晰,同样也被正确的处理,OpenCV耗时: 169.523193359375 ms。 |
| 40 | +也可直接在浏览器中使用 |
70 | 41 |
|
71 |
| -jsqr也不能处理这样的图片。 |
| 42 | +``` html |
| 43 | +<script src="dist/OpencvQr.js"></script> |
| 44 | +<script> |
| 45 | + const cvQr = new OpencvQr({ |
| 46 | + dw: "http://xxx.com/models/detect.caffemodel", |
| 47 | + sw: "http://xxx.com/models/sr.caffemodel", |
| 48 | + }); |
| 49 | +</script> |
72 | 50 |
|
| 51 | +``` |
73 | 52 |
|
74 | 53 |
|
75 |
| -**电子二维码识别:** |
76 |
| - |
77 |
| -电子版的发票图片都正确的识别了;OpenCV耗时: 165.333984375 ms,QRjs耗时: 44.613037109375 ms。不过QRjs的效率相对会高一些。 |
| 54 | +### 使用 |
78 | 55 |
|
| 56 | +OpencvQr暴露一个加载方法和三个使用方法, 支持typescript类型 OpencvQr.d.ts |
79 | 57 |
|
80 |
| -## 浏览器兼容性: |
81 |
| -暨WebAssembly兼容性,基本上现代浏览器都是支持的: |
82 |
| -<img width="789" alt="CleanShot 2022-05-23 at 17 16 35@2x" src="https://user-images.githubusercontent.com/11383747/169796444-07af908a-48a6-448f-b458-56175ad2576d.png"> |
83 |
| - |
84 |
| -## 总结 |
85 |
| -OpenCV因为需要加入wechat_qrcode组件,所以必须使用自定义编译。需要在本地搭建c++的编译环境,是前端基本不曾涉足的领域,相对较为繁琐,也会有一些困难,但这也让前端具备了更强大的本领,由于WebAssembly的存在,前端也有了更多的可能。 |
86 |
| - |
87 |
| -总之,由于前端越强大,我们能做的事也越多,挑战也会越大,大家共勉。 |
| 58 | +``` javascript |
| 59 | + // 初始化时需自行加载模型文件,模型文件请自行保存,需静态加载,不可编译转换 |
| 60 | + const cvQr = new OpencvQr({ |
| 61 | + dw: "http://xxx.com/models/detect.caffemodel", |
| 62 | + sw: "http://xxx.com/models/sr.caffemodel", |
| 63 | + }); |
| 64 | + |
| 65 | + // 加载canvas中的图像 |
| 66 | + const result = cvQr.load("canvasInput"); |
| 67 | + |
| 68 | + // 返回解析结果字符 |
| 69 | + const infos = result?.getInfos(); |
| 70 | + // 返回解析的二维码截取图像 ImageData |
| 71 | + const images = result?.getImages(); |
| 72 | + // 返回已识别的二维码图像相对于原图的位置信息 坐标和宽高 |
| 73 | + const sizes = result?.getSizes(); |
88 | 74 |
|
89 |
| -## 参考 |
90 |
| -[编译微信二维码引擎到webAssembly实践 | 虚幻](https://qwertyyb.github.io/2021/06/19/%E7%BC%96%E8%AF%91%E5%BE%AE%E4%BF%A1%E4%BA%8C%E7%BB%B4%E7%A0%81%E5%BC%95%E6%93%8E%E5%88%B0webAssembly%E5%AE%9E%E8%B7%B5/) |
91 |
| -OpenCV: https://github.com/opencv/opencv |
92 |
| -OpenCV’s contrib: https://github.com/opencv/opencv_contrib |
| 75 | +``` |
93 | 76 |
|
94 | 77 |
|
| 78 | +## 浏览器兼容性: |
| 79 | +暨WebAssembly兼容性,基本上现代浏览器都是支持的: |
| 80 | +<img width="789" alt="CleanShot 2022-05-23 at 17 16 35@2x" src="https://user-images.githubusercontent.com/11383747/169796444-07af908a-48a6-448f-b458-56175ad2576d.png"> |
95 | 81 |
|
0 commit comments