一、概述
微信二维码检测器,用于检测和解析二维码。
微信二维码包括两个基于 CNN 的模型:物体检测模型和超分辨率模型。 对象检测模型用于检测带有边界框的二维码。 二维码较小时,应用超分辨率模型放大二维码。
二、类参考
1、函数原型
初始化微信二维码。 它包括两个模型,它们以 caffe 格式打包。 因此,有prototxt和caffe模型(总共四个参数)。
WeChatQRCode (const std::string &detector_prototxt_path="", const std::string &detector_caffe_model_path="", const std::string &super_resolution_prototxt_path="", const std::string &super_resolution_caffe_model_path="")
2、参数详解
detector_prototxt_path | prototxt file path for the detector |
detector_caffe_model_path | caffe model file path for the detector |
super_resolution_prototxt_path | prototxt file path for the super resolution model |
super_resolution_caffe_model_path | caffe file path for the super resolution model |
上述四个模型文件下载地址
GitHub - WeChatCV/opencv_3rdparty: OpenCV - 3rdpartyhttps://github.com/WeChatCV/opencv_3rdparty
3、函数原型
检测和解码 QR 码。
detectAndDecode (InputArray img, OutputArrayOfArrays points=noArray())
4、参数详解
img | 支持灰度或彩色(BGR)图像。 |
points | 找到的二维码四边形的顶点的可选输出数组。 如果找不到,则为空。 |
三、OpenCV源码
1、源码路径
opencv_contrib\modules\wechat_qrcode\src\wechat_qrcode.cpp
2、源码代码
WeChatQRCode::WeChatQRCode(const String& detector_prototxt_path,
const String& detector_caffe_model_path,
const String& super_resolution_prototxt_path,
const String& super_resolution_caffe_model_path) {
p = makePtr<WeChatQRCode::Impl>();
if (!detector_caffe_model_path.empty() && !detector_prototxt_path.empty()) {
// initialize detector model (caffe)
p->use_nn_detector_ = true;
CV_Assert(utils::fs::exists(detector_prototxt_path));
CV_Assert(utils::fs::exists(detector_caffe_model_path));
p->detector_ = make_shared<SSDDetector>();
auto ret = p->detector_->init(detector_prototxt_path, detector_caffe_model_path);
CV_Assert(ret == 0);
} else {
p->use_nn_detector_ = false;
p->detector_ = NULL;
}
// initialize super_resolution_model
// it could also support non model weights by cubic resizing
// so, we initialize it first.
p->super_resolution_model_ = make_shared<SuperScale>();
if (!super_resolution_prototxt_path.empty() && !super_resolution_caffe_model_path.empty()) {
p->use_nn_sr_ = true;
// initialize dnn model (caffe format)
CV_Assert(utils::fs::exists(super_resolution_prototxt_path));
CV_Assert(utils::fs::exists(super_resolution_caffe_model_path));
auto ret = p->super_resolution_model_->init(super_resolution_prototxt_path,
super_resolution_caffe_model_path);
CV_Assert(ret == 0);
} else {
p->use_nn_sr_ = false;
}
}
vector<string> WeChatQRCode::detectAndDecode(InputArray img, OutputArrayOfArrays points) {
CV_Assert(!img.empty());
CV_CheckDepthEQ(img.depth(), CV_8U, "");
if (img.cols() <= 20 || img.rows() <= 20) {
return vector<string>(); // image data is not enough for providing reliable results
}
Mat input_img;
int incn = img.channels();
CV_Check(incn, incn == 1 || incn == 3 || incn == 4, "");
if (incn == 3 || incn == 4) {
cvtColor(img, input_img, COLOR_BGR2GRAY);
} else {
input_img = img.getMat();
}
auto candidate_points = p->detect(input_img);
auto res_points = vector<Mat>();
auto ret = p->decode(input_img, candidate_points, res_points);
// opencv type convert
vector<Mat> tmp_points;
if (points.needed()) {
for (size_t i = 0; i < res_points.size(); i++) {
Mat tmp_point;
tmp_points.push_back(tmp_point);
res_points[i].convertTo(((OutputArray)tmp_points[i]), CV_32FC2);
}
points.createSameSize(tmp_points, CV_32FC2);
points.assign(tmp_points);
}
return ret;
};
四、效果图像示例
使用了和QRCodeDetector模块相同的图像对微信二维码进行了简单测试。
Bitmap bitmap = this.appWorkspace.ActiveDocumentWorkspace.CompositionSurface.CreateAliasedBitmap();
Mat src = OpenCvSharp.Extensions.BitmapConverter.ToMat(bitmap);
OpenCvSharp.WeChatQRCode weChatQRCode = WeChatQRCode.Create(
"wechat\\detect.prototxt",
"wechat\\detect.caffemodel",
"wechat\\sr.prototxt",
"wechat\\sr.caffemodel");
Mat[] mats;
string[] res;
weChatQRCode.DetectAndDecode(src, out mats, out res);
if(res!=null && res.Length > 0)
{
foreach (string s in res)
this.richTextBox1.Text += s;
}
示例图像如下