Skip to content

Commit

Permalink
Merge pull request #3289 from AleksandrPanov:wechat_fix_output_qr_cor…
Browse files Browse the repository at this point in the history
…ners

fix output qr corners
  • Loading branch information
asmorkalov committed Sep 5, 2022
2 parents ebd6445 + cee17e4 commit 47bf66f
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 5 deletions.
10 changes: 9 additions & 1 deletion modules/wechat_qrcode/src/decodermgr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ using zxing::Result;
using zxing::UnicomBlock;
namespace cv {
namespace wechat_qrcode {
int DecoderMgr::decodeImage(cv::Mat src, bool use_nn_detector, string& result) {
int DecoderMgr::decodeImage(cv::Mat src, bool use_nn_detector, string& result, vector<Point2f>& points) {
int width = src.cols;
int height = src.rows;
if (width <= 20 || height <= 20)
Expand Down Expand Up @@ -46,6 +46,14 @@ int DecoderMgr::decodeImage(cv::Mat src, bool use_nn_detector, string& result) {
int ret = TryDecode(source, zx_result);
if (!ret) {
result = zx_result->getText()->getText();
auto result_points = zx_result->getResultPoints();
for(int i = 0; i < result_points->size() / 4; i++) {
const int ind = i * 4;
for (int j = 1; j < 4; j++)
points.emplace_back(result_points[ind+j]->getX(), result_points[ind+j]->getY());

points.emplace_back(result_points[ind]->getX(), result_points[ind]->getY());
}
return ret;
}
// try different binarizers
Expand Down
2 changes: 1 addition & 1 deletion modules/wechat_qrcode/src/decodermgr.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class DecoderMgr {
DecoderMgr() { reader_ = new zxing::qrcode::QRCodeReader(); };
~DecoderMgr(){};

int decodeImage(cv::Mat src, bool use_nn_detector, string& result);
int decodeImage(cv::Mat src, bool use_nn_detector, string& result, vector<Point2f>& points);

private:
zxing::Ref<zxing::UnicomBlock> qbarUicomBlock_;
Expand Down
16 changes: 13 additions & 3 deletions modules/wechat_qrcode/src/wechat_qrcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,8 @@ vector<string> WeChatQRCode::Impl::decode(const Mat& img, vector<Mat>& candidate
vector<string> decode_results;
for (auto& point : candidate_points) {
Mat cropped_img;
Align aligner;
if (use_nn_detector_) {
Align aligner;
cropped_img = cropObj(img, point, aligner);
} else {
cropped_img = img;
Expand All @@ -144,9 +144,19 @@ vector<string> WeChatQRCode::Impl::decode(const Mat& img, vector<Mat>& candidate
super_resolution_model_->processImageScale(cropped_img, cur_scale, use_nn_sr_);
string result;
DecoderMgr decodemgr;
auto ret = decodemgr.decodeImage(scaled_img, use_nn_detector_, result);

vector<Point2f> points_qr;
auto ret = decodemgr.decodeImage(scaled_img, use_nn_detector_, result, points_qr);
if (ret == 0) {
for (auto&& pt: points_qr) {
pt /= cur_scale;
}

if (use_nn_detector_)
points_qr = aligner.warpBack(points_qr);
for (int i = 0; i < 4; ++i) {
point.at<float>(i, 0) = points_qr[i].x;
point.at<float>(i, 1) = points_qr[i].y;
}
decode_results.push_back(result);
points.push_back(point);
break;
Expand Down
52 changes: 52 additions & 0 deletions modules/wechat_qrcode/test/test_qrcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,58 @@ TEST_P(Objdetect_QRCode_Multi, regression) {
}
}

TEST(Objdetect_QRCode_points_position, rotate45) {
string path_detect_prototxt, path_detect_caffemodel, path_sr_prototxt, path_sr_caffemodel;
string model_version = "_2021-01";
path_detect_prototxt = findDataFile("dnn/wechat"+model_version+"/detect.prototxt", false);
path_detect_caffemodel = findDataFile("dnn/wechat"+model_version+"/detect.caffemodel", false);
path_sr_prototxt = findDataFile("dnn/wechat"+model_version+"/sr.prototxt", false);
path_sr_caffemodel = findDataFile("dnn/wechat"+model_version+"/sr.caffemodel", false);

auto detector = wechat_qrcode::WeChatQRCode(path_detect_prototxt, path_detect_caffemodel, path_sr_prototxt,
path_sr_caffemodel);

const cv::String expect_msg = "OpenCV";
QRCodeEncoder::Params params;
params.version = 5; // 37x37
Ptr<QRCodeEncoder> qrcode_enc = cv::QRCodeEncoder::create(params);
Mat qrImage;
qrcode_enc->encode(expect_msg, qrImage);
Mat image(800, 800, CV_8UC1);
const int pixInBlob = 4;
Size qrSize = Size((21+(params.version-1)*4)*pixInBlob,(21+(params.version-1)*4)*pixInBlob);
Rect2f rec((image.cols - qrSize.width)/2, (image.rows - qrSize.height)/2, qrSize.width, qrSize.height);
vector<float> goldCorners = {rec.x, rec.y,
rec.x+rec.width, rec.y,
rec.x+rec.width, rec.y+rec.height,
rec.x, rec.y+rec.height};
Mat roiImage = image(rec);
cv::resize(qrImage, roiImage, qrSize, 1., 1., INTER_NEAREST);

vector<Mat> points1;
auto decoded_info1 = detector.detectAndDecode(image, points1);
ASSERT_EQ(1ull, decoded_info1.size());
ASSERT_EQ(expect_msg, decoded_info1[0]);
EXPECT_NEAR(0, cvtest::norm(Mat(goldCorners), points1[0].reshape(1, 8), NORM_INF), 8.);

const double angle = 45;
Point2f pc(image.cols/2.f, image.rows/2.f);
Mat rot = getRotationMatrix2D(pc, angle, 1.);
warpAffine(image, image, rot, image.size());
vector<float> rotateGoldCorners;
for (int i = 0; i < static_cast<int>(goldCorners.size()); i+= 2) {
rotateGoldCorners.push_back(rot.at<double>(0, 0) * goldCorners[i] +
rot.at<double>(0, 1) * goldCorners[i+1] + rot.at<double>(0, 2));
rotateGoldCorners.push_back(rot.at<double>(1, 0) * goldCorners[i] +
rot.at<double>(1, 1) * goldCorners[i+1] + rot.at<double>(1, 2));
}
vector<Mat> points2;
auto decoded_info2 = detector.detectAndDecode(image, points2);
ASSERT_EQ(1ull, decoded_info2.size());
ASSERT_EQ(expect_msg, decoded_info2[0]);
EXPECT_NEAR(0, cvtest::norm(Mat(rotateGoldCorners), points2[0].reshape(1, 8), NORM_INF), 11.);
}

INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode, testing::ValuesIn(qrcode_images_name));
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Close, testing::ValuesIn(qrcode_images_close));
INSTANTIATE_TEST_CASE_P(/**/, Objdetect_QRCode_Monitor, testing::ValuesIn(qrcode_images_monitor));
Expand Down

0 comments on commit 47bf66f

Please sign in to comment.