Flutter OCR tutorial ini akan memandu Anda bagaimana cara mengembangkan fitur pemindai Kartu Tanda Penduduk (KTP) dan Nomor Pokok Wajib Pajak (NPWP) menggunakan Google ML Kit. Kebutuhan untuk mengekstrak informasi penting dari dokumen fisik secara cepat dan akurat semakin meningkat. Dengan memanfaatkan kemampuan Optical Character Recognition (OCR) dari Google ML Kit, kita dapat mengintegrasikan fungsi pemindaian dokumen langsung ke dalam aplikasi Flutter.
Saat ini, banyak aplikasi yang sudah memanfaatkan teknologi OCR (Optical Character Recognition) untuk proses e-KYC (Electronic Know Your Customer) mulai dari memindai KTP, NPWP, hingga dokumen resmi lainnya. Bahkan, teknologi ini kini bisa dijalankan langsung di perangkat secara lokal (on-device) tanpa koneksi internet, membuat prosesnya lebih cepat dan aman.
Kabar baiknya, teknologi ini sekarang bisa dijalankan langsung secara lokal tanpa perlu koneksi internet. Hal ini akan mempercepat proses sekaligus meningkatkan keamanan data.
Pada Flutter OCR tutorial kali ini, kami akan membahas cara membuat aplikasi Flutter sederhana yang mampu memindai dan mengekstrak data dari KTP dan NPWP secara offline menggunakan Google ML Kit. Simak berikut penjelasannya untuk Anda!
Table of Contents
Tutorial Flutter OCR: Membuat Pemindai KTP & NPWP dengan Google ML Kit
Langkah 1: Mempersiapkan Proyek Flutter
Mulai dengan membuat proyek Flutter baru:
flutter create ktp_npwp_scanner
Lalu tambahkan dependencies berikut di pubspec.yaml:
dependencies:
flutter:
sdk: flutter
google_mlkit_text_recognition: ^0.15.0
image_picker: ^1.1.2
image: ^4.5.4 #optional for image preprocessing
Jalankan flutter pub get
untuk mengunduh dependecy-nya.
Langkah 2: Buat UI Sederhana untuk Pilih Gambar
Buat tampilan UI yang memungkinkan pengguna dapat memilih gambar dari kamera atau galeri, lalu kemudian tampilkan hasil OCR-nya.
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'dart:io';
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
File? _selectedImage;
String _result = "";
final ImagePicker _picker = ImagePicker();
Future<void> _pickImage(ImageSource source) async {
final XFile? pickedFile = await _picker.pickImage(source: source);
if (pickedFile != null) {
setState(() {
_selectedImage = File(pickedFile.path);
});
final result = await recognizeText(_selectedImage!);
setState(() {
_result = result;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('KTP & NPWP Scanner')),
body: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (_selectedImage != null)
Image.file(_selectedImage!, height: 300, fit: BoxFit.contain),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton.icon(
icon: const Icon(Icons.camera_alt),
label: const Text('Camera'),
onPressed: () => _pickImage(ImageSource.camera),
),
ElevatedButton.icon(
icon: const Icon(Icons.image),
label: const Text('Gallery'),
onPressed: () => _pickImage(ImageSource.gallery),
),
],
),
const SizedBox(height: 20),
const Text('Data:',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
Text(_result),
],
),
);
}
}
Langkah 3: Tambahkan Fungsi OCR dengan Google ML Kit
Berikut cara OCR teks dari gambar yang dipilih menggunakan Google ML Kit.
Future<String> recognizeText(File imageFile) async {
final inputImage = InputImage.fromFile(imageFile);
final textRecognizer = TextRecognizer(script: TextRecognitionScript.latin);
final RecognizedText recognizedText =
await textRecognizer.processImage(inputImage);
return recognizedText.text;
}
Langkah 4: Ekstrak NIK dan NPWP dari Hasil OCR
Sekarang untuk mengambil data yang penting: NIK (16 digit) atau NPWP (biasanya 16/15 digit). Berikut fungsi yang dapat dipakai:
String? extractNIK(String ocrText) {
// Step 1: Remove non-digit characters but keep spacing between words
final cleaned = ocrText.replaceAll(RegExp(r'[^0-9\s]'), '');
// Step 2: Remove extra spaces and split into words
final words = cleaned.split(RegExp(r'\s+'));
// Step 3: Search for 15–16 digit numbers
for (final word in words) {
if (RegExp(r'^\d{15,16}$').hasMatch(word)) {
return word;
}
}
return null; // No NIK found
}
Penjelasan Fungsi:
- Menghapus karakter selain angka dan spasi.
- Memisahkan teks berdasarkan spasi untuk mengambil bagian – bagian angka.
- Mengembalikan angka dengan 15–16 digit (NIK/NPWP pertama yang ditemukan).
Langkah 5: Melihat Hasilnya
Berikut hasil tampilan aplikasi setelah dijalankan:
- Bagian kiri: Menampilkan teks asli dari hasil proses OCR.
- Bagian kanan: Menampilkan data yang telah diekstrak, hanya NIK dan NPWP-nya saja.

