Skip to main content

eas_passport_ocr 0.2.5 copy "eas_passport_ocr: ^0.2.5" to clipboard
eas_passport_ocr: ^0.2.5 copied to clipboard

On-device passport MRZ recognition for Flutter Android and iOS.

eas_passport_ocr · Flutter SDK #

Recognize TD3 passport information on Android and iOS. Images are processed on the device and are not uploaded to an OCR server.

The SDK reads the two-line machine-readable zone (MRZ) and returns core passport fields, rawMrz, and isExpired, using the same result schema as the JavaScript SDK. It does not read Chinese text or extract the issue date, place of issue, or issuing authority from the printed page.

Current version: 0.2.5, available on pub.dev. A source distribution is also available as eas_passport_ocr-flutter-0.2.5.tar.gz.

License #

Copyright belongs to Easit. This package uses a proprietary Evaluation and Commercial License, not MIT or another open-source license.

Internal testing, evaluation, and modifications for evaluation are permitted. Production deployment, commercial use, publicly distributed applications or services, and redistribution of source or compiled code require prior, separate written authorization from Easit. Downloading the package from pub.dev does not grant a commercial license. Third-party dependencies remain subject to their own terms.

Installation #

Requires Flutter 3.44 or later and Dart 3.12 or later. Add the pinned version to your app's pubspec.yaml:

dependencies:
  eas_passport_ocr: 0.2.5

Then run:

flutter pub get

For a local source distribution, extract it and use a path dependency instead:

dependencies:
  eas_passport_ocr:
    path: ../eas_passport_ocr

The default engine uses the community-maintained google_mlkit_text_recognition: 0.17.1 plugin. Native recognition models must be bundled with the app.

Quick start #

import 'dart:convert';
import 'package:eas_passport_ocr/eas_passport_ocr.dart';

Future<String> scanPassport(String localImagePath) async {
  final sdk = EasPassportOcr(); // Distortion correction is enabled by default.
  try {
    final result = await sdk.recognizeResult(localImagePath);
    if (result.containsKey('code')) {
      // Use code, msg, and suggestion to guide the user through a retry.
    } else {
      // Populate your form and ask the user to verify the passport details.
    }
    return jsonEncode(result);
  } finally {
    await sdk.dispose();
  }
}

Pass a local file path, not an HTTP or file:// URL. The host app handles image selection, camera and photo-library permissions, and any optional cropping. Capture the complete page with both MRZ lines visible.

An instance can be reused for sequential scans. Starting another scan or disposing of the instance while recognition is running reports BUSY. Wait for recognition to finish before calling dispose(). Repeated disposal is safe; scanning with a disposed instance reports DISPOSED.

Platform setup #

Android #

  • The plugin requires minSdk 21 and compileSdk 36 or later. Use the targetSdk from your Flutter template. If Flutter or another dependency requires higher values, use those values.
  • Keep the plugin's bundled-model dependency, com.google.mlkit:text-recognition:16.0.1. Do not replace it with the Play Services variant that downloads models dynamically.

iOS #

  • Requires a deployment target of iOS 15.5 or later and Xcode 15.3 or later.
  • Set the deployment target in both Runner and the Podfile. Exclude unsupported 32-bit architectures as described in the ML Kit plugin documentation.
  • The default plugin includes the Latin text model; no additional Chinese-language Pod is needed.
  • If using the camera/gallery example, configure NSCameraUsageDescription and NSPhotoLibraryUsageDescription in Info.plist.

Image OCR with the default engine is not supported on Flutter Web, macOS, Windows, or Linux and returns UNSUPPORTED_PLATFORM. The standalone parsePassportMrz function does not invoke native OCR.

API and results #

Recognition #

  • recognizeResult(path) returns a JSON-serializable Map<String, dynamic> containing either passport fields or a three-field error.
  • recognize(path) returns a PassportResult and throws PassportOcrException on failure. Call toJson() on the result or exception to serialize it.
  • EasPassportOcr(correctDistortion: false) disables geometric correction and the upscaling, line-box, and orientation retries. Whole-page repeated confirmation still runs.

Successful result #

A successful result contains exactly these 11 fields, without a success flag or data wrapper:

Field Meaning
documentType Document type from the MRZ.
issuingCountry Issuing-state code from the MRZ.
surname Surname in MRZ transliteration.
givenNames Given names in MRZ transliteration.
passportNumber Passport number.
nationality Nationality code from the MRZ.
birthDate Date of birth, formatted as YYYY-MM-DD.
sex M, F, or X.
expiryDate Expiration date, formatted as YYYY-MM-DD.
rawMrz Two normalized MRZ lines separated by a newline.
isExpired Expiration status based on the device's local date.

A passport is not considered expired on its expiration date. toJson() recalculates isExpired rather than retaining a stale value. MRZ dates contain two-digit years, so the inferred century must be checked against the original passport.

If you already have OCR text, parse it without invoking the recognition model:

final result = parsePassportMrz('$line1\n$line2');
final expired = result.isExpired;
final data = result.toJson();

Failed result #

A failure contains only three string fields: code, msg, and suggestion. Use result.containsKey('code') to detect it. suggestion is a single string, not an array.

The SDK currently returns user-facing error messages in Chinese. Translating this README does not change the runtime language. The following is an example of the actual output:

