Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9fa014e

Browse files
author
Alexander Panov
authored
Merge pull request#23264 from AleksandrPanov:add_detect_qr_with_aruco
Add detect qr with aruco#23264Using Aruco to detect finder patterns to search QR codes.TODO (in next PR):- add single QR detect (update `detect()` and `detectAndDecode()`)- need reduce full enumeration of finder patterns- need add finder pattern info to `decode` step- need to merge the pipeline of the old and new algorithm[Current results:](https://docs.google.com/spreadsheets/d/1ufKyR-Zs-IGXwvqPgftssmTlceVjiQX364sbrjr2QU8/edit#gid=1192415584)+20% total detect, +8% total decode in OpenCV [QR benchmark](https://github.com/opencv/opencv_benchmarks/tree/develop/python_benchmarks/qr_codes) ![res1](https://user-images.githubusercontent.com/22337800/231228556-191d3eae-a318-44e1-af99-e7d420bf6248.png)78.4% detect, 58.7% decode vs 58.5 detect, 50.5% decode in default[main.py.txt](https://github.com/opencv/opencv/files/10762369/main.py.txt)![res2](https://user-images.githubusercontent.com/22337800/231229123-ed7f1eda-159a-444b-a3ff-f107d8eb4a20.png)add new info to [google docs](https://docs.google.com/spreadsheets/d/1ufKyR-Zs-IGXwvqPgftssmTlceVjiQX364sbrjr2QU8/edit?usp=sharing)### Pull Request Readiness ChecklistSee details athttps://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request- [x] I agree to contribute to the project under Apache 2 License.- [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV- [x] The PR is proposed to the proper branch- [x] There is a reference to the original bug report and related work- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name.- [ ] The feature is well documented and sample code can be built with the project CMake
1 parent5330112 commit9fa014e

File tree

7 files changed

+929
-362
lines changed

7 files changed

+929
-362
lines changed

‎modules/objdetect/include/opencv2/objdetect.hpp‎

Lines changed: 104 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
#defineOPENCV_OBJDETECT_HPP
4646

4747
#include"opencv2/core.hpp"
48+
#include"opencv2/objdetect/aruco_detector.hpp"
4849

4950
/**
5051
@defgroup objdetect Object Detection
@@ -763,28 +764,15 @@ class CV_EXPORTS_W QRCodeEncoder {
763764

764765
};
765766

766-
classCV_EXPORTS_W QRCodeDetector
767-
{
767+
classCV_EXPORTS_W_SIMPLE QRCodeDetectorBase {
768768
public:
769-
CV_WRAPQRCodeDetector();
770-
~QRCodeDetector();
769+
CV_DEPRECATED_EXTERNAL// avoid using in C++ code, will be moved to "protected" (need to fix bindings first)
770+
QRCodeDetectorBase();
771771

772-
/** @brief sets the epsilon used during the horizontal scan of QR code stop marker detection.
773-
@param epsX Epsilon neighborhood, which allows you to determine the horizontal pattern
774-
of the scheme 1:1:3:1:1 according to QR code standard.
775-
*/
776-
CV_WRAPvoidsetEpsX(double epsX);
777-
/** @brief sets the epsilon used during the vertical scan of QR code stop marker detection.
778-
@param epsY Epsilon neighborhood, which allows you to determine the vertical pattern
779-
of the scheme 1:1:3:1:1 according to QR code standard.
780-
*/
781-
CV_WRAPvoidsetEpsY(double epsY);
782-
783-
/** @brief use markers to improve the position of the corners of the QR code
784-
*
785-
* alignmentMarkers using by default
786-
*/
787-
CV_WRAPvoidsetUseAlignmentMarkers(bool useAlignmentMarkers);
772+
QRCodeDetectorBase(const QRCodeDetectorBase&) =default;
773+
QRCodeDetectorBase(QRCodeDetectorBase&&) =default;
774+
QRCodeDetectorBase&operator=(const QRCodeDetectorBase&) =default;
775+
QRCodeDetectorBase&operator=(QRCodeDetectorBase&&) =default;
788776

