Spaces:
Sleeping
Sleeping
Pointf5ive commited on
Commit ·
16b10a3
1
Parent(s): 8c23eee
Fix Tesseract fallback batch loading and OCR progress visibility
Browse files- smoke_signal_tab.py +65 -18
smoke_signal_tab.py
CHANGED
|
@@ -721,6 +721,14 @@ try:
|
|
| 721 |
SS_SURYA_LOAD_TIMEOUT_SEC = max(1, int(os.environ.get("SS_SURYA_LOAD_TIMEOUT_SEC", "20")))
|
| 722 |
except Exception:
|
| 723 |
SS_SURYA_LOAD_TIMEOUT_SEC = 20
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 724 |
|
| 725 |
|
| 726 |
def _load_surya_runtime():
|
|
@@ -982,6 +990,8 @@ def run_ocr(progress=gr.Progress(track_tqdm=False)) -> tuple:
|
|
| 982 |
continue
|
| 983 |
total_pages_planned = max(total_pages_planned, 1)
|
| 984 |
processed_pages = 0
|
|
|
|
|
|
|
| 985 |
|
| 986 |
for _, row in eligible.iterrows():
|
| 987 |
book_id = row["book_id"]
|
|
@@ -1009,36 +1019,36 @@ def run_ocr(progress=gr.Progress(track_tqdm=False)) -> tuple:
|
|
| 1009 |
|
| 1010 |
# First pass: render OCR/hybrid pages once and keep PIL images for batch OCR.
|
| 1011 |
ocr_targets = []
|
|
|
|
| 1012 |
for page_data in profile.get("pages", []):
|
| 1013 |
page_num = page_data["page_number"]
|
| 1014 |
route = page_data["route"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1015 |
|
| 1016 |
if route == "embedded_text":
|
| 1017 |
continue
|
| 1018 |
|
| 1019 |
render_path = None
|
| 1020 |
-
img = None
|
| 1021 |
if doc is not None:
|
| 1022 |
try:
|
| 1023 |
page = doc[page_num - 1]
|
| 1024 |
-
pix = page.get_pixmap(dpi=
|
| 1025 |
render_dir = RENDERS_DIR / book_id
|
| 1026 |
render_dir.mkdir(exist_ok=True)
|
| 1027 |
-
render_path = render_dir / f"{book_id}_page_{page_num:04d}
|
| 1028 |
pix.save(str(render_path))
|
| 1029 |
page_data["render_path"] = str(render_path.relative_to(SS_ROOT))
|
| 1030 |
-
page_data["render_dpi"] =
|
| 1031 |
-
|
| 1032 |
-
if surya is not None:
|
| 1033 |
-
from PIL import Image
|
| 1034 |
-
img = Image.open(render_path).convert("RGB")
|
| 1035 |
except Exception as e:
|
| 1036 |
log.append(log_line(f" ⚠ {book_id} p{page_num}: render failed ({e})"))
|
| 1037 |
|
| 1038 |
ocr_targets.append({
|
| 1039 |
"page_num": page_num,
|
| 1040 |
"route": route,
|
| 1041 |
-
"image": img,
|
| 1042 |
"render_path": page_data.get("render_path"),
|
| 1043 |
})
|
| 1044 |
|
|
@@ -1049,15 +1059,52 @@ def run_ocr(progress=gr.Progress(track_tqdm=False)) -> tuple:
|
|
| 1049 |
for start in range(0, len(ocr_targets), batch_size):
|
| 1050 |
batch = ocr_targets[start:start + batch_size]
|
| 1051 |
batch_pages = [item["page_num"] for item in batch]
|
| 1052 |
-
batch_images = [
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1053 |
|
| 1054 |
try:
|
| 1055 |
-
if
|
| 1056 |
-
raise RuntimeError("
|
| 1057 |
|
| 1058 |
if surya is not None:
|
| 1059 |
predictions = _run_surya_batch(batch_images, surya)
|
| 1060 |
-
for item, page_result in zip(
|
| 1061 |
regions, conf = _regions_from_page_result(page_result)
|
| 1062 |
ocr_lookup[item["page_num"]] = {
|
| 1063 |
"regions": regions,
|
|
@@ -1066,17 +1113,17 @@ def run_ocr(progress=gr.Progress(track_tqdm=False)) -> tuple:
|
|
| 1066 |
}
|
| 1067 |
else:
|
| 1068 |
fallback_preds = _run_tesseract_batch(batch_images)
|
| 1069 |
-
for item, pred in zip(
|
| 1070 |
ocr_lookup[item["page_num"]] = pred
|
| 1071 |
except Exception as e:
|
| 1072 |
# If Surya batch fails, try Tesseract for this batch before giving up.
|
| 1073 |
if surya is not None:
|
| 1074 |
log.append(log_line(f" ⚠ {book_id} batch {batch_pages[0]}-{batch_pages[-1]} Surya error: {e}; retrying with Tesseract"))
|
| 1075 |
fallback_preds = _run_tesseract_batch(batch_images)
|
| 1076 |
-
for item, pred in zip(
|
| 1077 |
ocr_lookup[item["page_num"]] = pred
|
| 1078 |
else:
|
| 1079 |
-
for item in
|
| 1080 |
ocr_lookup[item["page_num"]] = {
|
| 1081 |
"regions": [],
|
| 1082 |
"confidence": 0.0,
|
|
@@ -1096,7 +1143,7 @@ def run_ocr(progress=gr.Progress(track_tqdm=False)) -> tuple:
|
|
| 1096 |
route = page_data["route"]
|
| 1097 |
|
| 1098 |
progress(
|
| 1099 |
-
(processed_pages,
|
| 1100 |
desc=f"OCR {book_id} p{page_num}/{len(profile.get('pages', []))}",
|
| 1101 |
)
|
| 1102 |
|
|
@@ -1199,7 +1246,7 @@ def run_ocr(progress=gr.Progress(track_tqdm=False)) -> tuple:
|
|
| 1199 |
qdf = pd.concat([existing, qdf], ignore_index=True).drop_duplicates(subset=["region_id"])
|
| 1200 |
qdf.to_csv(QUEUE_CSV, index=False)
|
| 1201 |
|
| 1202 |
-
progress((
|
| 1203 |
save_manifest_df(df)
|
| 1204 |
return _ocr_status_html(), "\n".join(log)
|
| 1205 |
|
|
|
|
| 721 |
SS_SURYA_LOAD_TIMEOUT_SEC = max(1, int(os.environ.get("SS_SURYA_LOAD_TIMEOUT_SEC", "20")))
|
| 722 |
except Exception:
|
| 723 |
SS_SURYA_LOAD_TIMEOUT_SEC = 20
|
| 724 |
+
try:
|
| 725 |
+
SS_RENDER_DPI_SURYA = max(72, int(os.environ.get("SS_RENDER_DPI_SURYA", "300")))
|
| 726 |
+
except Exception:
|
| 727 |
+
SS_RENDER_DPI_SURYA = 300
|
| 728 |
+
try:
|
| 729 |
+
SS_RENDER_DPI_FALLBACK = max(72, int(os.environ.get("SS_RENDER_DPI_FALLBACK", "220")))
|
| 730 |
+
except Exception:
|
| 731 |
+
SS_RENDER_DPI_FALLBACK = 220
|
| 732 |
|
| 733 |
|
| 734 |
def _load_surya_runtime():
|
|
|
|
| 990 |
continue
|
| 991 |
total_pages_planned = max(total_pages_planned, 1)
|
| 992 |
processed_pages = 0
|
| 993 |
+
rendered_pages = 0
|
| 994 |
+
total_work_units = max(total_pages_planned * 2, 1)
|
| 995 |
|
| 996 |
for _, row in eligible.iterrows():
|
| 997 |
book_id = row["book_id"]
|
|
|
|
| 1019 |
|
| 1020 |
# First pass: render OCR/hybrid pages once and keep PIL images for batch OCR.
|
| 1021 |
ocr_targets = []
|
| 1022 |
+
render_dpi = SS_RENDER_DPI_SURYA if surya is not None else SS_RENDER_DPI_FALLBACK
|
| 1023 |
for page_data in profile.get("pages", []):
|
| 1024 |
page_num = page_data["page_number"]
|
| 1025 |
route = page_data["route"]
|
| 1026 |
+
rendered_pages += 1
|
| 1027 |
+
progress(
|
| 1028 |
+
(rendered_pages, total_work_units),
|
| 1029 |
+
desc=f"Rendering {book_id} p{page_num} @ {render_dpi}dpi",
|
| 1030 |
+
)
|
| 1031 |
|
| 1032 |
if route == "embedded_text":
|
| 1033 |
continue
|
| 1034 |
|
| 1035 |
render_path = None
|
|
|
|
| 1036 |
if doc is not None:
|
| 1037 |
try:
|
| 1038 |
page = doc[page_num - 1]
|
| 1039 |
+
pix = page.get_pixmap(dpi=render_dpi, alpha=False)
|
| 1040 |
render_dir = RENDERS_DIR / book_id
|
| 1041 |
render_dir.mkdir(exist_ok=True)
|
| 1042 |
+
render_path = render_dir / f"{book_id}_page_{page_num:04d}_{render_dpi}dpi.png"
|
| 1043 |
pix.save(str(render_path))
|
| 1044 |
page_data["render_path"] = str(render_path.relative_to(SS_ROOT))
|
| 1045 |
+
page_data["render_dpi"] = render_dpi
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1046 |
except Exception as e:
|
| 1047 |
log.append(log_line(f" ⚠ {book_id} p{page_num}: render failed ({e})"))
|
| 1048 |
|
| 1049 |
ocr_targets.append({
|
| 1050 |
"page_num": page_num,
|
| 1051 |
"route": route,
|
|
|
|
| 1052 |
"render_path": page_data.get("render_path"),
|
| 1053 |
})
|
| 1054 |
|
|
|
|
| 1059 |
for start in range(0, len(ocr_targets), batch_size):
|
| 1060 |
batch = ocr_targets[start:start + batch_size]
|
| 1061 |
batch_pages = [item["page_num"] for item in batch]
|
| 1062 |
+
batch_images = []
|
| 1063 |
+
batch_items_with_images = []
|
| 1064 |
+
try:
|
| 1065 |
+
from PIL import Image
|
| 1066 |
+
except Exception as e:
|
| 1067 |
+
Image = None
|
| 1068 |
+
log.append(log_line(f" ⚠ PIL unavailable for OCR batch ({e})"))
|
| 1069 |
+
|
| 1070 |
+
if Image is not None:
|
| 1071 |
+
for item in batch:
|
| 1072 |
+
rel_path = item.get("render_path")
|
| 1073 |
+
if not rel_path:
|
| 1074 |
+
ocr_lookup[item["page_num"]] = {
|
| 1075 |
+
"regions": [],
|
| 1076 |
+
"confidence": 0.0,
|
| 1077 |
+
"method": "error-no-render-path",
|
| 1078 |
+
}
|
| 1079 |
+
continue
|
| 1080 |
+
|
| 1081 |
+
render_abs = SS_ROOT / rel_path
|
| 1082 |
+
if not render_abs.exists():
|
| 1083 |
+
ocr_lookup[item["page_num"]] = {
|
| 1084 |
+
"regions": [],
|
| 1085 |
+
"confidence": 0.0,
|
| 1086 |
+
"method": "error-render-missing",
|
| 1087 |
+
}
|
| 1088 |
+
continue
|
| 1089 |
+
|
| 1090 |
+
try:
|
| 1091 |
+
img = Image.open(render_abs).convert("RGB")
|
| 1092 |
+
batch_images.append(img)
|
| 1093 |
+
batch_items_with_images.append(item)
|
| 1094 |
+
except Exception as e:
|
| 1095 |
+
ocr_lookup[item["page_num"]] = {
|
| 1096 |
+
"regions": [],
|
| 1097 |
+
"confidence": 0.0,
|
| 1098 |
+
"method": f"error-open-image ({e})",
|
| 1099 |
+
}
|
| 1100 |
|
| 1101 |
try:
|
| 1102 |
+
if not batch_items_with_images:
|
| 1103 |
+
raise RuntimeError("No render images available in this OCR batch.")
|
| 1104 |
|
| 1105 |
if surya is not None:
|
| 1106 |
predictions = _run_surya_batch(batch_images, surya)
|
| 1107 |
+
for item, page_result in zip(batch_items_with_images, predictions):
|
| 1108 |
regions, conf = _regions_from_page_result(page_result)
|
| 1109 |
ocr_lookup[item["page_num"]] = {
|
| 1110 |
"regions": regions,
|
|
|
|
| 1113 |
}
|
| 1114 |
else:
|
| 1115 |
fallback_preds = _run_tesseract_batch(batch_images)
|
| 1116 |
+
for item, pred in zip(batch_items_with_images, fallback_preds):
|
| 1117 |
ocr_lookup[item["page_num"]] = pred
|
| 1118 |
except Exception as e:
|
| 1119 |
# If Surya batch fails, try Tesseract for this batch before giving up.
|
| 1120 |
if surya is not None:
|
| 1121 |
log.append(log_line(f" ⚠ {book_id} batch {batch_pages[0]}-{batch_pages[-1]} Surya error: {e}; retrying with Tesseract"))
|
| 1122 |
fallback_preds = _run_tesseract_batch(batch_images)
|
| 1123 |
+
for item, pred in zip(batch_items_with_images, fallback_preds):
|
| 1124 |
ocr_lookup[item["page_num"]] = pred
|
| 1125 |
else:
|
| 1126 |
+
for item in batch_items_with_images:
|
| 1127 |
ocr_lookup[item["page_num"]] = {
|
| 1128 |
"regions": [],
|
| 1129 |
"confidence": 0.0,
|
|
|
|
| 1143 |
route = page_data["route"]
|
| 1144 |
|
| 1145 |
progress(
|
| 1146 |
+
(total_pages_planned + processed_pages, total_work_units),
|
| 1147 |
desc=f"OCR {book_id} p{page_num}/{len(profile.get('pages', []))}",
|
| 1148 |
)
|
| 1149 |
|
|
|
|
| 1246 |
qdf = pd.concat([existing, qdf], ignore_index=True).drop_duplicates(subset=["region_id"])
|
| 1247 |
qdf.to_csv(QUEUE_CSV, index=False)
|
| 1248 |
|
| 1249 |
+
progress((total_work_units, total_work_units), desc="OCR complete")
|
| 1250 |
save_manifest_df(df)
|
| 1251 |
return _ocr_status_html(), "\n".join(log)
|
| 1252 |
|