{
  "code": "MRZ_INVALID",
  "msg": "未能识别清楚,照片可能存在反光、扭曲、缺角或文字截断。",
  "suggestion": "请避开反光、摊平护照,完整拍入资料页及四角,确保底部两行字母和数字清晰、未被截断。"
}

In English, this says that recognition was unsuccessful and the photo may have glare, distortion, missing corners, or cut-off text. It advises avoiding glare, flattening the passport, capturing the entire page and its corners, and keeping both MRZ lines clear and complete.

Code Meaning
INVALID_INPUT Invalid image path or input.
UNSUPPORTED_PLATFORM The default image OCR engine is unavailable on this platform.
BUSY A recognition operation is already running.
DISPOSED The instance has been disposed of.
MRZ_NOT_FOUND No usable MRZ was found.
MRZ_INVALID The MRZ could not be reliably confirmed and validated.
OCR_FAILED Local recognition failed; check the image, permissions, and native engine configuration.

When there is image evidence, messages describe suspected glare, bending or character-size variation, text near an image edge, or insufficient character resolution. When the cause cannot be narrowed down, the message lists glare, distortion, missing corners, and cut-off text as possible causes.

These are conservative diagnostic rules, not a classifier calibrated on a real-world dataset. They do not detect all four page corners or independently classify blur. Text near an image edge does not prove that a physical corner is missing. Image diagnostics run only with the default engine; custom text engines provide text for MRZ validation.

Failure JSON does not contain a success flag, nested error, diagnostics, measurement data, cause lists, unvalidated identity fields, images, or stack traces.

Migrating from 0.1.x: replace checks for a success flag and nested error messages with the three-field schema above. The throwing recognize() API remains available. Dart's PassportOcrException.toJson() and JavaScript's PassportOcrError.toJSON() use the same three-field error schema.

Whole-page recognition and confirmation #

The default engine accepts a complete passport page without a manually selected MRZ region. It starts with local ML Kit recognition and repeats reads on normalized and contrast-adjusted images. When needed, it locates the two character rows, preserves natural character proportions, straightens curved baselines, and tries per-character correction. Long rows are scaled to fit the output canvas without cutting off their ends.

Version 0.2.3 incorporates repeated-read confirmation and conflict checks from the JavaScript SDK. Both rows require support from different processing attempts. Before accepting a corrected whole-row result, the engine rereads the second row using another geometric sampling method. Conflicting passport numbers or dates that each pass validation cause rejection.

The SDK does not guess replacements such as O/0, insert missing characters, truncate extra characters, or relax checksum requirements. Stricter confirmation may reject photos accepted by earlier versions. Repeated agreement and passing checksums do not guarantee every field is correct or authenticate a document; users should verify results against the original passport.

Fallbacks include bounded upscaling, rotation, and crops based on ML Kit line boxes. Each scan makes at most 80 native OCR calls and stops early once a result is confirmed. Difficult images can take longer. Local illumination correction and shear compensation can help where character strokes remain visible, but cannot recover information erased by glare or cut off from the image. Arbitrary distortion recovery is not guaranteed.

Decoding, scaling, geometric processing, and encoding derived images run in a background isolate using compute. Full-page copies, crops, and line images are stored in a temporary directory and removed on success or error, without modifying the source image. Forced process termination can prevent cleanup. Do not back up or upload these temporary files.

Custom OCR engine #

Implement PassportTextEngine.recognizeLines() and close(), then pass the engine to EasPassportOcr(engine: yourEngine). Return text lines in reading order.

A custom engine is responsible for preprocessing and repeated-read confirmation. The SDK continues to locate, parse, and validate the MRZ and produce the common result schema. It does not read virtual paths supplied to custom engines or perform the default engine's image diagnostics.

Example app and verification #

example/lib/main.dart provides a camera/gallery screen and JSON copying. The distribution does not include generated Android/iOS project scaffolding. Create it with:

cd example
flutter create --platforms=android,ios --project-name passport_ocr_example .
flutter pub get
# Complete the platform and permission setup above, then:
flutter run

Run package checks from the package directory:

flutter pub get
flutter analyze
flutter test

Tests use fictional public fixtures, synthetic distorted characters, and native-channel test doubles. They cover the result schema, repeated confirmation, checksum collisions, geometry, rotation and line-box fallbacks, retry limits, instance reuse, temporary-file cleanup, and resource disposal.

Android/iOS OCR acceptance testing on real devices is still pending. Mocked ML Kit responses do not establish real-photo recognition accuracy. Browser results cannot be treated as Flutter results because the engines differ. Test offline on your target devices to verify bundled models, permissions, and recognition quality. The source archive excludes native engines and models, so its size is not the increase in your app's installation size.

Dependencies #

Third-party dependencies and native ML Kit components are governed by their own terms. This package does not include the Tesseract engine or OCR-B model used by the JavaScript SDK.

0
likes
0
points
327
downloads

Publisher

unverified uploader

Weekly Downloads

On-device passport MRZ recognition for Flutter Android and iOS.

Topics

#ocr #passport #mrz

License

unknown (license)

Dependencies

flutter, google_mlkit_text_recognition, image

More

Packages that depend on eas_passport_ocr