Skip to content

[MS-1421] Creating OCR framework to work with the OCR readouts with text filter and spatial constraints#1643

Merged
alexandr-simprints merged 10 commits into
mainfrom
MS-1421-create-ocr-framework-for-intuitive-fields-extraction
May 5, 2026
Merged

[MS-1421] Creating OCR framework to work with the OCR readouts with text filter and spatial constraints#1643
alexandr-simprints merged 10 commits into
mainfrom
MS-1421-create-ocr-framework-for-intuitive-fields-extraction

Conversation

@alexandr-simprints
Copy link
Copy Markdown
Contributor

@alexandr-simprints alexandr-simprints commented Apr 27, 2026

JIRA ticket
Will be released in: 2026.2.0

Notable changes

Adding a way of extracting text fields from scanned ID cards by combining text matching with spatial navigation. This is required because the non-credential fields (name, date of birth, expiry date, etc.) cannot be reliably extracted using only pattern matching alone. The reader allows extraction rules to be expressed as human-readable queries:

// Spatial navigation
val dateOfBirth = reader.find {
    isBelow { containsText("date of birth") }
    matchesPattern(Regex("your-regex-pattern"))
    isAbove { containsText("expiry date") }
}

// Simple text matching pattern
val credential = ocrReader.find { matchesPattern(NHIS_PATTERN) }

Custom OCR models

ML Kit's Text class is converted into custom OcrTextModel. This keeps all extraction logic free of ML Kit dependencies and makes it possible to unit test.

Column-aware spatial filtering

Since the fields of interest on the documents that we're scanning are located in their respective columns, only isBelow and isAbove are used. However, there might be situations where two columns are located right next to each other, and in order to enforce horizontal column boundaries, a candidate line is only returned if its left edge falls within the horizontal bounds of the anchor.

If a column-aware spatial filtering is not applied then for a document layout as below

Date of birth            Date of expiry
11/11/1999                12/12/2028 

the following query

val dateOfBirth = reader.find {
    isBelow { containsText("date of birth") }
}

might equally return 11/11/1999 or 12/12/2028. We want to avoid such scenarios, and explicitly check that the value's boundaries below field of interest (date of birth) start within the 'date of birth' width.

image

The drawing above demonstrates the logic for determining whether a line is within anchor's column. If the line's top-left X coordinate is between anchor's X_left and X_right, then the element is considered in the same column

@cla-bot cla-bot Bot added the ... label Apr 27, 2026
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces an OCR querying framework for the external credential scan flow, enabling extraction of ID-card fields by combining text matching with spatial constraints, and refactors existing Ghana credential selectors to use the new reader/model abstraction.

Changes:

  • Added a custom OCR model (OcrText/OcrLine) and a query DSL (OcrReader + OcrQueryScope) for text + spatial filtering.
  • Refactored Ghana NHIS / Ghana ID credential selection to return the matched OCR line instead of a boolean.
  • Updated credential coordinate detection to use the new OCR reader/model pipeline.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
feature/external-credential/.../GhanaNhisCardOcrSelectorUseCase.kt Switches from regex boolean check to selecting an OcrLine via OcrReader.
feature/external-credential/.../GhanaIdCardOcrSelectorUseCase.kt Switches from regex boolean check to selecting an OcrLine via OcrReader.
feature/external-credential/.../GetCredentialCoordinatesUseCase.kt Builds an OcrReader from ML Kit output and returns detected credential bounds from the selected OcrLine.
feature/external-credential/.../reader/OcrReader.kt Adds reader entry point for executing OCR queries.
feature/external-credential/.../reader/OcrQuery.kt Implements the query scope and spatial/text filters used by the OCR reader.
feature/external-credential/.../reader/OcrModel.kt Adds ML Kit–independent OCR domain model used for extraction.
feature/external-credential/.../reader/OcrBuilder.kt Converts ML Kit Text output into the custom OCR model.
feature/external-credential/.../model/BoundingBox.kt Changes toBoundingBox() to accept nullable Rect.

@alexandr-simprints alexandr-simprints marked this pull request as ready for review April 29, 2026 08:44
…his allows to isolate ML kit dependencies in tests
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 11 comments.

Comments suppressed due to low confidence (1)

feature/external-credential/src/main/java/com/simprints/feature/externalcredential/screens/scanocr/usecase/GetCredentialCoordinatesUseCase.kt:46

  • This suspend use case catches Exception, which will also catch and swallow CancellationException, preventing cooperative coroutine cancellation. Re-throw CancellationException (or catch a narrower exception type) before logging/returning null.
        } catch (e: Exception) {
            Simber.e("OCR failed for $documentType", e, tag = MULTI_FACTOR_ID)
            null

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented May 5, 2026

@alexandr-simprints alexandr-simprints merged commit 6bc8088 into main May 5, 2026
14 checks passed
@alexandr-simprints alexandr-simprints deleted the MS-1421-create-ocr-framework-for-intuitive-fields-extraction branch May 5, 2026 14:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants