Spaces:
Sleeping
Sleeping
| 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) | |