Kegagalan ekstraksi teks pada pipeline pemrosesan PDF sering kali dipicu oleh teknik obfuscation font adversarial, seperti konsep Ghost Font. Dokumen tampak normal ketika dirender di layar, namun payload ekstraksi parser berbasis teks menghasilkan string kosong atau karakter acak (garbage text). Kondisi ini memicu lonjakan fallback error pada worker pool backend.
Gejala Sistem: Teks Terbaca Visual, Payload Ekstraksi Kosong
Masalah ini terdeteksi pada antrean worker dokumen dengan indikator berikut:
- Parser PDF berbasis programmatic stream (seperti
pdfminer,pypdf, atau library berbasis Poppler) menghasilkan payload kosong (empty string) atau karakter Unicode Private Use Area (PUA, rentang\uE000-\uF8FF). - Renderer PDF (seperti MuPDF atau PDF.js) tetap menampilkan teks secara normal di browser dan PDF viewer.
- Worker pipeline mendeteksi kegagalan parsing berbasis aturan bisnis (misalnya validasi field nomor identitas atau total invoice), memicu retry berulang hingga queue backpressure melonjak.
Analisis Root Cause: Manipulasi Tabel ToUnicode CMap
Format PDF memisahkan representasi visual dokumen dari representasi semantik teksnya. Font embedding di PDF bekerja melalui glyph index yang dipetakan ke koordinat visual vektor. Untuk memungkinkan fitur copy-paste, indexing, dan ekstraksi teks, spesifikasi PDF (ISO 32000-1) menyediakan tabel ToUnicode CMap (Character Map).
Font adversarial mengeksploitasi arsitektur ini dengan dua metode utama:
- Stripping ToUnicode: Menghapus stream CMap sama sekali dari struktur font dictionary. Akibatnya, parser teks tidak memiliki mapping table dari glyph ID ke karakter Unicode standar.
- Arbitrary Glyph Remapping: Menempatkan glyph visual huruf 'A' pada indeks biner karakter 'X', atau memetakan glyph ke kode kontrol/karakter acak. Viewer PDF merender bentuk kurva font secara benar, tetapi parser mengekstrak bytecode teks mentah yang tidak sesuai.
Deteksi Anomali CMap di Level Backend
Pipeline harus memvalidasi integritas CMap sebelum menyerahkan stream teks ke lapisan indexing. Ekstraksi teks harus digagalkan secara eksplisit jika font tidak menyediakan mapping Unicode valid, agar worker dapat langsung mengarahkan dokumen ke pipeline visual OCR.
import io
from pypdf import PdfReader
def is_font_adversarial(pdf_stream: bytes) -> bool:
reader = PdfReader(io.BytesIO(pdf_stream))
total_fonts = 0
missing_cmap_fonts = 0
for page in reader.pages:
if "/Resources" not in page or "/Font" not in page["/Resources"]:
continue
fonts = page["/Resources"]["/Font"].get_object()
for font_key in fonts:
font_obj = fonts[font_key].get_object()
subtype = font_obj.get("/Subtype", "")
# Type3 atau font vektor umum Type0/TrueType
if subtype in ["/Type0", "/TrueType", "/Type1"]:
total_fonts += 1
# Deteksi ketiadaan tabel ToUnicode
if "/ToUnicode" not in font_obj:
missing_cmap_fonts += 1
else:
# Validasi stream ToUnicode tidak kosong
cmap_stream = font_obj["/ToUnicode"].get_object().get_data()
if len(cmap_stream.strip()) == 0:
missing_cmap_fonts += 1
if total_fonts == 0:
return False
# Ambang batas deteksi font rusak/adversarial
return (missing_cmap_fonts / total_fonts) > 0.5
# ponytail: cek sederhana berbasis rasio font stream; gunakan parser freetype jika butuh analisis level glyph.
assert is_font_adversarial(b"%PDF-1.4 empty test") is False
Fallback ke Visual OCR
Ketika deteksi menandai PDF mengandung font adversarial, bypass parsing teks standar dan konversi halaman PDF langsung menjadi bitmap (rasterization), lalu kirim ke engine OCR:
- Tesseract (OCR Tradisional): Cocok untuk dokumen berbasis formulir standar dengan kontras tinggi. Gunakan
pdftoppmdengan resolusi minimal 300 DPI sebelum inferensi Tesseract guna menjaga akurasi batas glyph. - TrOCR / Transformer-based OCR: Gunakan TrOCR ketika dokumen mengandung noise visual, font khusus, atau degradasi resolusi yang gagal diproses engine berbasis binarization klasik.
Arsitektur fallback yang efisien:
- Jalankan verifikasi CMap pada layer pre-validation worker.
- Jika valid dan rasio PUA rendah: ekstrak teks via native PDF parser (latensi rendah, resource ringan).
- Jika invalid (terdeteksi font adversarial): tandai flag
FORCE_VISUAL_OCR, render halaman ke PNG 300 DPI menggunakan MuPDF/pdf2image, lalu jalankan model OCR. - Simpan hasil OCR dan perbarui status dokumen untuk indexing database.
Trade-off dan Mitigasi
Eksekusi visual OCR secara permanen pada semua PDF tidak efisien karena konsumsi CPU/GPU yang jauh lebih tinggi dan latensi ekstraksi yang lebih lambat hingga 10-50x dibanding parsing stream PDF murni. Menerapkan skema inspeksi metadata CMap terlebih dahulu memungkinkan pipeline menjaga throughput tinggi sekaligus tetap kebal terhadap manipulasi font adversarial.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!