Skip to content

Improve QR code version estimation #22695

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Merged
merged 1 commit into from
Nov 28, 2022

Conversation

AleksandrPanov
Copy link
Contributor

@AleksandrPanov AleksandrPanov commented Oct 26, 2022

QR codes with version 7 or greater store a special 18 bit code with the version number of the code:

https://www.thonky.com/qr-code-tutorial/format-version-information
https://www.thonky.com/qr-code-tutorial/format-version-tables

This PR reads this QR information to determine the version.

Also, to determine the version of QR codes < 7, added method with getNumModules() function.
To check the correctness, a benchmark was launched:

  • correctly found 10 versions in category high_version instead of 2
  • +6% monitor decode, +0.5% total correct decoded images, no regression

Logging from benchmark:
new_version.txt
base.txt

Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

  • I agree to contribute to the project under Apache 2 License.
  • 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
  • The PR is proposed to the proper branch
  • 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

@asmorkalov asmorkalov changed the title qr improve version detect Improve QR code version estimation Nov 17, 2022
@asmorkalov asmorkalov added this to the 4.7.0 milestone Nov 17, 2022
@AleksandrPanov AleksandrPanov force-pushed the qr_improve_version_detect branch from 3240ebc to 53964a3 Compare November 17, 2022 14:32
@asmorkalov asmorkalov self-requested a review November 17, 2022 16:04
@AleksandrPanov AleksandrPanov force-pushed the qr_improve_version_detect branch 4 times, most recently from 82a247a to 0a8c040 Compare November 18, 2022 02:39
@AleksandrPanov AleksandrPanov marked this pull request as ready for review November 18, 2022 08:59
@AleksandrPanov AleksandrPanov force-pushed the qr_improve_version_detect branch from 0a8c040 to 8566b76 Compare November 18, 2022 09:05
@AleksandrPanov AleksandrPanov force-pushed the qr_improve_version_detect branch from 8550665 to ea53a7b Compare November 23, 2022 17:04
@AleksandrPanov AleksandrPanov marked this pull request as draft November 23, 2022 21:42
@AleksandrPanov AleksandrPanov force-pushed the qr_improve_version_detect branch 2 times, most recently from a6d055e to 091f3e6 Compare November 24, 2022 02:12
@AleksandrPanov AleksandrPanov marked this pull request as ready for review November 24, 2022 02:12
@asmorkalov asmorkalov self-assigned this Nov 24, 2022
@AleksandrPanov AleksandrPanov force-pushed the qr_improve_version_detect branch 4 times, most recently from 2ea256c to 79c63c6 Compare November 25, 2022 10:50
@AleksandrPanov
Copy link
Contributor Author

@asmorkalov

@AleksandrPanov AleksandrPanov force-pushed the qr_improve_version_detect branch from 79c63c6 to 4b41946 Compare November 25, 2022 13:36
@asmorkalov asmorkalov self-requested a review November 28, 2022 14:01
Copy link
Contributor

@asmorkalov asmorkalov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@AleksandrPanov AleksandrPanov force-pushed the qr_improve_version_detect branch from 3d0a706 to ed3810f Compare November 28, 2022 14:46
@asmorkalov asmorkalov merged commit eb68de9 into opencv:4.x Nov 28, 2022
Copy link
Member

@rogday rogday left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for contribution!
Just comments, feel free to ignore.
EDIT: welp, I'm late

* findPatternsVerticesPoints() may be erroneous, so they are checked.
*/
static inline std::pair<int, int> matchPatternPoints(const vector<Point> &finderPattern,
const vector<Point2f> cornerPointsQR) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like it should be a reference

sqrt(normL2Sqr<float>(cornerPointsQR[0] - cornerPointsQR[3]))*0.5f;
const float maxRelativeDistance = .1f;

if (distanceToOrig/originalQrSide > maxRelativeDistance)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, looks suspicious: squared distance is divided by mean of distances

vector<vector<Point>> finderPatterns;
double numModulesX = 0., numModulesY = 0.;
bool flag = findPatternsVerticesPoints(finderPatterns);
if (flag) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: negate the condition to reduce nesting.

double numModulesX = 0., numModulesY = 0.;
bool flag = findPatternsVerticesPoints(finderPatterns);
if (flag) {
vector<double> pattern_distance(4);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this a vector?

if (flag) {
vector<double> pattern_distance(4);
for (auto& pattern : finderPatterns) {
auto indexes = matchPatternPoints(pattern, original_points);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: name both elements of the pair so that's easier to read.

Comment on lines +2527 to +2528
if (roundingError < thresholdFinderPattern)
useFinderPattern = true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useFinderPattern = (roundingError < thresholdFinderPattern);

bool useCode = false;
int versionByCode = 7;
if (cvRound(versionByFinderPattern) >= 7 || versionByTransition >= 7) {
vector<std::pair<double, int>> versionAndDistances;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this? Should be pair bestVersion instead, then push_back -> bestVersion = std::min(bestVersion, ...);

version_size = 21 + (version - 1) * 4;
CV_LOG_INFO(NULL, "QR corners: " << original_points[0] << " " << original_points[1] << " " << original_points[2] <<
" " << original_points[3]);
if ( !(0 < version && version <= 40) ) { return false; }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: if ( version <= 0 || version > 40) { return false; } looks far more readable

Comment on lines +2269 to +2271
if (1.f - minSide / maxSide > patternMaxRelativeLen)
return false;
return true;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return (1.f - minSide / maxSide <= patternMaxRelativeLen);

@alalek alalek mentioned this pull request Jan 8, 2023
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants