Pointf5ive commited on
Commit
918c9d8
·
1 Parent(s): 1754c00

Add manual OCR page exclusion by PDF page number

Browse files
Files changed (1) hide show
  1. smoke_signal_tab.py +47 -6
smoke_signal_tab.py CHANGED
@@ -1238,7 +1238,7 @@ def _run_tesseract_batch(images):
1238
  return outputs
1239
 
1240
 
1241
- def run_ocr(page_selection: str = "", replace_book_queue: bool = True) -> tuple:
1242
  """Run Surya OCR on all profiled PDFs."""
1243
  df = load_manifest_df()
1244
  debug = f"[DEBUG] SS_ROOT={SS_ROOT}\nMANIFEST_CSV={MANIFEST_CSV}\nCSV exists={MANIFEST_CSV.exists()}\n"
@@ -1269,11 +1269,26 @@ def run_ocr(page_selection: str = "", replace_book_queue: bool = True) -> tuple:
1269
  selection_set, selection_error = _parse_page_selection(page_selection)
1270
  if selection_error:
1271
  return _ocr_status_html(), f"{debug}Invalid page selection: {selection_error}"
 
 
 
 
 
 
 
 
1272
  if selection_set is None:
1273
  log.append(log_line("ℹ Page selection: all pages"))
1274
  else:
1275
  selected_preview = ",".join(str(p) for p in sorted(selection_set))
1276
  log.append(log_line(f"ℹ Page selection: {selected_preview}"))
 
 
 
 
 
 
 
1277
 
1278
  surya, surya_error, reused = _get_surya_runtime_with_timeout(SS_SURYA_LOAD_TIMEOUT_SEC)
1279
  if surya:
@@ -1308,14 +1323,33 @@ def run_ocr(page_selection: str = "", replace_book_queue: bool = True) -> tuple:
1308
  pages_all = profile.get("pages", [])
1309
  page_numbers = [int(p.get("page_number", 0) or 0) for p in pages_all]
1310
  max_page = max(page_numbers) if page_numbers else None
1311
- selected_pages_for_book = selection_set
1312
- if selection_set is not None:
 
1313
  selected_pages_for_book, sel_err = _parse_page_selection(page_selection, max_page=max_page)
1314
  if sel_err:
1315
  log.append(log_line(f"⚠ {book_id}: {sel_err}"))
1316
  continue
1317
- selected_preview = ",".join(str(p) for p in sorted(selected_pages_for_book))
1318
- log.append(log_line(f"ℹ {book_id}: selected pages {selected_preview}"))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1319
  processed_books.append(book_id)
1320
 
1321
  ocr_pages = []
@@ -1721,6 +1755,8 @@ def save_review_decision(idx: int, final_text: str, action: str, reviewer: str,
1721
 
1722
  decided_ids = set(d_df["region_id"].tolist()) if not d_df.empty else set()
1723
  pending = q_df[~q_df["region_id"].isin(decided_ids)]
 
 
1724
  if pending.empty:
1725
  return "All done!", *get_review_item(0)[1:]
1726
 
@@ -2027,6 +2063,11 @@ def smoke_signal_tab():
2027
  placeholder="all or e.g. 7 or 3-8 or 1,4,9-12",
2028
  lines=1,
2029
  )
 
 
 
 
 
