Skip to content

Commit 3787aca

Browse files
committed
QRDetector: tune distance and angle checks for FinderPatternSets
Turned out the scaling of the squaredDistance with the square of the finder pattern size ratio was skewing the cosine calculation too much, which could lead to accepting degenerate triangles like a,b,c on a line. This could cause the alignment pattern detection to find the same points for different alignment patterns and that in turn could result in RegressionLine creations with two identical points, which caused an assert to fail (see second issue in #951).
1 parent e108b65 commit 3787aca

File tree

1 file changed

+7
-5
lines changed

1 file changed

+7
-5
lines changed

core/src/qrcode/QRDetector.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -113,14 +113,16 @@ FinderPatternSets GenerateFinderPatternSets(FinderPatterns& patterns)
113113

114114
auto sets = std::multimap<double, FinderPatternSet>();
115115
auto squaredDistance = [](const auto* a, const auto* b) {
116-
// The scaling of the distance by the b/a size ratio is a very coarse compensation for the shortening effect of
116+
// The scaling of the distance based on the b/a size ratio is a very coarse compensation for the shortening effect of
117117
// the camera projection on slanted symbols. The fact that the size of the finder pattern is proportional to the
118118
// distance from the camera is used here. This approximation only works if a < b < 2*a (see below).
119119
// Test image: fix-finderpattern-order.jpg
120-
return dot((*a - *b), (*a - *b)) * std::pow(double(b->size) / a->size, 2);
120+
// Originally, I scaled the squaredDistance with the (b/a)^2 ratio but that could skew the cosine calculation
121+
// below too much, resulting in the acceptance of degenerate triangles (a, b and c on a line).
122+
return dot((*a - *b), (*a - *b)) * double(b->size) / a->size;
121123
};
122-
const double cosUpper = std::cos(45. / 180 * 3.1415); // TODO: use c++20 std::numbers::pi_v
123-
const double cosLower = std::cos(135. / 180 * 3.1415);
124+
const double cosUpper = std::cos(60. / 180 * 3.1415); // TODO: use c++20 std::numbers::pi_v
125+
const double cosLower = std::cos(120. / 180 * 3.1415);
124126

125127
int nbPatterns = Size(patterns);
126128
for (int i = 0; i < nbPatterns - 2; i++) {
@@ -162,7 +164,7 @@ FinderPatternSets GenerateFinderPatternSets(FinderPatterns& patterns)
162164
moduleCount < 21 * 0.9 || moduleCount > 177 * 1.5) // moduleCount may be overestimated, see above
163165
continue;
164166

165-
// Make sure the angle between AB and BC does not deviate from 90° by more than 45°
167+
// Make sure the angle between AB and BC does not deviate from 90° too much
166168
auto cosAB_BC = (distAB2 + distBC2 - distAC2) / (2 * distAB * distBC);
167169
if (std::isnan(cosAB_BC) || cosAB_BC > cosUpper || cosAB_BC < cosLower)
168170
continue;

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy