| 332 | } |
| 333 | |
| 334 | DetectorResult SampleQR(const BitMatrix& image, const FinderPatternSet& fp) |
| 335 | { |
| 336 | auto top = EstimateDimension(image, fp.tl, fp.tr); |
| 337 | auto left = EstimateDimension(image, fp.tl, fp.bl); |
| 338 | |
| 339 | if (!top.dim && !left.dim) |
| 340 | return {}; |
| 341 | |
| 342 | auto best = top.err == left.err ? (top.dim > left.dim ? top : left) : (top.err < left.err ? top : left); |
| 343 | int dimension = best.dim; |
| 344 | int moduleSize = static_cast<int>(best.ms + 1); |
| 345 | |
| 346 | auto br = PointF{-1, -1}; |
| 347 | auto brOffset = PointF{3, 3}; |
| 348 | |
| 349 | // Everything except version 1 (21 modules) has an alignment pattern. Estimate the center of that by intersecting |
| 350 | // line extensions of the 1 module wide square around the finder patterns. This could also help with detecting |
| 351 | // slanted symbols of version 1. |
| 352 | |
| 353 | // generate 4 lines: outer and inner edge of the 1 module wide black line between the two outer and the inner |
| 354 | // (tl) finder pattern |
| 355 | auto bl2 = TraceLine(image, fp.bl, fp.tl, 2); |
| 356 | auto bl3 = TraceLine(image, fp.bl, fp.tl, 3); |
| 357 | auto tr2 = TraceLine(image, fp.tr, fp.tl, 2); |
| 358 | auto tr3 = TraceLine(image, fp.tr, fp.tl, 3); |
| 359 | |
| 360 | if (bl2.isValid() && tr2.isValid() && bl3.isValid() && tr3.isValid()) { |
| 361 | // intersect both outer and inner line pairs and take the center point between the two intersection points |
| 362 | auto brInter = (intersect(bl2, tr2) + intersect(bl3, tr3)) / 2; |
| 363 | log(brInter, 3); |
| 364 | |
| 365 | if (dimension > 21) |
| 366 | if (auto brCP = LocateAlignmentPattern(image, moduleSize, brInter)) |
| 367 | br = *brCP; |
| 368 | |
| 369 | // if the symbol is tilted or the resolution of the RegressionLines is sufficient, use their intersection |
| 370 | // as the best estimate (see discussion in #199 and test image estimate-tilt.jpg ) |
| 371 | if (!image.isIn(br) && (EstimateTilt(fp) > 1.1 || (bl2.isHighRes() && bl3.isHighRes() && tr2.isHighRes() && tr3.isHighRes()))) |
| 372 | br = brInter; |
| 373 | } |
| 374 | |
| 375 | // otherwise the simple estimation used by upstream is used as a best guess fallback |
| 376 | if (!image.isIn(br)) { |
| 377 | br = fp.tr - fp.tl + fp.bl; |
| 378 | brOffset = PointF(0, 0); |
| 379 | } |
| 380 | |
| 381 | log(br, 3); |
| 382 | auto mod2Pix = Mod2Pix(dimension, brOffset, {fp.tl, fp.tr, br, fp.bl}); |
| 383 | |
| 384 | if( dimension >= Version::DimensionOfVersion(7, false)) { |
| 385 | auto version = ReadVersion(image, dimension, mod2Pix); |
| 386 | |
| 387 | // if the version bits are garbage -> discard the detection |
| 388 | if (!version || std::abs(version->dimension() - dimension) > 8) |
| 389 | return DetectorResult(); |
| 390 | if (version->dimension() != dimension) { |
| 391 | printf("update dimension: %d -> %d\n", dimension, version->dimension()); |
no test coverage detected