Pointf5ive commited on
Commit
16b10a3
·
1 Parent(s): 8c23eee

Fix Tesseract fallback batch loading and OCR progress visibility

Browse files
Files changed (1) hide show
  1. 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=300, alpha=False)
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}_300dpi.png"
1028
  pix.save(str(render_path))
1029
  page_data["render_path"] = str(render_path.relative_to(SS_ROOT))
1030
- page_data["render_dpi"] = 300
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 = [item["image"] for item in batch if item["image"] is not None]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1053
 
1054
  try:
1055
- if len(batch_images) != len(batch):
1056
- raise RuntimeError("One or more page renders missing for OCR batch.")
1057
 
1058
  if surya is not None:
1059
  predictions = _run_surya_batch(batch_images, surya)
1060
- for item, page_result in zip(batch, predictions):
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(batch, fallback_preds):
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(batch, fallback_preds):
1077
  ocr_lookup[item["page_num"]] = pred
1078
  else:
1079
- for item in batch:
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, total_pages_planned),
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((total_pages_planned, total_pages_planned), desc="OCR complete")
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