789777
/** @brief Detects QR code in image and returns the quadrangle containing the code.
790778
@param img grayscale or color (BGR) image containing (or not) QR code.
@@ -799,16 +787,7 @@ class CV_EXPORTS_W QRCodeDetector
799787
@param points Quadrangle vertices found by detect() method (or some other algorithm).
800788
@param straight_qrcode The optional output image containing rectified and binarized QR code
801789
*/
802-
CV_WRAP std::stringdecode(InputArray img, InputArray points, OutputArray straight_qrcode = noArray());
803-
804-
/** @brief Decodes QR code on a curved surface in image once it's found by the detect() method.
805-
806-
Returns UTF8-encoded output string or empty string if the code cannot be decoded.
807-
@param img grayscale or color (BGR) image containing QR code.
808-
@param points Quadrangle vertices found by detect() method (or some other algorithm).
809-
@param straight_qrcode The optional output image containing rectified and binarized QR code
810-
*/
811-
CV_WRAP cv::StringdecodeCurved(InputArray img, InputArray points, OutputArray straight_qrcode = noArray());
790+
CV_WRAP std::stringdecode(InputArray img, InputArray points, OutputArray straight_qrcode = noArray())const;
812791

813792
/** @brief Both detects and decodes QR code
814793
@@ -817,16 +796,8 @@ class CV_EXPORTS_W QRCodeDetector
817796
@param straight_qrcode The optional output image containing rectified and binarized QR code
818797
*/
819798
CV_WRAP std::stringdetectAndDecode(InputArray img, OutputArray points=noArray(),
820-
OutputArray straight_qrcode = noArray());
821-
822-
/** @brief Both detects and decodes QR code on a curved surface
799+
OutputArray straight_qrcode = noArray())const;
823800

824-
@param img grayscale or color (BGR) image containing QR code.
825-
@param points optional output array of vertices of the found QR code quadrangle. Will be empty if not found.
826-
@param straight_qrcode The optional output image containing rectified and binarized QR code
827-
*/
828-
CV_WRAP std::stringdetectAndDecodeCurved(InputArray img, OutputArray points=noArray(),
829-
OutputArray straight_qrcode = noArray());
830801

