diff --git a/3rdparty/quirc/include/quirc.h b/3rdparty/quirc/include/quirc.h index 0e7cb94d1c..957ae10e6c 100644 --- a/3rdparty/quirc/include/quirc.h +++ b/3rdparty/quirc/include/quirc.h @@ -165,6 +165,8 @@ void quirc_extract(const struct quirc *q, int index, /* Decode a QR-code, returning the payload data. */ quirc_decode_error_t quirc_decode(const struct quirc_code *code, struct quirc_data *data); +/* flip the QR code horizontaly (mirror flip) */ +void quirc_flip(struct quirc_code *code); #ifdef __cplusplus } diff --git a/3rdparty/quirc/src/decode.c b/3rdparty/quirc/src/decode.c index 894b5067d8..e24a4fbe2a 100644 --- a/3rdparty/quirc/src/decode.c +++ b/3rdparty/quirc/src/decode.c @@ -917,3 +917,18 @@ quirc_decode_error_t quirc_decode(const struct quirc_code *code, return QUIRC_SUCCESS; } + +void quirc_flip(struct quirc_code *code) +{ + struct quirc_code flipped = {0}; + unsigned int offset = 0; + for (int y = 0; y < code->size; y++) { + for (int x = 0; x < code->size; x++) { + if (grid_bit(code, y, x)) { + flipped.cell_bitmap[offset >> 3u] |= (1u << (offset & 7u)); + } + offset++; + } + } + memcpy(&code->cell_bitmap, &flipped.cell_bitmap, sizeof(flipped.cell_bitmap)); +} diff --git a/modules/objdetect/src/qrcode.cpp b/modules/objdetect/src/qrcode.cpp index 41c604a8db..93fffeaf5c 100644 --- a/modules/objdetect/src/qrcode.cpp +++ b/modules/objdetect/src/qrcode.cpp @@ -2732,6 +2732,12 @@ bool QRDecode::decodingProcess() quirc_data qr_code_data; quirc_decode_error_t errorCode = quirc_decode(&qr_code, &qr_code_data); + + if(errorCode == QUIRC_ERROR_DATA_ECC){ + quirc_flip(&qr_code); + errorCode = quirc_decode(&qr_code, &qr_code_data); + } + if (errorCode != 0) { return false; } for (int i = 0; i < qr_code_data.payload_len; i++) diff --git a/modules/objdetect/test/test_qrcode.cpp b/modules/objdetect/test/test_qrcode.cpp index 568324b7ca..0868932eab 100644 --- a/modules/objdetect/test/test_qrcode.cpp +++ b/modules/objdetect/test/test_qrcode.cpp @@ -708,6 +708,38 @@ TEST(Objdetect_QRCode_detect, detect_regression_21287) #endif } +TEST(Objdetect_QRCode_detect_flipped, regression_23249) +{ + + const std::vector> flipped_images = + // image name , expected result + {{"flipped_1.png", "The key is /qrcod_OMevpf"}, + {"flipped_2.png", "A26"}}; + + const std::string root = "qrcode/flipped/"; + + for(const auto &flipped_image : flipped_images){ + const std::string &image_name = flipped_image.first; + const std::string &expect_msg = flipped_image.second; + + std::string image_path = findDataFile(root + image_name); + Mat src = imread(image_path); + ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path; + QRCodeDetector qrcode; + std::vector corners; + Mat straight_barcode; + cv::String decoded_info; + EXPECT_TRUE(qrcode.detect(src, corners)); + EXPECT_TRUE(!corners.empty()); + std::string decoded_msg; + #ifdef HAVE_QUIRC + EXPECT_NO_THROW(decoded_msg = qrcode.decode(src, corners, straight_barcode)); + ASSERT_FALSE(straight_barcode.empty()) << "Can't decode qrimage."; + EXPECT_EQ(expect_msg, decoded_msg); + #endif + } +} + // @author Kumataro, https://github.com/Kumataro TEST(Objdetect_QRCode_decode, decode_regression_21929) {