OpenCvSharp使用微信的二维码识别引擎进行二维码识别

前言

之前使用ZXing做二维码识别,但是一些稍微不清晰的二维码,它都识别不出来。

https://www.psvmc.cn/article/2022-08-08-qrcode-csharp.html

这里就寻找到的替代的方式:使用微信开源的二维码识别,效果好多了。

这里推荐

ZXing 做二维码生成。

识别还是使用WeChatQRCode。

微信开源了其二维码的解码功能,并贡献给 OpenCV 社区。

其开源的 wechat_qrcode 项目被收录到 OpenCV contrib 项目中。

从 OpenCV 4.5.2 版本开始,就可以直接使用。

微信的扫码引擎优势

  • 支持了远距离二维码检测
  • 自动调焦定位
  • 多码检测识别等功能
  • 它是基于 CNN 的二维码检测

微信二维码识别

安装OpenCvSharp4依赖

需要安装两个依赖:

  • OpenCvSharp4
  • OpenCvSharp4.runtime.win
  • OpenCvSharp4.Extensions

添加引用

1
2
3
using OpenCvSharp;
using Point = OpenCvSharp.Point;
using Rect = OpenCvSharp.Rect;

其中

OpenCvSharp4.Extensions 主要是一些辅助的工具 比如Mat和Bitmap的互转。

安装

1
2
3
Install-Package OpenCvSharp4 -Version 4.6.0.20220608
Install-Package OpenCvSharp4.runtime.win -Version 4.6.0.20220608
Install-Package OpenCvSharp4.Extensions -Version 4.6.0.20220608

注意:

不同版本的OpenCV的语法有些许差别。

下载模型

使用这个二维码识别需要下载模型文件

https://github.com/psvmc/opencv_3rdparty

我这里直接放在了项目的根目录下opencv_3rdparty-wechat_qrcode文件夹中。

里面的文件都设置为

image-20240325185609843

工具类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
namespace card_scanner.Utils.ZCommon
{
using System;
using System.Text;

using OpenCvSharp;

public class ZQrWeChatUtils
{
private const string DETECTOR_PROTOTXT_PATH = "opencv_3rdparty-wechat_qrcode/detect.prototxt";
private const string DETECTOR_CAFFE_MODEL_PATH = "opencv_3rdparty-wechat_qrcode/detect.caffemodel";
private const string PROTOTXT_PATH = "opencv_3rdparty-wechat_qrcode/sr.prototxt";
private const string CAFFE_MODEL_PATH = "opencv_3rdparty-wechat_qrcode/sr.caffemodel";

public static string ReadPic(Mat img)
{
using (WeChatQRCode wechatQrcode = WeChatQRCode.Create(
DETECTOR_PROTOTXT_PATH,
DETECTOR_CAFFE_MODEL_PATH,
PROTOTXT_PATH,
CAFFE_MODEL_PATH
))
{
wechatQrcode.DetectAndDecode(
img,
out Mat[] rects,
out string[] texts
);
StringBuilder sb = new StringBuilder();
string result = "";
for (int i = 0; i < rects.Length; i++)
{
float x1 = rects[i].At<float>(0, 0);
float y1 = rects[i].At<float>(0, 1);
float x2 = rects[i].At<float>(2, 0);
float y2 = rects[i].At<float>(2, 1);
result = texts[i];
sb.AppendLine("内容:[" + result + "] 位置:" + x1 + "," + y1 + "," + x2 + "," + y2);
Console.WriteLine(@"读取的二维码:" + sb);
}
return result;
}
}
}
}

调用

读取图片

1
Mat img8 = new Mat(imgpath);

识别

1
ZQrWeChatUtils.ReadPic(img8);

转换Mat为Bitmap

1
Bitmap bitmap = OpenCvSharp.Extensions.BitmapConverter.ToBitmap(img8);

获取其中二维码区域的图片

1
2
3
4
5
6
7
8
public Bitmap DrawRect(Bitmap bmp, float x1, float y1, float x2, float y2, string text)
{
g = Graphics.FromImage(bmp);
g.DrawRectangle(p, x1, y1, x2 - x1, y2 - y1);
g.DrawString(text, drawFont, drawBush, x1, y2);
g.Dispose();
return bmp;
}