indian_number_plate_ocr 🇮🇳 🚗

Pub Version Flutter Platform License: MIT

A powerful, high-precision Flutter & Dart package for OCR and automatic extraction of Indian vehicle registration number plates using Google ML Kit.

Designed specifically to handle the complexities of Indian number plates—including HSRP watermarks, two-line / multi-line layouts, side-by-side plates, Bharat (BH) series, Military vehicles, and common OCR visual misreads.


✨ Key Features

  • 🚘 Standard Civilian & Commercial Plates: Fully supports 2-letter State codes (DL, MH, KA, etc.), RTO codes (up to 3 characters including alphanumeric series like DL 8C), series letters, and 4-digit numbers.
  • 🇮🇳 Bharat (BH) Series: Native detection and extraction of Bharat series registrations (e.g., 22 BH 6517 A).
  • ⚔️ Military & Armed Forces Plates: Extracts Indian defense vehicle plates (e.g., 03D153874W, 14A1478T) while preventing false positive tails.
  • 🛡️ HSRP Watermark & Noise Filtering: Automatically strips out background text, camera timestamps, watermark text (IND, INDIA, BHARAT, SARKAR, SHUTTERSTOCK), and Hindi text (न भारत सरकार).
  • 📐 Multi-Line & Side-by-Side Plate Assembly: Intelligently groups 2-line or 3-line plates mounted on vehicles, and uses ordinal prefix-pairing to accurately separate multiple cars parked side-by-side without cross-contamination.
  • 🧠 Smart OCR Error Recovery: Automatically corrects common camera misreads:
    • Digit 0 vs letter O in RTO and series codes.
    • Digit 1 vs I / l / |.
    • Common state code visual confusions (e.g., reading WH as MH, SN as TN, HH as MH, OL/QL as DL).
    • Specific multi-letter misreads like FO $\rightarrow$ FQ, C0 $\rightarrow$ CQ, and OV $\rightarrow$ DV, while strictly preserving legitimate 'O' series vehicle registrations (e.g., DL 7C O 2314).

📦 Installation

Add indian_number_plate_ocr to your pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  indian_number_plate_ocr: ^1.0.0

Then run:

flutter pub get

🚀 How to Use

1. Basic Setup & Initialization

Import the package in your Dart file and initialize the IndianPlateOcrService:

import 'package:indian_number_plate_ocr/indian_number_plate_ocr.dart';

class MyScanner {
  final IndianPlateOcrService _ocrService = IndianPlateOcrService();

  void dispose() {
    // Remember to dispose the OCR service when your widget or controller is destroyed!
    _ocrService.dispose();
  }
}

2. Extracting from Camera or Image File (extractPlatesFromImage)

You can directly pass the path of a photo taken via image_picker or camera:

import 'package:image_picker/image_picker.dart';
import 'package:indian_number_plate_ocr/indian_number_plate_ocr.dart';

Future<void> scanCarPhoto() async {
  final picker = ImagePicker();
  final XFile? photo = await picker.pickImage(source: ImageSource.camera);
  
  if (photo != null) {
    final IndianPlateOcrService ocrService = IndianPlateOcrService();
    
    // Scans image using Google ML Kit and extracts validated Indian number plates
    final List<String> extractedPlates = await ocrService.extractPlatesFromImage(photo.path);
    
    print('Found Number Plates: $extractedPlates');
    // Example Output: ['DL7CQ1939', 'MH10DV3465']
    
    ocrService.dispose();
  }
}

3. Extracting from Raw OCR Text (extractPlatesFromText)

If you are already performing text recognition or receiving string data from a backend or scanner, use extractPlatesFromText:

final IndianPlateOcrService ocrService = IndianPlateOcrService();

const String rawTextFromCamera = '''
  IND DL 7C Q IND DL 7C O
  न भारत सरकार न भारत सरकार
  AA123456789 AA123456789
  1939 2314
''';

final List<String> plates = ocrService.extractPlatesFromText(rawTextFromCamera);

print(plates);
// Output: ['DL7CQ1939', 'DL7CO2314']

4. Extracting Raw OCR Text (extractRawText)

If you need the raw unedited string recognized by Google ML Kit from an image before plate validation:

final String? rawText = await ocrService.extractRawText(photo.path);
print('Raw OCR string: $rawText');

🏗️ Supported Plate Formats

Plate Category Sample Input Text Extracted Normalized Output
Standard Civilian WB 06 F 5977, KA 19 P 8488 WB06F5977, KA19P8488
Alphanumeric RTO DL 8C AC 4194, DL 7C Q 1939 DL8CAC4194, DL7CQ1939
Bharat (BH) Series 22 BH 6517 A 22BH6517A
Military / Defense ^03D153874W, KA 19 EQ 1316 E 03D153874W, KA19EQ1316
Two-Line / Stacked PB 10 GN
4497
PB10GN4497
Side-by-Side (2 Cars) IND DL 7C Q IND DL 7C O
1939 2314
DL7CQ1939, DL7CO2314

🛠️ Best Practices & Tips

  1. Camera Resolution & Focus: Ensure the number plate occupies a reasonable portion of the camera frame.
  2. Dispose Resource: Always call ocrService.dispose() inside your widget's dispose() method to release ML Kit native resources.
  3. Hot Restart in Flutter: If you modify OCR logic or update package dependencies in an actively running app, perform a Hot Restart (Shift + F5 or R) instead of Hot Reload so that the underlying service binaries reload into device memory.

📄 License

This project is licensed under the MIT License.

Libraries

indian_number_plate_ocr
Indian Vehicle Number Plate OCR and extraction library.