2030
  ocr_replace_queue = gr.Checkbox(
2031
  label="Replace existing review queue entries for processed books",
2032
  value=True,
@@ -2036,7 +2077,7 @@ def smoke_signal_tab():
2036
 
2037
  ocr_run_event = ocr_btn.click(
2038
  run_ocr,
2039
- inputs=[ocr_page_selection, ocr_replace_queue],
2040
  outputs=[ocr_status, ocr_log],
2041
  show_progress="minimal",
2042
  )
 
1238
  return outputs
1239
 
1240
 
1241
+ def run_ocr(page_selection: str = "", page_exclusion: str = "", replace_book_queue: bool = True) -> tuple:
1242
  """Run Surya OCR on all profiled PDFs."""
1243
  df = load_manifest_df()
1244
  debug = f"[DEBUG] SS_ROOT={SS_ROOT}\nMANIFEST_CSV={MANIFEST_CSV}\nCSV exists={MANIFEST_CSV.exists()}\n"
 
1269
  selection_set, selection_error = _parse_page_selection(page_selection)
1270
  if selection_error:
1271
  return _ocr_status_html(), f"{debug}Invalid page selection: {selection_error}"
1272
+ exclusion_spec = (page_exclusion or "").strip().lower()
1273
+ exclusion_request = None if exclusion_spec in ("", "none", "-") else exclusion_spec
1274
+ if exclusion_request is not None:
1275
+ exclusion_set, exclusion_error = _parse_page_selection(exclusion_request)
1276
+ if exclusion_error:
1277
+ return _ocr_status_html(), f"{debug}Invalid exclusion selection: {exclusion_error}"
1278
+ else:
1279
+ exclusion_set = set()
1280
  if selection_set is None:
1281
  log.append(log_line("ℹ Page selection: all pages"))
1282
  else:
1283
  selected_preview = ",".join(str(p) for p in sorted(selection_set))
1284
  log.append(log_line(f"ℹ Page selection: {selected_preview}"))
1285
+ if exclusion_request is None:
1286
+ log.append(log_line("ℹ Page exclusion: none"))
1287
+ elif exclusion_set is None:
1288
+ log.append(log_line("ℹ Page exclusion: all selected pages"))
1289
+ else:
1290
+ excluded_preview = ",".join(str(p) for p in sorted(exclusion_set))
1291
+ log.append(log_line(f"ℹ Page exclusion: {excluded_preview}"))
1292
 
1293
  surya, surya_error, reused = _get_surya_runtime_with_timeout(SS_SURYA_LOAD_TIMEOUT_SEC)
1294
  if surya:
 
1323
  pages_all = profile.get("pages", [])
1324
  page_numbers = [int(p.get("page_number", 0) or 0) for p in pages_all]
1325
  max_page = max(page_numbers) if page_numbers else None
1326
+ if selection_set is None:
1327
+ selected_pages_for_book = set(page_numbers)
1328
+ else:
1329
  selected_pages_for_book, sel_err = _parse_page_selection(page_selection, max_page=max_page)
1330
  if sel_err:
1331
  log.append(log_line(f"⚠ {book_id}: {sel_err}"))
1332
  continue
1333
+ if selected_pages_for_book is None:
1334
+ selected_pages_for_book = set(page_numbers)
1335
+
1336
+ if exclusion_request is None:
1337
+ excluded_pages_for_book: set[int] = set()
1338
+ else:
1339
+ excluded_pages_for_book, excl_err = _parse_page_selection(exclusion_request, max_page=max_page)
1340
+ if excl_err:
1341
+ log.append(log_line(f"⚠ {book_id}: {excl_err}"))
1342
+ continue
1343
+ if excluded_pages_for_book is None:
1344
+ excluded_pages_for_book = set(page_numbers)
1345
+
1346
+ selected_pages_for_book = set(selected_pages_for_book) - set(excluded_pages_for_book)
1347
+ if not selected_pages_for_book:
1348
+ log.append(log_line(f"⚠ {book_id}: no pages left after applying selection/exclusion"))
1349
+ continue
1350
+
1351
+ selected_preview = ",".join(str(p) for p in sorted(selected_pages_for_book))
1352
+ log.append(log_line(f"ℹ {book_id}: effective selected pages {selected_preview}"))
1353
  processed_books.append(book_id)
1354
 
1355
  ocr_pages = []
 
1755
 
1756
  decided_ids = set(d_df["region_id"].tolist()) if not d_df.empty else set()
1757
  pending = q_df[~q_df["region_id"].isin(decided_ids)]
1758
+ if not pending.empty and {"book_id", "page"}.issubset(pending.columns):
1759
+ pending = pending.sort_values(["book_id", "page"], ascending=[True, True], kind="stable")
1760
  if pending.empty:
1761
  return "All done!", *get_review_item(0)[1:]
1762
 
 
2063
  placeholder="all or e.g. 7 or 3-8 or 1,4,9-12",
2064
  lines=1,
2065
  )
2066
+ ocr_page_exclusion = gr.Textbox(
2067
+ label="Pages to Exclude (optional)",
2068
+ placeholder="e.g. 1,2,3,17,25 (PDF page numbers)",
2069
+ lines=1,
2070
+ )
2071
  ocr_replace_queue = gr.Checkbox(
2072
  label="Replace existing review queue entries for processed books",
2073
  value=True,
 
2077
 
2078
  ocr_run_event = ocr_btn.click(
2079
  run_ocr,
2080
+ inputs=[ocr_page_selection, ocr_page_exclusion, ocr_replace_queue],
2081
  outputs=[ocr_status, ocr_log],
2082
  show_progress="minimal",
2083
  )