Skip to content

perf(scanner): drop two full-frame adaptive thresholds that nothing reads - #1307

Merged
bmc08gt merged 1 commit into
fix/scanner-badge-dot-candidate-prunefrom
perf/scanner-drop-dead-adaptive-threshold
Aug 22, 2026
Merged

perf(scanner): drop two full-frame adaptive thresholds that nothing reads#1307
bmc08gt merged 1 commit into
fix/scanner-badge-dot-candidate-prunefrom
perf/scanner-drop-dead-adaptive-threshold

Conversation

@bmc08gt

@bmc08gt bmc08gt commented Aug 22, 2026

Copy link
Copy Markdown
Collaborator

detectKikCode opened with a pair of full-frame 21×21 Gaussian adaptive thresholds:

// --- START OF EDIT ---
adaptiveThreshold(greyscale, blackish, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 21, 5);
adaptiveThreshold(greyscale, whitish,  255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY,     21, 5);
// --- END OF EDIT ---

Neither result is ever read.

  • whitish is unconditionally overwritten before anything touches it, by the global threshold(greyscale, whitish, 170, 255, THRESH_BINARY) a few dozen lines down.
  • blackish is only read on the inverted-code path (!check_high), and that path recomputes it itself, lazily, behind blackish_created — with a different algorithm (ADAPTIVE_THRESH_MEAN_C, at the quality-dependent width rather than a hardcoded 21).

So every analyzed frame paid for two full-frame adaptive thresholds whose output was discarded.

Cost, measured

S25 Ultra, 30 iterations per case, native detect only (no plane conversion), through the real render path:

frame code present before after
1280×720 yes 10.44 ms 4.99 ms
1280×720 no 14.30 ms 8.90 ms
1920×1080 yes 8.27 ms 2.79 ms
1920×1080 no 10.01 ms 4.47 ms

~5.5 ms off every frame, hit or miss — the "no code" rows are the ones that matter most, since that is what the analyzer pays while the user is still lining the phone up. This is larger than the luminance-plane fast path it stacks on top of.

The instrumented sweep still decodes 18/18 and stride parity is unchanged, which is what deleting values nothing consumes should look like.

iOS never carried this block.

Stacked on #1306.

…eads

detectKikCode opened with a pair of 21x21 Gaussian adaptive thresholds into
`whitish` and `blackish`. Neither result is ever read:

  - `whitish` is unconditionally overwritten a few dozen lines later by the
    global `threshold(greyscale, whitish, 170, 255, THRESH_BINARY)` before
    anything touches it.
  - `blackish` is only read on the inverted-code path (`!check_high`), and that
    path recomputes it itself, lazily, behind `blackish_created` -- with a
    different algorithm (ADAPTIVE_THRESH_MEAN_C at the quality-dependent width).

So the block was two full-frame adaptive thresholds per analyzed frame, thrown
away every time. Measured on an S25 Ultra over 30 iterations per case:

  1280x720   code present   10.44ms -> 4.99ms
  1280x720   no code        14.30ms -> 8.90ms
  1920x1080  code present    8.27ms -> 2.79ms
  1920x1080  no code        10.01ms -> 4.47ms

That is ~5.5ms off every frame the analyzer processes, hit or miss -- larger
than the luminance-plane fast path it stacks on. The instrumented sweep still
decodes 18/18 and stride parity is unchanged, which is what you would expect
from deleting values nothing consumes.

iOS never carried this block.
@github-actions github-actions Bot added the area: scanner QR/Kikcode scanning, camera label Aug 22, 2026
@bmc08gt
bmc08gt merged commit 464b2c9 into fix/scanner-badge-dot-candidate-prune Aug 22, 2026
3 checks passed
@bmc08gt
bmc08gt deleted the perf/scanner-drop-dead-adaptive-threshold branch August 22, 2026 02:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: scanner QR/Kikcode scanning, camera

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant