id_ocr
A robust and versatile Flutter plugin for CNIC (Computerized National Identity Card) detection and OCR, with specialized support for Urdu and Sindhi scripts.
This plugin combines the power of Google ML Kit for fast document detection and standard text recognition (English/Numeric) with Tesseract OCR as a fallback for complex Urdu and Sindhi scripts.
✨ Features
- Guided Card Scanning: Automatic document cropping and perspective correction using
google_mlkit_document_scanner. - Hybrid OCR Engine:
- Google ML Kit: High-speed extraction for English names, CNIC numbers, and dates.
- Tesseract fallback: Specialized support for Urdu and Sindhi script extraction (names, addresses).
- Advanced Data Extraction:
- Extracts Name, Father's Name, CNIC Number, and Date of Birth.
- Supports Gender extraction with normalization (
M/F,Male/Female, Urdu/Sindhi words). - Handles Date of Issue and Date of Expiry with specialized labels (e.g., "Valid Upto").
- Reliability Features:
- Memory-optimized scanner management to prevent native Android crashes (
SIG 9). - Automatic
image_pickerfallback if the native scanner activity fails. - Optional Manual Capture mode for full control over image sources.
- Memory-optimized scanner management to prevent native Android crashes (
- Customizable UI Flow: Easy-to-integrate services that can fit any design language.
- Micro-Animations: Built-in support for scanning animations and loaders.
🚀 Getting Started
1. Add Dependency
Add this to your package's pubspec.yaml file:
dependencies:
id_ocr: ^0.1.3
2. Platform Setup
Android
Update your android/app/build.gradle:
minSdkVersionshould be at least 21.
Add permissions to AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
3. Critical: Android Integration Tips
To avoid common crashes during integration (like No cropped images returned or SIG 9), ensure the following:
- Clean MainActivity: In
android/app/src/main/kotlin/.../MainActivity.kt, the class should simply extendFlutterActivity(). Avoid customonActivityResultoverrides unless they callsuper. - No Conflicting Plugins: Do not use
cunning_document_scanneralongsideid_ocr, as they conflict during the Activity Result delivery. - Hardware Acceleration: Ensure
android:hardwareAccelerated="true"is set (default in Flutter) to allow ML Kit to process images.
iOS
Add the following to your ios/Runner/Info.plist:
<key>NSCameraUsageDescription</key>
<string>We need access to your camera to scan the CNIC.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>We need access to your gallery to upload the CNIC image.</string>
🛠 Usage
Integrating id_ocr is straightforward. You can use the ScannerService for capturing images and OcrService for processing them.
Simple Example
import 'package:id_ocr/id_ocr.dart';
// 1. Initialize services
final ScannerService _scannerService = ScannerService();
final OcrService _ocrService = OcrService();
// 2. Scan and Process
Future<void> scanAndExtract() async {
// Capture image using document scanner
final String? path = await _scannerService.scanDocument();
if (path != null) {
// Process the image for the front side
CnicModel extractedData = await _ocrService.processImage(path, isFront: true);
print('Name: ${extractedData.name}');
print('CNIC: ${extractedData.cnicNumber}');
}
}
Data Model
The CnicModel contains the following fields:
name: Full name of the individual.fatherName: Father's or Husband's name.cnicNumber: 13-digit identity number.gender: Normalized Gender ("Male" or "Female").dob: Date of Birth.issueDate: Date of card issue.expiry: Card expiry date.address: Residential address (typically from the back side).
🏗 Guided Scan & Extraction Screen
The plugin is designed to support a seamless "Guided Scan" experience similar to the one in the example app:
- Instruction: Show a screen explaining what to scan (Front/Back).
- Scanner: Call
ScannerService.scanDocument(). - Extraction View: Immediately after the scanner returns, update your UI to show a loader (e.g., "Extracting Details...") while calling
OcrService.processImage(). - Repeat: Repeat for the back side if necessary.
// Example of the Guided Flow
void onScanTapped() async {
setState(() => isExtracting = false);
// 1. Scan Front
final path = await _scannerService.scanDocument();
if (path == null) return;
// 2. Show Extraction UI
setState(() => isExtracting = true);
// 3. Process OCR
final data = await _ocrService.processImage(path, isFront: true);
// 4. Update UI
setState(() {
extractedData = data;
isExtracting = false;
});
}
Check the example folder for a full implementation using GetX and custom animations.
📜 License
Distributed under the MIT License. See LICENSE for more information.
🤝 Contributing
Contributions are welcome! Feel free to open issues or submit pull requests to improve the OCR accuracy or add new features.
- Fork the Project
- Create your Feature Branch (
git checkout -b feature/AmazingFeature) - Commit your Changes (
git commit -m 'Add some AmazingFeature') - Push to the Branch (
git push origin feature/AmazingFeature) - Open a Pull Request