Merge pull request #19407 from rayonnant14:issue_19363
authorPolina Smolnikova <43805563+rayonnant14@users.noreply.github.com>
Fri, 5 Feb 2021 21:24:27 +0000 (00:24 +0300)
committerGitHub <noreply@github.com>
Fri, 5 Feb 2021 21:24:27 +0000 (21:24 +0000)
QRCodeDetector::decodeMulti() fixed invalid usage fixedType()

* fixed invalid usage fixedType()
changed default barcode type to CV_8UC1
added tests
added assert in case multi channel straight barcode input

* deleted extra wrap into OutputArray

* fix warnings

* objdetect(qr): remove unnecessary checks

Co-authored-by: Alexander Alekhin <alexander.a.alekhin@gmail.com>
modules/objdetect/src/qrcode.cpp
modules/objdetect/test/test_qrcode.cpp

index 449e6e6..063c7a9 100644 (file)
@@ -2491,12 +2491,13 @@ cv::String QRCodeDetector::decode(InputArray in, InputArray points,
     bool ok = qrdec.straightDecodingProcess();
 
     std::string decoded_info = qrdec.getDecodeInformation();
-
-    if (ok && straight_qrcode.needed())
+    if (!ok && straight_qrcode.needed())
+    {
+        straight_qrcode.release();
+    }
+    else if (straight_qrcode.needed())
     {
-        qrdec.getStraightBarcode().convertTo(straight_qrcode,
-                                             straight_qrcode.fixedType() ?
-                                             straight_qrcode.type() : CV_32FC2);
+        qrdec.getStraightBarcode().convertTo(straight_qrcode, CV_8UC1);
     }
 
     return ok ? decoded_info : std::string();
@@ -2520,11 +2521,13 @@ cv::String QRCodeDetector::decodeCurved(InputArray in, InputArray points,
 
     std::string decoded_info = qrdec.getDecodeInformation();
 
-    if (ok && straight_qrcode.needed())
+    if (!ok && straight_qrcode.needed())
     {
-        qrdec.getStraightBarcode().convertTo(straight_qrcode,
-                                             straight_qrcode.fixedType() ?
-                                             straight_qrcode.type() : CV_32FC2);
+        straight_qrcode.release();
+    }
+    else if (straight_qrcode.needed())
+    {
+        qrdec.getStraightBarcode().convertTo(straight_qrcode, CV_8UC1);
     }
 
     return ok ? decoded_info : std::string();
@@ -3615,18 +3618,18 @@ bool QRCodeDetector::decodeMulti(
             for_copy.push_back(straight_barcode[i]);
     }
     straight_barcode = for_copy;
-    vector<Mat> tmp_straight_qrcodes;
-    if (straight_qrcode.needed())
+    if (straight_qrcode.needed() && straight_barcode.size() == 0)
+    {
+        straight_qrcode.release();
+    }
+    else if (straight_qrcode.needed())
     {
+        straight_qrcode.create(Size((int)straight_barcode.size(), 1), CV_8UC1);
+        vector<Mat> tmp_straight_qrcodes(straight_barcode.size());
         for (size_t i = 0; i < straight_barcode.size(); i++)
         {
-            Mat tmp_straight_qrcode;
-            tmp_straight_qrcodes.push_back(tmp_straight_qrcode);
-            straight_barcode[i].convertTo(((OutputArray)tmp_straight_qrcodes[i]),
-                                             ((OutputArray)tmp_straight_qrcodes[i]).fixedType() ?
-                                             ((OutputArray)tmp_straight_qrcodes[i]).type() : CV_32FC2);
+            straight_barcode[i].convertTo(tmp_straight_qrcodes[i], CV_8UC1);
         }
-        straight_qrcode.createSameSize(tmp_straight_qrcodes, CV_32FC2);
         straight_qrcode.assign(tmp_straight_qrcodes);
     }
     decoded_info.clear();
index c26cd8a..fc55498 100644 (file)
@@ -252,6 +252,8 @@ TEST_P(Objdetect_QRCode, regression)
     decoded_info = qrcode.detectAndDecode(src, corners, straight_barcode);
     ASSERT_FALSE(corners.empty());
     ASSERT_FALSE(decoded_info.empty());
+    int expected_barcode_type = CV_8UC1;
+    EXPECT_EQ(expected_barcode_type, straight_barcode.type());
 #else
     ASSERT_TRUE(qrcode.detect(src, corners));
 #endif
@@ -317,6 +319,8 @@ TEST_P(Objdetect_QRCode_Close, regression)
     decoded_info = qrcode.detectAndDecode(barcode, corners, straight_barcode);
     ASSERT_FALSE(corners.empty());
     ASSERT_FALSE(decoded_info.empty());
+    int expected_barcode_type = CV_8UC1;
+    EXPECT_EQ(expected_barcode_type, straight_barcode.type());
 #else
     ASSERT_TRUE(qrcode.detect(barcode, corners));
 #endif
@@ -382,6 +386,8 @@ TEST_P(Objdetect_QRCode_Monitor, regression)
     decoded_info = qrcode.detectAndDecode(barcode, corners, straight_barcode);
     ASSERT_FALSE(corners.empty());
     ASSERT_FALSE(decoded_info.empty());
+    int expected_barcode_type = CV_8UC1;
+    EXPECT_EQ(expected_barcode_type, straight_barcode.type());
 #else
     ASSERT_TRUE(qrcode.detect(barcode, corners));
 #endif
@@ -442,6 +448,8 @@ TEST_P(Objdetect_QRCode_Curved, regression)
     decoded_info = qrcode.detectAndDecodeCurved(src, corners, straight_barcode);
     ASSERT_FALSE(corners.empty());
     ASSERT_FALSE(decoded_info.empty());
+    int expected_barcode_type = CV_8UC1;
+    EXPECT_EQ(expected_barcode_type, straight_barcode.type());
 #else
     ASSERT_TRUE(qrcode.detect(src, corners));
 #endif
@@ -502,6 +510,9 @@ TEST_P(Objdetect_QRCode_Multi, regression)
     EXPECT_TRUE(qrcode.detectAndDecodeMulti(src, decoded_info, corners, straight_barcode));
     ASSERT_FALSE(corners.empty());
     ASSERT_FALSE(decoded_info.empty());
+    int expected_barcode_type = CV_8UC1;
+    for(size_t i = 0; i < straight_barcode.size(); i++)
+        EXPECT_EQ(expected_barcode_type, straight_barcode[i].type());
 #else
     ASSERT_TRUE(qrcode.detectMulti(src, corners));
 #endif
@@ -612,6 +623,32 @@ TEST(Objdetect_QRCode_detectMulti, detect_regression_16961)
     EXPECT_EQ(corners.size(), expect_corners_size);
 }
 
+TEST(Objdetect_QRCode_decodeMulti, check_output_parameters_type_19363)
+{
+    const std::string name_current_image = "9_qrcodes.jpg";
+    const std::string root = "qrcode/multiple/";
+
+    std::string image_path = findDataFile(root + name_current_image);
+    Mat src = imread(image_path);
+    ASSERT_FALSE(src.empty()) << "Can't read image: " << image_path;
+#ifdef HAVE_QUIRC
+    QRCodeDetector qrcode;
+    std::vector<Point> corners;
+    std::vector<cv::String> decoded_info;
+#if 0  // FIXIT: OutputArray::create() type check
+    std::vector<Mat2b> straight_barcode_nchannels;
+    EXPECT_ANY_THROW(qrcode.detectAndDecodeMulti(src, decoded_info, corners, straight_barcode_nchannels));
+#endif
+
+    int expected_barcode_type = CV_8UC1;
+    std::vector<Mat1b> straight_barcode;
+    EXPECT_TRUE(qrcode.detectAndDecodeMulti(src, decoded_info, corners, straight_barcode));
+    ASSERT_FALSE(corners.empty());
+    for(size_t i = 0; i < straight_barcode.size(); i++)
+        EXPECT_EQ(expected_barcode_type, straight_barcode[i].type());
+#endif
+}
+
 TEST(Objdetect_QRCode_basic, not_found_qrcode)
 {
     std::vector<Point> corners;