Skip to content

Fix live scanner freezing/stutter and clean up detection overlay (iOS + Android) - #1

Merged
komodgn merged 1 commit into
masterfrom
fix/scanner-freeze-and-overlay
Aug 31, 2026
Merged

komodgn merged 1 commit into
masterfrom
fix/scanner-freeze-and-overlay

Conversation

@komodgn

@komodgn komodgn commented Aug 31, 2026 •

Copy link
Copy Markdown
Owner

Summary

Fixes several issues in the live clover scanner across both iOS and Android. The main fix is the iOS camera preview freezing for seconds at a time during detection; along the way this also cleans up shared-UI issues (box tracking, fps display) and an Android optimization.

Problems

  • iOS: camera preview periodically froze for several seconds while detecting clovers
  • Shared: detection boxes jumped between updates instead of tracking the clover smoothly
  • Shared: the fps chip rendered a literal %d fps

Root cause (iOS freeze)

The CoreML model has NMS baked in (nms=True), which keeps it off the Neural Engine and runs inference on the GPU. That contended with the GPU-bound camera preview compositing, so every inference stalled the preview.

Changes

iOS — preview freeze (CameraScanner.ios.kt)

  • Pin inference to the Neural Engine with computeUnits = cpuAndNeuralEngine, freeing the GPU for the preview (the core fix)
  • Call onResult directly from the inference queue instead of dispatching a Kotlin lambda to the GCD main queue every frame, which had been accumulating GC roots and triggering stop-the-world pauses
  • Load the Vision request off the main thread; use an atomic busy flag and cache the request list / options map to avoid per-frame allocations
  • Raise the preview preset to 720p (with fallback) and the inference rate to ~10/sec
  • Raise the Kotlin/Native GC target heap (build.gradle.kts)

Shared UI (ScanScreen.kt)

  • Interpolate detection boxes at display refresh rate so they glide after the clover instead of jumping between inference updates
  • Mark CloverDetector @stable and memoize the frame callback so state updates don't force the CameraScanner (and its UIKitView) to recompose
  • Format the fps chip in Kotlin to fix the literal %d fps; drop the now-unused fps_format string resource

Android (CloverDetector.android.kt, CameraScanner.android.kt)

  • Pass the camera Bitmap straight into ONNX inference, skipping the JPEG encode/decode round-trip

… + Android)

Several issues in the live camera scanner, across both platforms.

iOS — preview froze for seconds at a time (CameraScanner.ios.kt):
- Root cause: CoreML inference ran on the GPU (the model has NMS baked in,
  which keeps it off the Neural Engine), contending with the GPU-bound camera
  preview compositing. Force inference onto the Neural Engine + CPU
  (computeUnits = cpuAndNeuralEngine) so the GPU is free for the preview.
- Call onResult directly from the inference queue instead of dispatching a
  Kotlin lambda to the GCD main queue every frame, which had been accumulating
  GC roots and triggering stop-the-world pauses.
- Load the Vision request off the main thread; use an atomic busy flag and
  cache the request list / options map to avoid per-frame allocations.
- Raise inference rate to ~10/sec now that it no longer stalls the preview,
  and bump the preview preset to 720p (with fallback).
- Raise the Kotlin/Native GC target heap (build.gradle.kts) so it pauses the
  app less often under the camera + ML workload.

Shared UI — boxes jumped and the fps chip was broken (ScanScreen.kt):
- Interpolate detection boxes at display refresh rate so they glide after the
  clover instead of jumping between inference updates. (both platforms)
- Mark CloverDetector @stable and memoize the frame callback so state updates
  don't force the CameraScanner (and its UIKitView) to recompose. (both)
- Fix the fps chip showing a literal "%d fps" by formatting in Kotlin; drop the
  now-unused fps_format string resource. (both)

Android (CloverDetector.android.kt, CameraScanner.android.kt):
- Skip the JPEG encode/decode round-trip by passing the camera Bitmap straight
  into ONNX inference.
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 55a4642b-09f4-40f9-a8aa-babf017503ea


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@komodgn
komodgn merged commit e46dcc8 into master Aug 31, 2026
3 checks passed
@komodgn
komodgn deleted the fix/scanner-freeze-and-overlay branch August 31, 2026 15:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant