import cv2 import json import base64 import requests from paddleocr import PaddleOCR from pydantic import BaseModel

---------------------------

CONFIG

---------------------------

IMAGE_PATH = "voter_card.jpg" OLLAMA_URL = "http://localhost:11434/api/chat" MODEL = "qwen2.5vl:7b"

---------------------------

SCHEMA

---------------------------

class VoterID(BaseModel): epic_number: str | None = None name: str | None = None father_name: str | None = None husband_name: str | None = None dob: str | None = None gender: str | None = None

---------------------------

OCR

---------------------------

ocr = PaddleOCR( use_angle_cls=True, lang="en" )

result = ocr.ocr(IMAGE_PATH, cls=True)

ocr_blocks = []

for line in result[0]:

bbox = line[0]
text = line[1][0]
confidence = float(line[1][1])

ocr_blocks.append({
    "text": text,
    "confidence": round(confidence, 3),
    "bbox": bbox
})

sort by reading order

ocr_blocks.sort( key=lambda item: ( min(p[1] for p in item["bbox"]), min(p[0] for p in item["bbox"]) ) )

---------------------------

IMAGE TO BASE64

---------------------------

with open(IMAGE_PATH, "rb") as f: image_b64 = base64.b64encode(f.read()).decode()

---------------------------

PROMPT

---------------------------

prompt = f""" You are an expert Indian document extraction engine.

Document may be:

  • Voter ID
  • PAN Card
  • Aadhaar
  • Driving License

Use BOTH:

  1. The image
  2. OCR text
  3. OCR coordinates

OCR Results:

{json.dumps(ocr_blocks, ensure_ascii=False, indent=2)}

Return ONLY valid JSON.

Schema:

{{ "document_type": null, "id_number": null, "name": null, "father_name": null, "husband_name": null, "dob": null, "gender": null }}

Rules:

  • Correct obvious OCR mistakes.
  • Use image when OCR is incorrect.
  • Return null if field missing.
  • No explanation.
  • Output JSON only. """

---------------------------

OLLAMA VISION CALL

---------------------------

payload = { "model": MODEL, "messages": [ { "role": "user", "content": prompt, "images": [image_b64] } ], "stream": False }

response = requests.post( OLLAMA_URL, json=payload, timeout=300 )

response.raise_for_status()

content = response.json()["message"]["content"]

remove markdown wrappers

content = ( content.replace("json", "") .replace("", "") .strip() )

print("\nRAW RESPONSE\n") print(content)

---------------------------

PARSE JSON

---------------------------

try: data = json.loads(content)

print("\nSTRUCTURED DATA\n")
print(json.dumps(data, indent=4))

except Exception as e: print("JSON parsing failed") print(e)

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support