Spaces:
Sleeping
Sleeping
Pointf5ive commited on
Commit ·
be1ecc2
1
Parent(s): 6c9e2c1
Fix Smoke Signal Surya OCR for new predictor API
Browse files- smoke_signal/scripts/03_ocr_bakeoff.py +48 -9
- smoke_signal_tab.py +63 -15
smoke_signal/scripts/03_ocr_bakeoff.py
CHANGED
|
@@ -27,6 +27,7 @@ Usage:
|
|
| 27 |
|
| 28 |
import argparse
|
| 29 |
import csv
|
|
|
|
| 30 |
import json
|
| 31 |
import sys
|
| 32 |
import time
|
|
@@ -113,8 +114,34 @@ def _safe_load_surya_component(loader, checkpoint: Optional[str]):
|
|
| 113 |
def load_surya_context(checkpoint: Optional[str] = None) -> Optional[dict]:
|
| 114 |
"""
|
| 115 |
Load Surya OCR models once per run.
|
|
|
|
| 116 |
Returns context dict or None if Surya import/loading fails.
|
| 117 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 118 |
try:
|
| 119 |
from surya.ocr import run_ocr
|
| 120 |
from surya.model.detection.model import load_model as load_det_model
|
|
@@ -169,14 +196,23 @@ def _run_surya(image_path: Path, langs: list, surya_ctx: Optional[dict] = None)
|
|
| 169 |
|
| 170 |
try:
|
| 171 |
image = Image.open(str(image_path)).convert("RGB")
|
| 172 |
-
|
| 173 |
-
[
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
|
| 181 |
page_result = results[0]
|
| 182 |
|
|
@@ -191,10 +227,13 @@ def _run_surya(image_path: Path, langs: list, surya_ctx: Optional[dict] = None)
|
|
| 191 |
if text:
|
| 192 |
full_text.append(text)
|
| 193 |
confidences.append(conf)
|
|
|
|
|
|
|
|
|
|
| 194 |
words.append({
|
| 195 |
"text": text,
|
| 196 |
"confidence": round(conf, 4),
|
| 197 |
-
"bbox":
|
| 198 |
})
|
| 199 |
|
| 200 |
avg_conf = round(sum(confidences) / len(confidences), 4) if confidences else 0.0
|
|
|
|
| 27 |
|
| 28 |
import argparse
|
| 29 |
import csv
|
| 30 |
+
import hashlib
|
| 31 |
import json
|
| 32 |
import sys
|
| 33 |
import time
|
|
|
|
| 114 |
def load_surya_context(checkpoint: Optional[str] = None) -> Optional[dict]:
|
| 115 |
"""
|
| 116 |
Load Surya OCR models once per run.
|
| 117 |
+
Tries modern predictor API first, then legacy API.
|
| 118 |
Returns context dict or None if Surya import/loading fails.
|
| 119 |
"""
|
| 120 |
+
# New API (surya-ocr>=0.17 style)
|
| 121 |
+
try:
|
| 122 |
+
from surya.foundation import FoundationPredictor
|
| 123 |
+
from surya.detection import DetectionPredictor
|
| 124 |
+
from surya.recognition import RecognitionPredictor
|
| 125 |
+
try:
|
| 126 |
+
from surya.common.surya.schema import TaskNames
|
| 127 |
+
task_name = TaskNames.ocr_with_boxes
|
| 128 |
+
except Exception:
|
| 129 |
+
task_name = "ocr_with_boxes"
|
| 130 |
+
|
| 131 |
+
foundation_predictor = _safe_load_surya_component(FoundationPredictor, checkpoint)
|
| 132 |
+
det_predictor = DetectionPredictor()
|
| 133 |
+
rec_predictor = RecognitionPredictor(foundation_predictor)
|
| 134 |
+
return {
|
| 135 |
+
"api": "predictor-v2",
|
| 136 |
+
"task_name": task_name,
|
| 137 |
+
"det_predictor": det_predictor,
|
| 138 |
+
"rec_predictor": rec_predictor,
|
| 139 |
+
"checkpoint": checkpoint,
|
| 140 |
+
}
|
| 141 |
+
except Exception:
|
| 142 |
+
pass
|
| 143 |
+
|
| 144 |
+
# Legacy API (surya-ocr<=0.6 style)
|
| 145 |
try:
|
| 146 |
from surya.ocr import run_ocr
|
| 147 |
from surya.model.detection.model import load_model as load_det_model
|
|
|
|
| 196 |
|
| 197 |
try:
|
| 198 |
image = Image.open(str(image_path)).convert("RGB")
|
| 199 |
+
if ctx.get("api") == "predictor-v2":
|
| 200 |
+
results = ctx["rec_predictor"](
|
| 201 |
+
[image],
|
| 202 |
+
task_names=[ctx["task_name"]],
|
| 203 |
+
det_predictor=ctx["det_predictor"],
|
| 204 |
+
highres_images=[image],
|
| 205 |
+
math_mode=True,
|
| 206 |
+
)
|
| 207 |
+
else:
|
| 208 |
+
results = ctx["run"](
|
| 209 |
+
[image],
|
| 210 |
+
[langs],
|
| 211 |
+
ctx["det_model"],
|
| 212 |
+
ctx["det_processor"],
|
| 213 |
+
ctx["rec_model"],
|
| 214 |
+
ctx["rec_processor"],
|
| 215 |
+
)
|
| 216 |
|
| 217 |
page_result = results[0]
|
| 218 |
|
|
|
|
| 227 |
if text:
|
| 228 |
full_text.append(text)
|
| 229 |
confidences.append(conf)
|
| 230 |
+
bbox = getattr(line, "bbox", None)
|
| 231 |
+
if bbox is None:
|
| 232 |
+
bbox = getattr(line, "polygon", None)
|
| 233 |
words.append({
|
| 234 |
"text": text,
|
| 235 |
"confidence": round(conf, 4),
|
| 236 |
+
"bbox": bbox,
|
| 237 |
})
|
| 238 |
|
| 239 |
avg_conf = round(sum(confidences) / len(confidences), 4) if confidences else 0.0
|
smoke_signal_tab.py
CHANGED
|
@@ -735,23 +735,52 @@ def run_ocr() -> tuple:
|
|
| 735 |
|
| 736 |
log = []
|
| 737 |
|
| 738 |
-
# Try to import Surya
|
| 739 |
surya = None
|
|
|
|
|
|
|
| 740 |
try:
|
| 741 |
-
from surya.
|
| 742 |
-
from surya.
|
| 743 |
-
from surya.
|
| 744 |
-
|
| 745 |
-
|
| 746 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 747 |
surya = {
|
| 748 |
-
"
|
| 749 |
-
"
|
| 750 |
-
"
|
|
|
|
| 751 |
}
|
| 752 |
-
|
| 753 |
-
|
| 754 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 755 |
|
| 756 |
queue_rows = []
|
| 757 |
|
|
@@ -806,7 +835,23 @@ def run_ocr() -> tuple:
|
|
| 806 |
doc.close()
|
| 807 |
|
| 808 |
img = Image.open(render_path).convert("RGB")
|
| 809 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 810 |
page_result = result[0]
|
| 811 |
|
| 812 |
regions = []
|
|
@@ -814,7 +859,10 @@ def run_ocr() -> tuple:
|
|
| 814 |
txt = line.text.strip()
|
| 815 |
if txt:
|
| 816 |
c = float(line.confidence) if hasattr(line, "confidence") else 1.0
|
| 817 |
-
|
|
|
|
|
|
|
|
|
|
| 818 |
|
| 819 |
conf = sum(r["confidence"]*r["word_count"] for r in regions) / max(sum(r["word_count"] for r in regions), 1) if regions else 0.0
|
| 820 |
conf = round(conf, 4)
|
|
|
|
| 735 |
|
| 736 |
log = []
|
| 737 |
|
| 738 |
+
# Try to import/load Surya (new predictor API first, then legacy API)
|
| 739 |
surya = None
|
| 740 |
+
surya_error = None
|
| 741 |
+
log.append(log_line("Loading Surya models (may take a moment)..."))
|
| 742 |
try:
|
| 743 |
+
from surya.foundation import FoundationPredictor
|
| 744 |
+
from surya.detection import DetectionPredictor
|
| 745 |
+
from surya.recognition import RecognitionPredictor
|
| 746 |
+
try:
|
| 747 |
+
from surya.common.surya.schema import TaskNames
|
| 748 |
+
task_name = TaskNames.ocr_with_boxes
|
| 749 |
+
except Exception:
|
| 750 |
+
task_name = "ocr_with_boxes"
|
| 751 |
+
|
| 752 |
+
foundation_predictor = FoundationPredictor()
|
| 753 |
+
det_predictor = DetectionPredictor()
|
| 754 |
+
rec_predictor = RecognitionPredictor(foundation_predictor)
|
| 755 |
surya = {
|
| 756 |
+
"api": "predictor-v2",
|
| 757 |
+
"task_name": task_name,
|
| 758 |
+
"det_predictor": det_predictor,
|
| 759 |
+
"rec_predictor": rec_predictor,
|
| 760 |
}
|
| 761 |
+
except Exception as e:
|
| 762 |
+
surya_error = e
|
| 763 |
+
try:
|
| 764 |
+
from surya.ocr import run_ocr as surya_run
|
| 765 |
+
from surya.model.detection.model import load_model as load_det
|
| 766 |
+
from surya.model.detection.processor import load_processor as load_det_proc
|
| 767 |
+
from surya.model.recognition.model import load_model as load_rec
|
| 768 |
+
from surya.model.recognition.processor import load_processor as load_rec_proc
|
| 769 |
+
surya = {
|
| 770 |
+
"api": "legacy-v1",
|
| 771 |
+
"run": surya_run,
|
| 772 |
+
"det_model": load_det(),
|
| 773 |
+
"det_proc": load_det_proc(),
|
| 774 |
+
"rec_model": load_rec(),
|
| 775 |
+
"rec_proc": load_rec_proc(),
|
| 776 |
+
}
|
| 777 |
+
except Exception as legacy_error:
|
| 778 |
+
surya_error = f"{surya_error}; legacy={legacy_error}"
|
| 779 |
+
|
| 780 |
+
if surya:
|
| 781 |
+
log.append(log_line(f"✓ Surya models loaded ({surya['api']})"))
|
| 782 |
+
else:
|
| 783 |
+
log.append(log_line(f"⚠ Surya unavailable ({surya_error}) — falling back to text extraction only"))
|
| 784 |
|
| 785 |
queue_rows = []
|
| 786 |
|
|
|
|
| 835 |
doc.close()
|
| 836 |
|
| 837 |
img = Image.open(render_path).convert("RGB")
|
| 838 |
+
if surya["api"] == "predictor-v2":
|
| 839 |
+
result = surya["rec_predictor"](
|
| 840 |
+
[img],
|
| 841 |
+
task_names=[surya["task_name"]],
|
| 842 |
+
det_predictor=surya["det_predictor"],
|
| 843 |
+
highres_images=[img],
|
| 844 |
+
math_mode=True,
|
| 845 |
+
)
|
| 846 |
+
else:
|
| 847 |
+
result = surya["run"](
|
| 848 |
+
[img],
|
| 849 |
+
[["en"]],
|
| 850 |
+
surya["det_model"],
|
| 851 |
+
surya["det_proc"],
|
| 852 |
+
surya["rec_model"],
|
| 853 |
+
surya["rec_proc"],
|
| 854 |
+
)
|
| 855 |
page_result = result[0]
|
| 856 |
|
| 857 |
regions = []
|
|
|
|
| 859 |
txt = line.text.strip()
|
| 860 |
if txt:
|
| 861 |
c = float(line.confidence) if hasattr(line, "confidence") else 1.0
|
| 862 |
+
bbox = getattr(line, "bbox", None)
|
| 863 |
+
if bbox is None:
|
| 864 |
+
bbox = getattr(line, "polygon", None)
|
| 865 |
+
regions.append({"text": txt, "confidence": round(c,4), "bbox": bbox, "word_count": len(txt.split())})
|
| 866 |
|
| 867 |
conf = sum(r["confidence"]*r["word_count"] for r in regions) / max(sum(r["word_count"] for r in regions), 1) if regions else 0.0
|
| 868 |
conf = round(conf, 4)
|