Skip to content

feat: unified anchor-based ID OCR + 16KB-aligned native deps (0.6.0)#160

Open
haklyray wants to merge 4 commits into
developfrom
feat/Improvement-of-OCR
Open

feat: unified anchor-based ID OCR + 16KB-aligned native deps (0.6.0)#160
haklyray wants to merge 4 commits into
developfrom
feat/Improvement-of-OCR

Conversation

@haklyray

@haklyray haklyray commented Jun 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Cuts 0.6.0 (next minor after 0.5.1). Three things:

  1. Unified OCR — merges "simple OCR" + "ID scan OCR" into one mode. Adds anchor-based ID scanning with per-country configs (Colombia, Venezuela, Nicaragua, Guatemala). Legacy free-text OCR (no scanIDOCRCountryOptions) is byte-for-byte unchanged.
  2. CameraX 1.3.1 → 1.4.2libimage_processing_util_jni.so was 4KB-aligned; 1.4.x ships 16KB. Required for SDK-35 Play uploads. Sentry is already on 8.0.0 here.
  3. Review fixes — see below.

Fixes since first review

Finding Fix
cameraProvider.unbindAll() ran before imageCapture.takePicture() → every manual capture failed silently Drop the unbind; activity lifecycle handles cleanup
Cell-level OCR spun a new Executors.newSingleThreadExecutor() per anchor and awaited each field for 1s (~5s analyzer-thread block on 5-field countries, plus leaked threads) Single lazy class-field executor; all cell-OCR tasks awaited in parallel under one 2s timeout
Demo app carried a commented-out signing block + unsigned release buildType Removed release block, signingConfigs, and the missingDimensionStrategy no-op. Demo is debug-only by direction.

Compatibility

  • OCRResult adds three default-valued fields. Source-compatible. Gson consumers unaffected; callers using OCRResult.copy(...) need a recompile.
  • Adds Modes.SCAN_ID_OCR("manual-ocr") already marked @Deprecated; unified Modes.OCR is the supported path.

Known limitations (follow-ups)

  • AAR output filenames changed: Kotlin DSL emits core-lib-{debug,release}.aar. The Capacitor plugin still vendors smartscannerlib-{debug,release}-1.0.aar — rename in your publish step.
  • AGP 4→9 + Gradle 6.5→9.1 + Kotlin 1.5→2.2 + JDK 8→21 land in the same commit as the OCR feature. Bisects on OCR drag in the tooling jump.
  • Venezuela Expiry Date regex ([0-9]{2}-[0-9]{4}) doesn't match the country-level dateFormat = "dd/MM/yyyy", so the field returns raw "12-2030". Needs a per-field dateFormat override (API change) to fix properly.
  • No unit tests added.
  • Dead code in Image.kt extensions (toGrayscale, adaptiveThreshold, etc.) and OCROptions.width/height.

Release

Tag 0.6.0 pushed @ 9f6f040. Commits:

  • 6f5ad4c feat: unified OCR with anchor-based ID scanning and country normalization
  • 0d0dde7 chore: bump CameraX to 1.4.2 for 16KB page alignment
  • 9f6f040 fix(ocr): parallel cell-OCR + drop unbind-before-takePicture + demo debug-only

haklyray added 4 commits June 2, 2026 15:59
…tion

- Upgrade Gradle build files to Kotlin DSL and update dependencies
- Merge simple OCR and ID scan OCR into a single unified OCR mode
- Add anchor-based field extraction with per-country configs (Colombia, Venezuela, Nicaragua, Guatemala)
- Normalize output fields to standard keys (documentNumber, firstName, lastName, dateOfBirth, gender)
- Parse dates and gender values per-country configuration
- Return both normalized fields and rawFields in OCR result
- Fix portrait rotation for ID scanning (hardcode 90° instead of device-reported)
- Add rect border color feedback (grey→blue→green) during scanning
- Add debug overlay toggle in example app settings (enabled by default)
- Remove table OCR from example app
CameraX 1.3.1 ships libimage_processing_util_jni.so with 4KB LOAD
segment alignment, which Google Play rejects for SDK-35 AABs on devices
with 16KB memory pages. 1.4.x publishes 16KB-aligned natives.

Sentry is already on 8.0.0 in this repo and does not need a change here;
the matching bump in smartscanner-capacitor's android/build.gradle is
landing on chore/16kb-deps in that repo so it picks up the same Sentry
8.x at consumer build time.
…ebug-only

Three review findings on top of feat/Improvement-of-OCR that should land
before tagging 0.6.0:

1. Manual capture regression. SmartScannerActivity's R.id.manual_capture
   handler called cameraProvider.unbindAll() *before* imageCapture.takePicture(),
   so the use case was always unbound when takePicture ran -- onError fired,
   onImageSaved never did, and the captured frame was silently dropped on every
   manual capture (MRZ manual, document capture, OCR manual). Drop the unbind.
   The activity's lifecycle handles cleanup on finish().

2. Cell-level OCR was creating a fresh single-thread executor per anchor
   inside the per-field loop (Executors.newSingleThreadExecutor() with no
   shutdown), and awaiting each field synchronously for up to 1s. For
   Nicaragua / Guatemala (5+ fields) that meant up to ~5s of analyzer-thread
   blocking per frame plus a handful of leaked non-daemon threads. Hoist the
   executor to a lazy class field, enqueue all cell-OCR tasks during the
   per-field sweep, then await all in parallel under one 2s overall timeout.
   Worst case wall time is now bounded by the slowest individual recognition,
   not their sum.

3. Demo app was carrying a commented-out signingConfig and an unsigned
   release build type. The demo isn't published; it ships debug-only.
   Removed the release block, the missingDimensionStrategy("variant","full")
   no-op (core-lib has no flavor dimension), and the dead signingConfig
   placeholder.
…on versions

CI was failing on this branch for three reasons:

1. ./gradlew assembleRelease tried to build :app:assembleRelease, but the
   demo app no longer has a release buildType (it's debug-only by direction).
   Switched to ./gradlew :core-lib:assembleRelease :app:assembleDebug so the
   library still produces a release AAR while the demo builds debug-only.

2. The runner default JDK is not 21, but the build pins
   JavaVersion.VERSION_21 / jvmTarget = "21". Added actions/setup-java@v4
   with temurin 21.

3. actions/checkout@v2, actions/cache@v2, actions/upload-artifact@v2 are
   end-of-life. Bumped to @v4. v4 also requires unique artifact names, so
   both uploads were renamed (core-lib-aar / demo-app-debug).

Also dropped the signing.properties echo step -- nothing in the build files
references it (legacy from when the demo app had a configured release
signingConfig).
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