INFERENCELAB
Back to Engineering Journals
Engineering FellowshipCohort 2026
docling-pk

Building Robust OCR Extraction for Pakistani Documents

Built the core image processing, OCR, and field extraction pipeline for docling-pk, supporting Pakistani identity and education documents. Real-world testing exposed failures caused by image preprocessing assumptions and OCR layout variability, leading to more robust extraction strategies. The system now handles rotated documents, layout-dependent fields, and explicit extraction failures rather than relying on ideal document structure. The work reinforced a practical lesson: real document variability must drive OCR design, not assumptions from standard preprocessing techniques.

Published: 2026-09-19 6 min read

Lab Note & Technical Documentation

What I built

I built the image processing and field extraction core of docling-pk, a library that reads structured data (name, CNIC number, dates, marks) from photos of Pakistani identity and education documents. This includes preprocessor.py (blur detection and deskew), ocr.py (an EasyOCR wrapper that tries all four rotations and keeps the best result), the field extraction logic in parsers/cnic.py, parsers/matric.py, and parsers/intermediate.py, and extractor.py, which ties all of it together.

One technical decision

I initially added adaptive thresholding to preprocessing because it is standard advice for OCR under uneven lighting. Later, while debugging low confidence scores, I ran a direct test: the same real photos, with and without that step. Removing it raised EasyOCR's own confidence on every sample, sometimes by 20 points. The threshold was converting images into a harsh black and white format the model was never trained on.

What I would do differently: test standard advice against real data from day one instead of trusting it by default.

What broke, and how I fixed it

CNIC number and date extraction worked on my first test image but failed inconsistently on others. I assumed my regex was wrong and spent time tightening it. The real cause became clear only when I printed the raw OCR text directly: EasyOCR read all three date labels as one group, then all three date values as a separate group further down, not as label-value pairs. My code assumed a value always sits right after its label, which worked for some fields and silently failed for others depending on layout. The fix was to stop assuming label adjacency. I extract every date shaped string from the raw text and assign them by fixed position (birth, issue, expiry), since that order holds across real cards even when layout scrambles their position relative to their labels.

What I could not have learned from a tutorial

The same field can fail for different reasons on different real documents, and that is a feature of the problem, not a bug in my code. Gender extracted cleanly as text on one CNIC and was completely unrecoverable on another, due to a difference in the card's print sub-format. This taught me to write extraction code that records why a field failed, not just that it did, and to stop treating one successful test image as proof of a working solution.

Project Repositories & Artifacts

Contributors
Technologies
Computer VisionNLP