kaderkita_ocr
On-device Flutter OCR for Indonesian KTP and Kartu Keluarga (KK).
Scanners capture from the camera, run Google ML Kit Text Recognition locally, and return structured fields. Optional debug mode attaches raw OCR text, confidence, ROI/crop previews, and step-by-step pipeline images for tooling.
Privacy: all OCR runs on-device. No images or text are uploaded by this package.
Requirements
| Flutter | >=3.38.0 |
| Dart | >=3.10.0 |
| Platforms | Android, iOS |
Native pieces come from transitive plugins: camera and
google_mlkit_text_recognition.
Install
dependencies:
kaderkita_ocr: ^0.3.0
Platform setup
Android — camera permission in AndroidManifest.xml:
<uses-permission android:name="android.permission.CAMERA"/>
iOS — camera usage string in Info.plist:
<key>NSCameraUsageDescription</key>
<string>Camera is used to scan KTP and Kartu Keluarga on-device.</string>
Quick start
import 'package:kaderkita_ocr/kaderkita_ocr.dart';
Future<void> scanKtp(BuildContext context) async {
final result = await Navigator.push<KtpScanResult>(
context,
MaterialPageRoute(
builder: (_) => const KtpScanner(
// debug: true → attach ScanDebug (raw text, ROIs, pipeline images)
config: KaderkitaOcrConfig(debug: false),
),
),
);
if (result == null) return;
print(result.data.nik);
print(result.data.nama);
}
Same pattern for KK:
final result = await Navigator.push<KkScanResult>(
context,
MaterialPageRoute(builder: (_) => const KkScanner()),
);
Public API
| Type | Role |
|---|---|
KtpScanner / KkScanner |
Full-screen camera scanners; pop with a result |
KaderkitaOcrConfig |
debug, autoCapture |
KtpScanResult / KkScanResult |
data + optional debug |
KtpData / KkData / KkMember |
Structured fields |
ScanDebug / RoiPreview / ImagePipelineStep |
Debug payload |
ScanDebugPanel / ImagePipelineViewer |
Optional debug UI widgets |
NikValidator |
Structural NIK checks |
Internals (OcrService, parsers, Monte Carlo tools) live under
lib/src/ and are not part of the stable public API.
Data model / output
Each scanner pops a result whose data holds the structured fields (always
present) and an optional debug payload (only when config.debug == true).
Every field is nullable — OCR may not recover it.
KtpData (KtpScanResult.data)
| Field | Type | toJson key |
|---|---|---|
nik |
String? |
nik |
nama |
String? |
nama |
tempatLahir |
String? |
tempat_lahir |
tanggalLahir |
String? |
tanggal_lahir (DD-MM-YYYY) |
jenisKelamin |
String? |
jenis_kelamin |
confidence |
double? |
confidence |
rawText |
String? |
— (in-memory only) |
Helper: isComplete (has nik, nama, and tanggalLahir).
KkData (KkScanResult.data)
| Field | Type | toJson key |
|---|---|---|
nomorKk |
String? |
nomor_kk |
namaKepalaKeluarga |
String? |
nama_kepala_keluarga |
alamat |
String? |
alamat |
rtRw |
String? |
rt_rw |
kodePos |
String? |
kode_pos |
desaKelurahan |
String? |
desa_kelurahan |
kecamatan |
String? |
kecamatan |
kabupatenKota |
String? |
kabupaten_kota |
provinsi |
String? |
provinsi |
members |
List<KkMember> |
members (each via toFieldMap()) |
confidence |
double? |
confidence |
rawText |
String? |
— (in-memory only) |
Helper: hasMembers.
KkMember (a row of the family table)
All fields are String? except the flag: no, namaLengkap, nik,
jenisKelamin, tempatLahir, tanggalLahir, agama, pendidikan,
jenisPekerjaan, golonganDarah, and isKepalaKeluarga (bool).
isKepalaKeluarga marks the head of family — the member whose name matches the
extracted namaKepalaKeluarga (exact, else nearest by Levenshtein). toFieldMap()
returns Map<String, dynamic> with snake_case keys (nama_lengkap, nik,
is_kepala_keluarga, …). Helpers: hasIdentity, isEmptyRow.
golonganDarahis retained in the model and output (golongan_darah) but is not scanned by default, so it is typicallynull.
Debug mode
const KaderkitaOcrConfig(debug: true)
When enabled, result.debug includes:
rawText— OCR text dumpconfidence— aggregate score when availablerois— bracket / column crop previewspipelineSteps— labeled images for each preprocess / layout stage
Show them with ScanDebugPanel or ImagePipelineViewer.
When debug is false (default), heavy image bytes are not attached to the result.
Documentation
- KTP NIK glyph-compare pipeline — Methods A/B/C preprocessing, crop geometry, multi-example templates, voting, and all tunable parameters.
- Nomor KK glyph-compare pipeline — how the KK number reuses the same color pipeline (layout differences + final-capture gating).
Example
See example/ for a minimal host app with a debug toggle and result pages.
cd example && flutter run
License
Apache License 2.0 — see LICENSE.
Libraries
- kaderkita_ocr
- On-device Indonesian KTP and Kartu Keluarga (KK) OCR scanners.