Bill-Invoice-Scanner-Pro / benchmark_sroie.py
DIVYANSHI SINGH
Root project layout configured for deployment
b0bec61
Raw
History Blame Contribute Delete
3.85 kB
import os
import json
import sqlite3
import time
from ocr import OCRScanner
from extractor import parse_invoice
import database
import re
def clean_amount(val):
if not val: return 0.0
val_str = str(val)
m = re.search(r'\d+(?:,\d{3})*(?:\.\d+)?', val_str)
if m:
return float(m.group(0).replace(',', ''))
return 0.0
def benchmark_sroie(limit=1000):
"""
SROIE Benchmark Suite - Production Scale.
1. Processes images via OCRScanner.
2. Parses fields via invoice_parser.
3. Compares against Ground Truth JSONs.
4. Persists results to invoices.db.
"""
database.init_db()
scanner = OCRScanner()
# Correct relative paths from bill_scanner/
img_dir = "../SROIE_Dataset/data/img/"
key_dir = "../SROIE_Dataset/data/key/"
if not os.path.exists(img_dir):
print(f"Error: Dataset directory {img_dir} not found.")
return
images = [f for f in os.listdir(img_dir) if f.lower().endswith(('.jpg', '.jpeg', '.png'))]
if limit:
images = images[:limit]
print(f"--- Starting SROIE Production Benchmark: {len(images)} images ---")
stats = {
"processed": 0,
"total_match": 0,
"date_match": 0,
"errors": 0
}
start_time = time.time()
for i, img_name in enumerate(images):
img_path = os.path.normpath(os.path.join(img_dir, img_name))
key_name = img_name.rsplit('.', 1)[0] + '.json'
key_path = os.path.normpath(os.path.join(key_dir, key_name))
if not os.path.exists(key_path):
continue
try:
# 1. OCR + Extraction
raw_text = scanner.extract_text(img_path)
parsed = parse_invoice(raw_text)
# Add filename for tracking
parsed["file_name"] = img_name
# 2. Ground Truth Comparison
with open(key_path, 'r', encoding='utf-8') as f:
gt = json.load(f)
# Extract values for accuracy comparison
p_total = clean_amount(parsed.get('total'))
gt_total = clean_amount(gt.get('total'))
p_date = str(parsed.get('date', '') or '').strip()
gt_date = str(gt.get('date', '') or '').strip()
# Simple fuzzy matching for benchmark
is_t_match = abs(p_total - gt_total) < 0.01 if gt_total > 0 else (p_total == gt_total)
is_d_match = (gt_date in p_date or p_date in gt_date) if gt_date else True
if is_t_match: stats["total_match"] += 1
if is_d_match: stats["date_match"] += 1
stats["processed"] += 1
# 3. Persistent DB Save
database.save_invoice(parsed)
if (i + 1) % 10 == 0 or (i + 1) == len(images):
elapsed = time.time() - start_time
t_acc = (stats["total_match"] / stats["processed"]) * 100
d_acc = (stats["date_match"] / stats["processed"]) * 100
print(f"Prog: {i+1}/{len(images)} | Total Acc: {t_acc:.1f}% | Date Acc: {d_acc:.1f}% | Time: {elapsed:.1f}s")
except Exception as e:
stats["errors"] += 1
print(f"Error on {img_name}: {e}")
total_elapsed = time.time() - start_time
print("\n" + "="*50)
print(f"BENCHMARK COMPLETE")
print(f"Processed: {stats['processed']} | Errors: {stats['errors']}")
print(f"Final Total Accuracy: {(stats['total_match']/max(1, stats['processed'])):.2%}")
print(f"Final Date Accuracy: {(stats['date_match']/max(1, stats['processed'])):.2%}")
print(f"Total Time: {total_elapsed:.1f} seconds")
print("="*50)
if __name__ == "__main__":
benchmark_sroie(limit=1000)