CoolFace
Apppublic

PACWIN2027/Form_Summary_Extraction

sourceHugging Faceupdated 1mo agoView on Hugging Face
0likes
ocr.py65 linesDownload Raw Back to extractor
1# -*- coding: utf-8 -*-
2"""Tesseract fallback for scanned pages.
3
4Most Punjab electoral PDFs published since ~2019 carry a real text layer, which
5is both faster and far more accurate than OCR. This module only runs for pages
6where :attr:`extractor.pdfsource.Page.has_text_layer` is False.
7"""
8
9import os
10
11OCR_LANG = os.environ.get('OCR_LANG', 'pan+eng')
12OCR_DPI = int(os.environ.get('OCR_DPI', '300'))
13OCR_PSM = os.environ.get('OCR_PSM', '6')
14
15
16def available():
17    """True when both pytesseract and a rendering backend are importable."""
18    try:
19        import pypdfium2  # noqa: F401
20        import pytesseract
21        pytesseract.get_tesseract_version()
22        return True
23    except Exception:
24        return False
25
26
27def languages():
28    try:
29        import pytesseract
30        return pytesseract.get_languages(config='')
31    except Exception:
32        return []
33
34
35def ocr_pages(pdf_path, page_numbers):
36    """OCR the given 1-based page numbers, returning ``{page_no: [line, ...]}``."""
37    if not page_numbers or not available():
38        return {}
39
40    import pypdfium2
41    import pytesseract
42
43    lang = OCR_LANG
44    if 'pan' in lang and 'pan' not in languages():
45        # Punjabi model missing - fall back to English so the page is not lost.
46        lang = 'eng'
47
48    out = {}
49    doc = pypdfium2.PdfDocument(pdf_path)
50    try:
51        scale = OCR_DPI / 72.0
52        for number in page_numbers:
53            page = doc[number - 1]
54            image = page.render(scale=scale).to_pil()
55            text = pytesseract.image_to_string(
56                image, lang=lang, config='--oem 1 --psm %s' % OCR_PSM)
57            out[number] = [l.strip() for l in text.splitlines() if l.strip()]
58    finally:
59        doc.close()
60    return out
61
62
63def scanned_page_numbers(pages):
64    return [p.number for p in pages if not p.has_text_layer]
65