Flutter OCR Tutorial: Cara Membuat Scanner KTP & NPWP dengan Google ML Kit

Sumber: www.freepik.com

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!

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.
flutter ocr tutorial


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.