Bonus: Preprocessing Gambar agar OCR Lebih Akurat
Kualitas gambar sangat memengaruhi hasil OCR. Pencahayaan yang buruk, atau gambar buram bisa membuat teks sulit dikenali. Untuk itu, pada flutter OCR tutorial ini, kami memberikan tips agar melakukan preprocessing terlebih dahulu sebelum memproses gambar ke OCR :
import 'dart:io';
import 'package:image/image.dart' as img;
Future<File> preprocessImage(File file) async {
final bytes = await file.readAsBytes();
img.Image? image = img.decodeImage(bytes);
if (image == null) return file;
final gray = img.grayscale(image);
final contrast = img.contrast(gray, contrast: 175);
final denoised = img.gaussianBlur(contrast, radius: 1);
final output = img.encodeJpg(denoised);
final path = '${file.parent.path}/processed_${file.uri.pathSegments.last}';
return File(path)..writeAsBytesSync(output);
}
Penjelasan Fungsi:
- Mengubah gambar menjadi hitam putih untuk mengurangi noise warna.
- Meningkatkan kontras agar teks terlihat lebih jelas.
- Menerapkan Gaussian blur untuk melakukan denoise gambar.
Kode Selengkapnya
Berikut full code yang mencakup keseluruhan implementasi mulai dari pembuatan tampilan pengguna, implementasi OCR menggunakan Google ML Kit, ekstraksi NIK/NPWP, hingga preprocessing gambar untuk meningkatkan akurasi OCR.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:google_mlkit_text_recognition/google_mlkit_text_recognition.dart';
import 'package:image/image.dart' as img;
import 'package:image_picker/image_picker.dart';
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
MyHomePageState createState() => MyHomePageState();
}
class MyHomePageState extends State<MyHomePage> {
File? _selectedImage;
String _result = "";
final ImagePicker _picker = ImagePicker();
Future<void> _pickImage(ImageSource source) async {
final XFile? pickedFile = await _picker.pickImage(source: source);
if (pickedFile != null) {
setState(() {
_selectedImage = File(pickedFile.path);
});
final result = await recognizeText(_selectedImage!);
final nik = extractNIK(result);
setState(() {
_result = nik ?? "NIK tidak ditemukan";
});
}
}
String? extractNIK(String ocrText) {
final cleaned = ocrText.replaceAll(RegExp(r'[^0-9\s]'), '');
final words = cleaned.split(RegExp(r'\s+'));
for (final word in words) {
if (RegExp(r'^\d{15,16}$').hasMatch(word)) {
return word;
}
}
return null;
}
Future<String> recognizeText(File imageFile) async {
final inputImage = InputImage.fromFile(await preprocessImage(imageFile));
final textRecognizer = TextRecognizer(script: TextRecognitionScript.latin);
final RecognizedText recognizedText =
await textRecognizer.processImage(inputImage);
return recognizedText.text;
}
Future<File> preprocessImage(File file) async {
final bytes = await file.readAsBytes();
img.Image? image = img.decodeImage(bytes);
if (image == null) return file;
final gray = img.grayscale(image);
final contrast = img.contrast(gray, contrast: 175);
final denoised = img.gaussianBlur(contrast, radius: 1);
final output = img.encodeJpg(denoised);
final path = '${file.parent.path}/processed_${file.uri.pathSegments.last}';
return File(path)..writeAsBytesSync(output);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('KTP & NPWP Scanner')),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
if (_selectedImage != null)
Image.file(_selectedImage!, height: 300, fit: BoxFit.contain),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton.icon(
icon: const Icon(Icons.camera_alt),
label: const Text('Camera'),
onPressed: () => _pickImage(ImageSource.camera),
),
ElevatedButton.icon(
icon: const Icon(Icons.image),
label: const Text('Gallery'),
onPressed: () => _pickImage(ImageSource.gallery),
),
],
),
const SizedBox(height: 20),
const Text('Data:',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
const SizedBox(height: 10),
Text(_result),
],
),
),
);
}
}
Baca Juga: Cara Integrasi Generative AI di Aplikasi Flutter
Kesimpulan
Hanya dengan beberapa tools saja, kita bisa membangun fitur OCR offline di Flutter untuk membaca data dari KTP dan NPWP. Menggabungkan Google ML Kit dengan preprocessing gambar sederhana bisa meningkatkan akurasi pengambilan data seperti NIK dan NPWP tanpa perlu koneksi internet.
Dengan mengikuti Flutter OCR tutorial ini, Anda sekarang dapat memahami langkah-langkah dasar untuk membuat fitur OCR di aplikasi Flutter yang dapat memindai dan mengekstrak data dari dokumen seperti KTP dan NPWP secara efisien. Penerapan teknologi OCR ini memungkinkan Anda untuk mengembangkan aplikasi dengan fungsionalitas tinggi, seperti dalam proses e-KYC, yang semakin dibutuhkan oleh berbagai industri.
Jika Anda membutuhkan jasa pembuatan aplikasi Flutter yang mengintegrasikan fitur OCR, LOGIQUE siap membantu. Tim kami memiliki pengalaman dalam pengembangan aplikasi dengan teknologi terbaru, termasuk OCR dan solusi berbasis Flutter. Jangan ragu untuk menghubungi kami dan mulai bangun aplikasi Flutter impian Anda dengan fitur canggih yang sesuai kebutuhan bisnis Anda.