831802
/** @brief Detects QR codes in image and returns the vector of the quadrangles containing the codes.
832803
@param img grayscale or color (BGR) image containing (or not) QR codes.
@@ -860,18 +831,109 @@ class CV_EXPORTS_W QRCodeDetector
860831
OutputArray points = noArray(),
861832
OutputArrayOfArrays straight_qrcode = noArray()
862833
)const;
863-
864-
protected:
865834
structImpl;
835+
protected:
866836
Ptr<Impl> p;
867837
};
868838

839+
classCV_EXPORTS_W_SIMPLE QRCodeDetector : public QRCodeDetectorBase
840+
{
841+
public:
842+
CV_WRAPQRCodeDetector();
843+
844+
/** @brief sets the epsilon used during the horizontal scan of QR code stop marker detection.
845+
@param epsX Epsilon neighborhood, which allows you to determine the horizontal pattern
846+
of the scheme 1:1:3:1:1 according to QR code standard.
847+
*/
848+
CV_WRAP QRCodeDetector&setEpsX(double epsX);
849+
/** @brief sets the epsilon used during the vertical scan of QR code stop marker detection.
850+
@param epsY Epsilon neighborhood, which allows you to determine the vertical pattern
851+
of the scheme 1:1:3:1:1 according to QR code standard.
852+
*/
853+
CV_WRAP QRCodeDetector&setEpsY(double epsY);
854+
855+
/** @brief use markers to improve the position of the corners of the QR code
856+
*
857+
* alignmentMarkers using by default
858+
*/
859+
CV_WRAP QRCodeDetector&setUseAlignmentMarkers(bool useAlignmentMarkers);
860+
861+
/** @brief Decodes QR code on a curved surface in image once it's found by the detect() method.
862+
863+
Returns UTF8-encoded output string or empty string if the code cannot be decoded.
864+
@param img grayscale or color (BGR) image containing QR code.
865+
@param points Quadrangle vertices found by detect() method (or some other algorithm).
866+
@param straight_qrcode The optional output image containing rectified and binarized QR code
867+
*/
868+
CV_WRAP cv::StringdecodeCurved(InputArray img, InputArray points, OutputArray straight_qrcode = noArray());
869+
870+
/** @brief Both detects and decodes QR code on a curved surface
871+
872+
@param img grayscale or color (BGR) image containing QR code.
873+
@param points optional output array of vertices of the found QR code quadrangle. Will be empty if not found.
874+
@param straight_qrcode The optional output image containing rectified and binarized QR code
875+
*/
876+
CV_WRAP std::stringdetectAndDecodeCurved(InputArray img, OutputArray points=noArray(),
877+
OutputArray straight_qrcode = noArray());
878+
};
879+
880+
classCV_EXPORTS_W_SIMPLE QRCodeDetectorAruco : public QRCodeDetectorBase {
881+
public:
882+
CV_WRAPQRCodeDetectorAruco();
883+
884+
structCV_EXPORTS_W_SIMPLE Params {
885+
CV_WRAPParams();
886+
887+
/** @brief The minimum allowed pixel size of a QR module in the smallest image in the image pyramid, default 4.f*/
888+
CV_PROP_RWfloat minModuleSizeInPyramid;
889+
890+
/** @brief The maximum allowed relative rotation for finder patterns in the same QR code, default pi/12*/
891+
CV_PROP_RWfloat maxRotation;
892+
893+
/** @brief The maximum allowed relative mismatch in module sizes for finder patterns in the same QR code, default 1.75f*/
894+
CV_PROP_RWfloat maxModuleSizeMismatch;
895+
896+
/** @brief The maximum allowed module relative mismatch for timing pattern module, default 2.f
897+
*
898+
* If relative mismatch of timing pattern module more this value, penalty points will be added.
899+
* If a lot of penalty points are added, QR code will be rejected.*/
900+
CV_PROP_RWfloat maxTimingPatternMismatch;
901+
902+
/** @brief The maximum allowed percentage of penalty points out of total pins in timing pattern, default 0.4f*/
903+
CV_PROP_RWfloat maxPenalties;
904+
905+
/** @brief The maximum allowed relative color mismatch in the timing pattern, default 0.2f*/
906+
CV_PROP_RWfloat maxColorsMismatch;
907+
908+
/** @brief The algorithm find QR codes with almost minimum timing pattern score and minimum size, default 0.9f
909+
*
910+
* The QR code with the minimum "timing pattern score" and minimum "size" is selected as the best QR code.
911+
* If for the current QR code "timing pattern score" * scaleTimingPatternScore < "previous timing pattern score" and "size" < "previous size", then
912+
* current QR code set as the best QR code.*/
913+
CV_PROP_RWfloat scaleTimingPatternScore;
914+
};
915+
916+
/** @brief QR code detector constructor for Aruco-based algorithm. See cv::QRCodeDetectorAruco::Params*/
917+
CV_WRAPexplicitQRCodeDetectorAruco(const QRCodeDetectorAruco::Params& params);
918+
919+
/** @brief Detector parameters getter. See cv::QRCodeDetectorAruco::Params*/
920+
CV_WRAPconst QRCodeDetectorAruco::Params&getDetectorParameters()const;
921+
922+
/** @brief Detector parameters setter. See cv::QRCodeDetectorAruco::Params*/
923+
CV_WRAP QRCodeDetectorAruco&setDetectorParameters(const QRCodeDetectorAruco::Params& params);
924+
925+
/** @brief Aruco detector parameters are used to search for the finder patterns.*/
926+
CV_WRAP aruco::DetectorParametersgetArucoParameters();
927+
928+
/** @brief Aruco detector parameters are used to search for the finder patterns.*/
929+
CV_WRAPvoidsetArucoParameters(const aruco::DetectorParameters& params);
930+
};
931+
869932
//! @}
870933
}
871934

