Tutorial Surya OCR: Document AI untuk Text Detection, OCR, dan Layout Analysis
Surya adalah library Document AI open-source yang powerful untuk melakukan OCR (Optical Character Recognition), text detection, layout analysis, reading order detection, dan table recognition. Dikembangkan oleh Vik Paruchuri (creator Marker), Surya mendukung lebih dari 90 bahasa dan memberikan akurasi yang sangat kompetitif dibandingkan solusi komersial seperti Google Cloud Vision.
Dalam tutorial ini, kita akan mempelajari cara menggunakan Surya untuk berbagai task document AI, mulai dari instalasi hingga penggunaan lanjutan untuk memproses dokumen kompleks.
Mengapa Surya?
Sebelum kita mulai, berikut beberapa alasan mengapa Surya layak dipertimbangkan:
- Multi-bahasa: Mendukung 90+ bahasa termasuk Bahasa Indonesia, CJK, Arabic, dan lainnya
- Akurasi tinggi: Benchmark menunjukkan akurasi setara atau lebih baik dari Google Cloud Vision pada banyak bahasa
- Open-source: Lisensi GPL-3.0, gratis untuk penggunaan non-komersial
- Fitur lengkap: OCR, text detection, layout analysis, table recognition, dan reading order detection dalam satu package
- GPU acceleration: Mendukung CUDA untuk pemrosesan yang lebih cepat
- Mudah digunakan: API yang sederhana dan intuitif
Instalasi
Persyaratan Sistem
- Python 3.9 atau lebih baru
- PyTorch (akan diinstal otomatis)
- GPU NVIDIA dengan CUDA (opsional, tapi sangat direkomendasikan untuk performa)
Instalasi via pip
pip install surya-ocr
Instalasi dari Source (untuk development)
git clone https://github.com/VikParuchuri/surya.git
cd surya
pip install -e .
Verifikasi Instalasi
import surya
print(surya.version)
Instalasi Dependensi Tambahan
Untuk memproses file PDF, instal juga:
pip install pypdfium2
Basic Usage
1. Text Detection
Text detection adalah langkah pertama dalam pipeline OCR. Surya mendeteksi area di mana teks berada dalam gambar.
from surya.detection import DetectionPredictor
from PIL import Image
Load image
image = Image.open("dokumen.png")
Inisialisasi detector
detector = DetectionPredictor()
Deteksi teks
predictions = detector([image])
Lihat hasil deteksi
for prediction in predictions:
for bbox in prediction.bboxes:
print(f"Bounding box: {bbox.bbox}")
print(f"Confidence: {bbox.confidence:.4f}")
print(f"Polygon: {bbox.polygon}")
print()
2. OCR (Optical Character Recognition)
Setelah mendeteksi area teks, kita bisa melakukan OCR untuk mengekstrak teks dari gambar.
from surya.recognition import RecognitionPredictor
from surya.detection import DetectionPredictor
from surya.ocr import OCRPredictor
from PIL import Image
Load image
image = Image.open("dokumen.png")
Inisialisasi predictor
detpredictor = DetectionPredictor()
recpredictor = RecognitionPredictor()
ocrpredictor = OCRPredictor(detpredictor, recpredictor)
Jalankan OCR
predictions = ocrpredictor([image])
Tampilkan hasil
for prediction in predictions:
for textline in prediction.textlines:
print(f"Text: {textline.text}")
print(f"Confidence: {textline.confidence:.4f}")
print(f"BBox: {textline.bbox}")
print()
3. Menentukan Bahasa
Surya bisa mendeteksi bahasa secara otomatis, tapi kamu juga bisa menentukan bahasa secara eksplisit untuk hasil yang lebih akurat:
from surya.recognition import RecognitionPredictor
from surya.detection import DetectionPredictor
from surya.ocr import OCRPredictor
from PIL import Image
image = Image.open("dokumenindonesia.png")
detpredictor = DetectionPredictor()
recpredictor = RecognitionPredictor()
ocrpredictor = OCRPredictor(detpredictor, recpredictor)
Tentukan bahasa: Indonesian
predictions = ocrpredictor([image], langs=[["id"]])
for prediction in predictions:
for textline in prediction.textlines:
print(f"{textline.text}")
Kode bahasa mengikuti standar ISO 639. Beberapa contoh: id (Indonesia), en (English), zh (Chinese), ja (Japanese), ar (Arabic).
Layout Analysis
Layout analysis mengidentifikasi struktur dokumen seperti paragraf, heading, tabel, gambar, dan elemen lainnya.
from surya.detection import DetectionPredictor
from surya.layout import LayoutPredictor
from PIL import Image
image = Image.open("dokumen.png")
detpredictor = DetectionPredictor()
layoutpredictor = LayoutPredictor()
Analisis layout
predictions = layoutpredictor([image])
for prediction in predictions:
for layoutbox in prediction.bboxes:
print(f"Label: {layoutbox.label}")
print(f"BBox: {layoutbox.bbox}")
print(f"Confidence: {layoutbox.confidence:.4f}")
print()
Label yang tersedia dalam layout analysis meliputi:
Text- Paragraf teks biasaTitle- Judul atau headingTable- TabelFigure- Gambar atau diagramList- Daftar/listCaption- Keterangan gambarHeader- Header halamanFooter- Footer halamanPageNumber- Nomor halaman
Table Recognition
Surya dapat mendeteksi dan mengekstrak struktur tabel dari dokumen.
from surya.detection import DetectionPredictor
from surya.layout import LayoutPredictor
from surya.tablerec import TableRecPredictor
from PIL import Image
image = Image.open("dokumentabel.png")
detpredictor = DetectionPredictor()
layoutpredictor = LayoutPredictor()
tablepredictor = TableRecPredictor()
Deteksi layout dulu untuk menemukan tabel
layoutpredictions = layoutpredictor([image])
Ambil area tabel
tableboxes = []
for pred in layoutpredictions:
for box in pred.bboxes:
if box.label == "Table":
tableboxes.append(box.bbox)
Rekognisi tabel
if tableboxes:
tablepredictions = tablepredictor(
[image],
[tableboxes[0]] # Proses tabel pertama
)
for prediction in tablepredictions:
for cell in prediction.cells:
print(f"Row: {cell.row}, Col: {cell.col}")
print(f"Text: {cell.text}")
print(f"BBox: {cell.bbox}")
print()
Reading Order Detection
Reading order detection menentukan urutan pembacaan yang benar untuk elemen-elemen dalam dokumen, sangat berguna untuk dokumen multi-kolom.
from surya.detection import DetectionPredictor
from surya.layout import LayoutPredictor
from surya.ordering import OrderingPredictor
from PIL import Image
image = Image.open("dokumenmultikolom.png")
detpredictor = DetectionPredictor()
layoutpredictor = LayoutPredictor()
orderingpredictor = OrderingPredictor()
Dapatkan layout
layoutpredictions = layoutpredictor([image])
Tentukan reading order
orderpredictions = orderingpredictor(
[image],
[layoutpredictions[0].bboxes]
)
for prediction in orderpredictions:
for item in prediction.bboxes:
print(f"Order: {item.position}, Label: {item.label}")
print(f"BBox: {item.bbox}")
print()
Advanced Usage
Batch Processing untuk Banyak Dokumen
Ketika kamu perlu memproses banyak dokumen sekaligus, gunakan batch processing untuk efisiensi:
from surya.recognition import RecognitionPredictor
from surya.detection import DetectionPredictor
from surya.ocr import OCRPredictor
from PIL import Image
import os
detpredictor = DetectionPredictor()
recpredictor = RecognitionPredictor()
ocrpredictor = OCRPredictor(detpredictor, recpredictor)
Load semua gambar
imagedir = "dokumen/"
images = []
filenames = []
for filename in os.listdir(imagedir):
if filename.endswith((".png", ".jpg", ".jpeg")):
img = Image.open(os.path.join(imagedir, filename))
images.append(img)
filenames.append(filename)
Proses batch (Surya akan mengoptimasi GPU usage)
predictions = ocrpredictor(images, langs=[["id"]] len(images))
Simpan hasil
for filename, prediction in zip(filenames, predictions):
print(f"\n=== {filename} ===")
fulltext = "\n".join([line.text for line in prediction.textlines])
print(fulltext)
# Simpan ke file
outputpath = f"output/{filename}.txt"
with open(outputpath, "w", encoding="utf-8") as f:
f.write(fulltext)
Memproses File PDF
from surya.recognition import RecognitionPredictor
from surya.detection import DetectionPredictor
from surya.ocr import OCRPredictor
import pypdfium2 as pdfium
from PIL import Image
def pdftoimages(pdfpath, dpi=150):
"""Convert PDF pages ke list of PIL Images."""
pdf = pdfium.PdfDocument(pdfpath)
images = []
for i in range(len(pdf)):
page = pdf[i]
bitmap = page.render(scale=dpi / 72)
pilimage = bitmap.topil()
images.append(pilimage)
return images
Convert PDF ke images
images = pdftoimages("laporan.pdf")
print(f"Total halaman: {len(images)}")
Inisialisasi OCR
detpredictor = DetectionPredictor()
recpredictor = RecognitionPredictor()
ocrpredictor = OCRPredictor(detpredictor, recpredictor)
OCR semua halaman
predictions = ocrpredictor(images, langs=[["id"]] len(images))
Gabungkan hasil
fulldocument = []
for i, prediction in enumerate(predictions):
pagetext = "\n".join([line.text for line in prediction.textlines])
fulldocument.append(f"--- Halaman {i+1} ---\n{pagetext}")
result = "\n\n".join(fulldocument)
print(result)
Pipeline Lengkap: OCR + Layout + Table Recognition
Berikut contoh pipeline lengkap yang menggabungkan semua fitur Surya:
from surya.recognition import RecognitionPredictor
from surya.detection import DetectionPredictor
from surya.layout import LayoutPredictor
from surya.tablerec import TableRecPredictor
from surya.ordering import OrderingPredictor
from surya.ocr import OCRPredictor
from PIL import Image
import json
def processdocument(imagepath, language="id"):
"""Pipeline lengkap untuk memproses dokumen."""
image = Image.open(imagepath)
# Inisialisasi semua predictor
detpredictor = DetectionPredictor()
recpredictor = RecognitionPredictor()
layoutpredictor = LayoutPredictor()
tablepredictor = TableRecPredictor()
orderingpredictor = OrderingPredictor()
ocrpredictor = OCRPredictor(detpredictor, recpredictor)
# Step 1: Layout analysis
layoutpreds = layoutpredictor([image])
layout = layoutpreds[0]
# Step 2: Reading order
orderpreds = orderingpredictor([image], [layout.bboxes])
order = orderpreds[0]
# Step 3: OCR
ocrpreds = ocrpredictor([image], langs=[[language]])
ocr = ocrpreds[0]
# Step 4: Table recognition (jika ada tabel)
tables = []
for box in layout.bboxes:
if box.label == "Table":
tablepred = tablepredictor([image], [box.bbox])
tables.append({
"bbox": box.bbox,
"cells": [
{
"row": cell.row,
"col": cell.col,
"text": cell.text,
"bbox": cell.bbox
}
for cell in tablepred[0].cells
]
})
# Compile hasil
result = {
"textlines": [
{
"text": line.text,
"confidence": line.confidence,
"bbox": line.bbox
}
for line in ocr.textlines
],
"layout": [
{
"label": box.label,
"bbox": box.bbox,
"confidence": box.confidence
}
for box in layout.bboxes
],
"readingorder": [
{
"position": item.position,
"label": item.label,
"bbox": item.bbox
}
for item in order.bboxes
],
"tables": tables
}
return result
Gunakan pipeline
result = processdocument("dokumenkompleks.png", language="id")
Simpan hasil ke JSON
with open("hasilanalisis.json", "w", encoding="utf-8") as f:
json.dump(result, f, ensureascii=False, indent=2)
Tampilkan teks dengan urutan baca yang benar
print("=== Teks Dokumen (Urutan Baca) ===")
for line in result["textlines"]:
print(f"[{line['confidence']:.2f}] {line['text']}")
Visualisasi Hasil Deteksi
Kamu bisa memvisualisasikan hasil deteksi menggunakan PIL atau matplotlib:
from surya.detection import DetectionPredictor
from PIL import Image, ImageDraw, ImageFont
image = Image.open("dokumen.png")
detector = DetectionPredictor()
predictions = detector([image])
Buat salinan gambar untuk visualisasi
visimage = image.copy()
draw = ImageDraw.Draw(visimage)
colors = {
"Text": "blue",
"Title": "red",
"Table": "green",
"Figure": "purple",
"List": "orange"
}
for prediction in predictions:
for bbox in prediction.bboxes:
coords = bbox.bbox # [x1, y1, x2, y2]
draw.rectangle(coords, outline="red", width=2)
visimage.save("hasildeteksi.png")
print("Visualisasi disimpan ke hasildeteksi.png")
Menggunakan CLI
Surya juga menyediakan command-line interface untuk penggunaan cepat:
# OCR
suryaocr dokumen.png --langs id
Text detection
suryadetect dokumen.png
Layout analysis
suryalayout dokumen.png
Table recognition
suryatable dokumen.png
Untuk memproses folder berisi banyak gambar:
suryaocr ./folderdokumen/ --langs id --resultsdir ./output/
Konfigurasi dan Optimasi
Pengaturan GPU
import os
Gunakan GPU tertentu
os.environ["CUDAVISIBLEDEVICES"] = "0"
Atur batch size (sesuaikan dengan VRAM GPU)
os.environ["RECOGNITIONBATCHSIZE"] = "64"
os.environ["DETECTORBATCHSIZE"] = "16"
os.environ["LAYOUTBATCHSIZE"] = "16"
os.environ["ORDERBATCHSIZE"] = "16"
os.environ["TABLERECBATCHSIZE"] = "16"
Menjalankan di CPU
Jika tidak punya GPU, Surya tetap bisa berjalan di CPU meski lebih lambat:
import torch
Force CPU mode
device = "cpu"
Kurangi batch size untuk CPU
os.environ["RECOGNITIONBATCHSIZE"] = "8"
os.environ["DETECTORBATCHSIZE"] = "4"
Tips Optimasi Performa
def resizeimage(image, maxsize=3000):
"""Resize gambar dengan menjaga aspek rasio."""
w, h = image.size
if max(w, h) > maxsize:
ratio = maxsize / max(w, h)
neww = int(w ratio)
newh = int(h ratio)
return image.resize((neww, newh), Image.LANCZOS)
return image
~/.cache/huggingface/import gc
import torch
def processlargepdf(pdfpath):
images = pdftoimages(pdfpath)
results = []
for i, img in enumerate(images):
pred = ocrpredictor([img], langs=[["id"]])
results.append(pred[0])
# Bersihkan memori setiap 10 halaman
if (i + 1) % 10 == 0:
gc.collect()
if torch.cuda.isavailable():
torch.cuda.emptycache()
return results
Best Practices
1. Pre-processing Gambar
Kualitas input sangat mempengaruhi hasil OCR. Berikut tips pre-processing:
from PIL import Image, ImageEnhance, ImageFilter
def preprocessforocr(imagepath):
"""Pre-processing gambar untuk hasil OCR yang lebih baik."""
img = Image.open(imagepath)
# Convert ke RGB jika perlu
if img.mode != "RGB":
img = img.convert("RGB")
# Tingkatkan kontras
enhancer = ImageEnhance.Contrast(img)
img = enhancer.enhance(1.5)
# Tingkatkan ketajaman
enhancer = ImageEnhance.Sharpness(img)
img = enhancer.enhance(2.0)
return img
2. Handling Error dengan Graceful
def safeocr(imagepath, language="id"):
"""OCR dengan error handling yang baik."""
try:
image = Image.open(image
path)
if image.mode not in ("RGB", "L"):
image = image.convert("RGB")
detpredictor = DetectionPredictor()
recpredictor = RecognitionPredictor()
ocrpredictor = OCRPredictor(detpredictor, recpredictor)
predictions = ocrpredictor([image], langs=[[language]])
if not predictions or not predictions[0].textlines:
return {"success": False, "error": "No text detected"}
textlines = [
{
"text": line.text,
"confidence": line.confidence
}
for line in predictions[0].textlines
]
return {
"success": True,
"text": "\n".join([l["text"] for l in textlines]),
"lines": textlines,
"avgconfidence": sum(l["confidence"] for l in textlines) / len(textlines)
}
except FileNotFoundError:
return {"success": False, "error": f"File not found: {imagepath}"}
except Exception as e:
return {"success": False, "error": str(e)}
3. Post-processing Hasil OCR
import re
def cleanocrtext(text):
"""Bersihkan hasil OCR."""
# Hapus spasi berlebih
text = re.sub(r' +', ' ', text)
# Perbaiki line breaks
text = re.sub(r'\n{3,}', '\n\n', text)
# Hapus karakter non-printable
text = re.sub(r'[^\S\n]+', ' ', text)
# Strip setiap baris
lines = [line.strip() for line in text.split('\n')]
text = '\n'.join(lines)
return text.strip()
4. Export Hasil ke Berbagai Format
import json
import csv
def exportresults(predictions, outputformat="json", outputpath="output"):
"""Export hasil OCR ke berbagai format."""
lines = []
for pred in predictions:
for line in pred.textlines:
lines.append({
"text": line.text,
"confidence": line.confidence,
"bbox": line.bbox
})
if outputformat == "json":
with open(f"{outputpath}.json", "w", encoding="utf-8") as f:
json.dump(lines, f, ensureascii=False, indent=2)
elif outputformat == "csv":
with open(f"{outputpath}.csv", "w", encoding="utf-8", newline="") as f:
writer = csv.DictWriter(f, fieldnames=["text", "confidence", "bbox"])
writer.writeheader()
for line in lines:
line["bbox"] = str(line["bbox"])
writer.writerow(line)
elif outputformat == "txt":
with open(f"{outputpath}.txt", "w", encoding="utf-8") as f:
for line in lines:
f.write(f"{line['text']}\n")
print(f"Hasil disimpan ke {outputpath}.{outputformat}")
Perbandingan dengan Alternatif Lain
| Fitur | Surya | Tesseract | EasyOCR | PaddleOCR |
|-------|-------|-----------|---------|-----------|
| Bahasa yang didukung | 90+ | 100+ | 80+ | 80+ |
| GPU Support | Ya | Terbatas | Ya | Ya |
| Layout Analysis | Ya | Terbatas | Tidak | Ya |
| Table Recognition | Ya | Tidak | Tidak | Ya |
| Reading Order | Ya | Tidak | Tidak | Tidak |
| Akurasi (general) | Tinggi | Sedang | Tinggi | Tinggi |
| Kecepatan | Cepat (GPU) | Cepat (CPU) | Sedang | Cepat |
| Lisensi | GPL-3.0 | Apache-2.0 | Apache-2.0 | Apache-2.0 |
Kesimpulan
Surya adalah solusi Document AI yang komprehensif dan powerful. Dengan fitur OCR multi-bahasa, text detection, layout analysis, table recognition, dan reading order detection, Surya menjadi pilihan utama untuk berbagai kebutuhan pemrosesan dokumen.
Poin-poin penting yang perlu diingat:
pip install surya-ocrSurya terus dikembangkan secara aktif dengan peningkatan model dan fitur baru. Untuk penggunaan komersial, pastikan untuk memeriksa detail lisensi GPL-3.0 dan opsi lisensi komersial yang tersedia.