fix(scanner): bring the detector back in line with Android, on matching OpenCV - #630
Merged
Conversation
Three divergences between the two hand-maintained copies of the C++ detector, all of them iOS being behind: - The candidate prune dropped an ellipse whenever a *smaller* one sat within 50px of it. The centre badge is a disc with the logo glyph knocked out, and the glyph's dot is itself a clean ellipse near the badge centre, so past a certain on-screen size the badge and the dot land in the same bucket and the forward-only comparison always discards the badge -- the only candidate that can yield finder points. Require the two areas to be within 2x of each other, so the rule prunes what it was written for (one physical circle fitted twice, from the inner and outer edge of its stroke) and nothing else. Same fix as code-android-app#1306. - The contour prune indexed the ellipse mask with contour points without checking them against the mask bounds. Android bounds-checks the same lookup. - build_opencv.sh could not run on a current Xcode: OpenCV still defaults IPHONEOS_DEPLOYMENT_TARGET to 9.0, which Xcode 16+ rejects, and still passes -fembed-bitcode / -bitcode_verify, which have been dead since Xcode 14. Pass --iphoneos_deployment_target and --disable-bitcode.
…mework Android has been on OpenCV 4.12.0 for a while; iOS was still on 4.10.0. Same detector source, two different OpenCV versions, is a bad place to debug a parity bug from -- when Android's 4.12 reproduced iOS's 4.10 failures on the same frames it was clear the version was not the variable, but that is only knowable after the fact. Line them up. Rebuilt with the (now working) build_opencv.sh: 49MB, arm64 device plus arm64/x86_64 simulator, same 13 excluded modules, device slice at minos 15.0. The generated Info.plist hardcoded MinimumOSVersion 12.0, which no longer matched the binary -- it now follows the deployment target. Also deletes opencv2.xcframework.backup.20251202_202647, 427 files and 100MB of a framework nothing references, committed by an earlier run of the same script. The script backs up before installing, so this is recoverable by rebuilding.
bmc08gt
added a commit
that referenced
this pull request
Aug 23, 2026
The 4.12.0 rebuild in #630 was made with the only Xcode on the build machine, a 27.0 beta, so both framework slices carry LC_BUILD_VERSION sdk 27.0. The App Store rejects any binary stamped above the newest released SDK (ITMS-90512), which took out 2026.8.3 build 500 — and would take out every release until fixed, since this sits on main. Restamp both slices to 26.1, the sdk the shipping 2026.8.2 framework carried, with vtool. Nothing else in the binary changes and the frameworks are unsigned, so there is nothing to re-sign. Also refuse to build the framework at all under a too-new SDK. This script's output is committed and shipped as-is, so a beta Xcode here surfaces as a failed submission weeks later, long after whoever ran it has moved on.
This was referenced Aug 24, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Brings the iOS copy of the C++ detector back in line with Android, and lines up the OpenCV version underneath it.
The detector bug
The candidate prune dropped an ellipse whenever a smaller one sat within 50px of it:
The centre badge is a disc with the logo glyph knocked out by the even-odd rule, so the glyph's round dot is itself a clean ellipse sitting ~0.08·D from the badge centre. Past a certain on-screen size both land in the same 50px bucket, and this forward-only comparison always discards the larger one — the badge, the only candidate that can produce finder points. The search then runs from the dot and finds 1 finder point instead of 9.
The rule exists to collapse one physical circle fitted twice, from the inner and outer edge of its stroke. Those two fits are comparable in area, so requiring the areas to be within 2× of each other keeps the intended behaviour and stops it eating nested features.
This is a hard failure band, not a slowdown: hold the phone too close and the code will not decode until you back off.
Also
build_opencv.shcould not run on a current Xcode at all: OpenCV still defaultsIPHONEOS_DEPLOYMENT_TARGETto 9.0 (Xcode 16+ rejects it outright) and still passes-fembed-bitcode/-bitcode_verify, dead since Xcode 14. The generatedInfo.plistalso hardcodedMinimumOSVersion 12.0.minos 15.0, well under CodeScanner's own iOS 18Package.swiftfloor.opencv2.xcframework.backup.20251202_202647— 427 files, 100MB of a framework nothing references, committed by an earlier run of the same script.Result
FlipcashTests/CodeScanSweepTestson iPhone 17 Pro, OpenCV 4.12.0, identical in both runs except the one prune expression:Full suite green: 4/4.
Same fix as code-payments/code-android-app#1306.