872935
#include"opencv2/objdetect/detection_based_tracker.hpp"
873936
#include"opencv2/objdetect/face.hpp"
874-
#include"opencv2/objdetect/aruco_detector.hpp"
875937
#include"opencv2/objdetect/charuco_detector.hpp"
876938

877939
#endif
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"ManualFuncs" : {
3+
"QRCodeDetectorAruco": {
4+
"getDetectorParameters": {"declaration" : [""],"implementation" : [""] }
5+
}
6+
}
7+
}

‎modules/objdetect/perf/perf_qrcode_pipeline.cpp‎

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// of this distribution and at http://opencv.org/license.html.
44

55
#include"perf_precomp.hpp"
6+
#include"../test/test_qr_utils.hpp"
67

78
namespaceopencv_test
89
{
@@ -23,7 +24,9 @@ PERF_TEST_P_(Perf_Objdetect_QRCode, detect)
2324
std::vector< Point > corners;
2425
QRCodeDetector qrcode;
2526
TEST_CYCLE()ASSERT_TRUE(qrcode.detect(src, corners));
26-
SANITY_CHECK(corners);
27+
constint pixels_error =3;
28+
check_qr(root, name_current_image,"test_images", corners, {}, pixels_error);
29+
SANITY_CHECK_NOTHING();
2730
}
2831

2932
#ifdef HAVE_QUIRC
@@ -45,75 +48,73 @@ PERF_TEST_P_(Perf_Objdetect_QRCode, decode)
4548
decoded_info = qrcode.decode(src, corners, straight_barcode);
4649
ASSERT_FALSE(decoded_info.empty());
4750
}
48-
49-
std::vector<uint8_t>decoded_info_uint8_t(decoded_info.begin(), decoded_info.end());
50-
SANITY_CHECK(decoded_info_uint8_t);
51-
SANITY_CHECK(straight_barcode);
52-
51+
constint pixels_error =3;
52+
check_qr(root, name_current_image,"test_images", corners, {decoded_info}, pixels_error);
53+
SANITY_CHECK_NOTHING();
5354
}
5455
#endif
5556

56-
typedef ::perf::TestBaseWithParam<std::string> Perf_Objdetect_QRCode_Multi;
57+
typedef ::perf::TestBaseWithParam<std::tuple<std::string, std::string>> Perf_Objdetect_QRCode_Multi;
5758

58-
staticinlineboolcompareCorners(const Point2f& corner1,const Point2f& corner2) {
59-
return corner1.x == corner2.x ? corner1.y < corner2.y : corner1.x < corner2.x;
60-
}
59+
static std::set<std::pair<std::string, std::string>> disabled_samples = {{"5_qrcodes.png","aruco_based"}};
6160

6261
PERF_TEST_P_(Perf_Objdetect_QRCode_Multi, detectMulti)
6362
{
64-
const std::string name_current_image =GetParam();
63+
const std::string name_current_image = get<0>(GetParam());
64+
const std::string method = get<1>(GetParam());
6565
const std::string root ="cv/qrcode/multiple/";
6666

6767
std::string image_path =findDataFile(root + name_current_image);
6868
Mat src =imread(image_path);
6969
ASSERT_FALSE(src.empty()) <<"Can't read image:" << image_path;
70-
std::vector<Point2f> corners;
71-
QRCodeDetector qrcode;
70+
std::vector<Point> corners;
71+
QRCodeDetectorBase qrcode =QRCodeDetector();
72+
if (method =="aruco_based") {
73+
qrcode =QRCodeDetectorAruco();
74+
}
7275
TEST_CYCLE()ASSERT_TRUE(qrcode.detectMulti(src, corners));
73-
sort(corners.begin(), corners.end(), compareCorners);
74-
SANITY_CHECK(corners);
75-
}
76-
77-
staticinlineboolcompareQR(const pair<string, Mat>& v1,const pair<string, Mat>& v2) {
78-
return v1.first < v2.first;
76+
constint pixels_error =7;
77+
check_qr(root, name_current_image,"multiple_images", corners, {}, pixels_error,true);
78+
SANITY_CHECK_NOTHING();
7979
}
8080

