Extract Spesifik Teks Dari Gambar Dengan Pytesseract

Intro

Beberapa hari yang lalu salah seorang teman saya ingin mengambil nomor invoice dari sekian banyak hasil scan gambar invoice yang ia punya. Ia pun menanyakan solusinya kepada saya, setelah googling kesana kesini akhirnya saya menemukan solusi yang diinginkan. Yaitu dengan mengombinasikan OpenCV dengan Pytessseract untuk mengekstraknya.

Pytesseract:

Pytesseract atau Python-Tesseract adalah wrapper dari Google Tesseract OCR untuk bahasa Python. Library ini dapat digunakan untuk membuat script yang akan membaca sebuah teks dalam gambar dan mengekstraknya. Kalian bisa baca-baca lebih lanjut soal Pytesseract disini.

Step By Step

Pada case kali ini saya menggunakan OpenCV untuk memproses gambarnya lalu disesuaikan dengan Regex filter yang sudah ditentukan (untuk ekstraksi teks secara spesifik) kemudian di lempar ke Pytesseract untuk menyelesaikannya.

Untuk keperluan konten blog ini, saya menggunakan file gambar invoice dummy seperti ini:

invoice-test

Dari gambar diatas diketahui kita ingin mengambil nomor invoice yaitu 0001.

Berikut full code dari tools yang saya buat ini (akan dijelaskan beberapa barisnya kemudian).

import cv2
import re
from glob import glob
import pytesseract
from pytesseract import Output

data_pattern = '^(?!0{4})[0-9]{4}$' # SESUAIKAN REGEXNYA

img_mask = './data/*.jpg'
img_names = glob(img_mask)
for i in img_names:
    img = cv2.imread(i, 0)
    d = pytesseract.image_to_data(img, output_type=Output.DICT)
    keys = list(d.keys())
    n_boxes = len(d['text'])
    result = []
    for i in range(n_boxes):
        if int(d['conf'][i]) > 60:
            if re.match(data_pattern, d['text'][i]):
                result.append(d['text'][i])
                #(x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i])  // HANYA UNTUK TEST MENAMPILKAN GAMBAR
                #img = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)           // HANYA UNTUK TEST MENAMPILKAN GAMBAR
            
    print('No. Invoice: ',result[0])
    #cv2.imshow('img', img) // HANYA UNTUK TEST MENAMPILKAN GAMBAR

Secercah Penjelasan

data_pattern = '^(?!0{4})[0-9]{4}$'

Pada baris ini kita menentukan filter Regex yang akan digunakan, karena tadi saya ingin mengambil nomor invoice sebanyak 4 digit angka (0001) maka saya menggunakan Regex '^(?!0{4})[0-9]{4}$'

img_mask = './data/*.jpg'
img_names = glob(img_mask)
for i in img_names:
    img = cv2.imread(i, 0)
    d = pytesseract.image_to_data(img, output_type=Output.DICT)
    keys = list(d.keys())
    n_boxes = len(d['text'])

Baris code diatas berfungsi untuk mengambil semua file gambar bertipe .jpg dari sebuah folder bernama Data yang kemudian pytesseract mengekstrak text yang terdapat di dalamnya kedalam sebuah dictionary

dictionary

lalu script menghitung jumlah value dalam dictionary dengan key text.

d-text

result = []
    for i in range(n_boxes):
        if int(d['conf'][i]) > 60:
            if re.match(data_pattern, d['text'][i]):
                result.append(d['text'][i])

Langkah selanjutnya adalah kita melakukan matching filter Regex yang sebelumnya sudah di tentukan dengan value dari key text di output dictionary tadi. Bila match maka value akan ditambahkan kedalam array result yang selanjutnya tinggal kita print dengan syntax:

print('No. Invoice: ',result[0])

Dibawah ini adalah contoh gambar apabila value sesuai dengan Regex:

match

Result:

match