From f495296811cf3df511b5773ba6a84d7fabcfd383 Mon Sep 17 00:00:00 2001 From: Brandon McAnsh Date: Fri, 21 Aug 2026 22:43:57 -0400 Subject: [PATCH] perf(scanner): drop two full-frame adaptive thresholds that nothing reads 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. --- .../kik/scanner/src/main/cpp/scan/scanner.cpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/vendor/kik/scanner/src/main/cpp/scan/scanner.cpp b/vendor/kik/scanner/src/main/cpp/scan/scanner.cpp index fb37cbad9..937def521 100644 --- a/vendor/kik/scanner/src/main/cpp/scan/scanner.cpp +++ b/vendor/kik/scanner/src/main/cpp/scan/scanner.cpp @@ -417,23 +417,6 @@ bool detectKikCode(Mat &greyscale, Mat *out_progress, uint32_t device_quality, u Mat whitish; Mat blackish; - // --- START OF EDIT --- - // we switch to an inverted scheme (dark is high, light is low) if the - // center ellipse is dark, but we don't want to compute the extra threshold everytime - // so we only do this when needed. - // - // Using adaptive thresholding is more robust to lighting changes than a global threshold. - // It calculates a threshold for smaller regions, making it less susceptible to shadows or glare. - // A block size of 11 or higher is a good starting point and must be an odd number. - // The constant 'C' (here, 5) is subtracted from the mean, which helps in finding features. - - // For finding dark features on a light background. - adaptiveThreshold(greyscale, blackish, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY_INV, 21, 5); - - // For finding light features on a dark background. - adaptiveThreshold(greyscale, whitish, 255, ADAPTIVE_THRESH_GAUSSIAN_C, THRESH_BINARY, 21, 5); - // --- END OF EDIT --- - // we switch to an inverted scheme (dark is high, light is low) if the // center ellipse is dark, but we don't want to compute the extra threshold everytime // so we only do this when necessary