Skip to main content
A
Docs

OCR Pipeline

Multi-engine OCR with Azure, EasyOCR, and Tesseract failover for Arabic and English document text extraction.

OCR Architecture

Docs AI uses a multi-engine OCR strategy to maximize extraction accuracy across different document types and quality levels. The system selects the appropriate engine based on file type and falls back through a chain when the primary engine fails.

Engine Selection by File Type

File TypePrimary EngineNotes
PNG, JPG, JPEG, TIFF, BMPEasyOCRNative Arabic + English support with bounding boxes
PDF (text-embedded)PyPDF2Extracts embedded text directly — no OCR needed
PDF (scanned/image)Azure OCR -> EasyOCR -> TesseractThree-tier failover for scanned PDFs
DOCXpython-docxParses Word document structure directly

Failover Chain

For scanned documents where embedded text extraction fails, the OCR pipeline falls through three engines:

1. Azure OCR (Primary)

Azure's Computer Vision OCR service provides the highest accuracy for both Arabic and English text. It handles complex layouts, mixed-language documents, and low-quality scans effectively.

2. EasyOCR (Secondary)

EasyOCR runs locally without cloud dependencies. It provides strong Arabic character-level recognition and returns bounding box coordinates for each detected text block. Used when Azure OCR is unavailable or returns errors.

3. Tesseract (Tertiary)

Tesseract serves as the universal fallback. It supports Arabic through language packs and works across all image formats, though with lower accuracy on complex Arabic layouts compared to EasyOCR.

Local-Only Mode

When running without Azure credentials, the pipeline skips Azure OCR entirely and starts with EasyOCR. This enables fully offline document processing for air-gapped or sovereign environments.

OCR Output

The OCR endpoint returns extracted text along with confidence scores and block-level detail:

curl -X POST "http://localhost:8008/api/v1/docs/ocr?document_id=DOC_ID"
{
  "text": "United Arab Emirates\nEmiratesID\n784-1990-1234567-1\nالهوية الإماراتية",
  "confidence": 0.92,
  "language": "mixed",
  "blocks": [
    {
      "text": "United Arab Emirates",
      "confidence": 0.98,
      "bbox": [[10, 20], [200, 20], [200, 50], [10, 50]]
    },
    {
      "text": "الهوية الإماراتية",
      "confidence": 0.89,
      "bbox": [[10, 60], [180, 60], [180, 90], [10, 90]]
    }
  ]
}

Response Fields

FieldTypeDescription
textstringFull extracted text concatenated from all blocks
confidencefloatOverall confidence score (0.0-1.0)
languagestringDetected language: ar, en, or mixed
blocksarrayIndividual text blocks with per-block confidence and bounding boxes

Block Fields

FieldTypeDescription
textstringText content of this block
confidencefloatConfidence score for this block
bboxarrayBounding box coordinates as four [x, y] corner points

Arabic-Specific Handling

Arabic text presents unique OCR challenges:

  • Right-to-left flow — Text blocks must be ordered RTL, not LTR
  • Connected script — Arabic letters connect, requiring ligature-aware recognition
  • Diacritical marks — Optional tashkeel marks (harakat) affect meaning but are often omitted in printed text
  • Mixed direction — Documents frequently mix Arabic and English (e.g., Emirates IDs have both)

EasyOCR handles these challenges natively, with Arabic as a first-class supported language. The OCR_LANGUAGES environment variable controls which language models are loaded:

OCR_LANGUAGES='["ar", "en"]'

LRU Caching

OCR results are cached using an LRU cache to avoid reprocessing the same document. If a document has already been OCR-processed, subsequent requests return the cached result immediately.

Configuration

VariableDefaultDescription
OCR_LANGUAGES["ar", "en"]Languages to load for OCR
OCR_GPUfalseEnable GPU acceleration for EasyOCR
MAX_FILE_SIZE_MB50Maximum upload file size
UPLOAD_DIR./uploadsDirectory for uploaded files

Batch Processing

For high-volume document processing, upload and OCR documents in sequence:

for file in documents/*.pdf; do
  # Upload
  doc_id=$(curl -s -X POST http://localhost:8008/api/v1/docs/upload \
    -F "file=@$file" | jq -r '.id')

  # OCR
  curl -X POST "http://localhost:8008/api/v1/docs/ocr?document_id=$doc_id"
done

The OCR engine processes documents sequentially. For parallel processing at scale, run multiple Docs AI instances behind a load balancer.