8181
#ifdef HAVE_QUIRC
8282
PERF_TEST_P_(Perf_Objdetect_QRCode_Multi, decodeMulti)
8383
{
84-
const std::string name_current_image =GetParam();
84+
const std::string name_current_image = get<0>(GetParam());
85+
std::string method = get<1>(GetParam());
8586
const std::string root ="cv/qrcode/multiple/";
8687
std::string image_path =findDataFile(root + name_current_image);
8788
Mat src =imread(image_path);
8889
ASSERT_FALSE(src.empty()) <<"Can't read image:" << image_path;
89-
QRCodeDetector qrcode;
90+
if (disabled_samples.find({name_current_image, method}) != disabled_samples.end()) {
91+
throwSkipTestException(name_current_image +" is disabled sample for method" + method);
92+
}
93+
QRCodeDetectorBase qrcode =QRCodeDetector();
94+
if (method =="aruco_based") {
95+
qrcode =QRCodeDetectorAruco();
96+
}
9097
std::vector<Point2f> corners;
9198
ASSERT_TRUE(qrcode.detectMulti(src, corners));
9299
std::vector<Mat> straight_barcode;
93100
std::vector< cv::String > decoded_info;
94101
TEST_CYCLE()
95102
{
96103
ASSERT_TRUE(qrcode.decodeMulti(src, corners, decoded_info, straight_barcode));
97-
for(size_t i =0; i < decoded_info.size(); i++)
98-
{
99-
ASSERT_FALSE(decoded_info[i].empty());
100-
}
104+
}
105+
ASSERT_TRUE(decoded_info.size() >0ull);
106+
for(size_t i =0; i <decoded_info.size(); i++) {
107+
ASSERT_FALSE(decoded_info[i].empty());
101108
}
102109
ASSERT_EQ(decoded_info.size(), straight_barcode.size());
103-
vector<pair<string, Mat> > result;
104-
for (size_t i =0ull;i <decoded_info.size(); i++) {
105-
result.push_back(make_pair(decoded_info[i], straight_barcode[i]));
110+
vector<Point>corners_result(corners.size());
111+
for (size_t i =0ull; i <corners_result.size(); i++) {
112+
corners_result[i] = corners[i];
106113
}
107114

108-
sort(result.begin(), result.end(), compareQR);
109-
vector<vector<uint8_t> > decoded_info_sort;
110-
vector<Mat> straight_barcode_sort;
111-
for (size_t i =0ull; i < result.size(); i++) {
112-
vector<uint8_t>tmp(result[i].first.begin(), result[i].first.end());
113-
decoded_info_sort.push_back(tmp);
114-
straight_barcode_sort.push_back(result[i].second);
115-
}
116-
SANITY_CHECK(decoded_info_sort);
115+
constint pixels_error =7;
116+
check_qr(root, name_current_image,"multiple_images", corners_result, decoded_info, pixels_error,true);
117+
SANITY_CHECK_NOTHING();
117118
}
118119
#endif
119120

@@ -127,11 +128,10 @@ INSTANTIATE_TEST_CASE_P(/*nothing*/, Perf_Objdetect_QRCode,
127128
// version_5_right.jpg DISABLED after tile fix, PR #22025
128129

129130
INSTANTIATE_TEST_CASE_P(/*nothing*/, Perf_Objdetect_QRCode_Multi,
130-
::testing::Values(
131-
"2_qrcodes.png","3_close_qrcodes.png","3_qrcodes.png","4_qrcodes.png",
132-
"5_qrcodes.png","6_qrcodes.png","7_qrcodes.png","8_close_qrcodes.png"
133-
)
134-
);
131+
testing::Combine(testing::Values("2_qrcodes.png","3_close_qrcodes.png","3_qrcodes.png","4_qrcodes.png",
132+
"5_qrcodes.png","6_qrcodes.png","7_qrcodes.png","8_close_qrcodes.png"),
133+
testing::Values("contours_based","aruco_based")));
134+
135135

136136
typedef ::perf::TestBaseWithParam< tuple< std::string, Size > > Perf_Objdetect_Not_QRCode;
137137

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp