Update app.py
Browse files
app.py
CHANGED
|
@@ -352,6 +352,19 @@
|
|
| 352 |
|
| 353 |
|
| 354 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 355 |
import fitz # PyMuPDF
|
| 356 |
import numpy as np
|
| 357 |
import cv2
|
|
@@ -532,19 +545,19 @@ def run_yolo_detection_and_count(
|
|
| 532 |
|
| 533 |
|
| 534 |
# ============================================================================
|
| 535 |
-
# --- MAIN DOCUMENT PROCESSING FUNCTION (
|
| 536 |
# ============================================================================
|
| 537 |
|
| 538 |
-
# NOTE: The return signature now
|
| 539 |
-
def run_single_pdf_preprocessing(pdf_path: str) -> Tuple[int, int, int, str, float, Dict[
|
| 540 |
"""
|
| 541 |
-
Runs the pipeline, returns counts, report, total time, page counts dict, and empty list.
|
| 542 |
"""
|
| 543 |
global GLOBAL_FIGURE_COUNT, GLOBAL_EQUATION_COUNT
|
| 544 |
start_time = time.time()
|
| 545 |
log_messages = []
|
| 546 |
|
| 547 |
-
#
|
| 548 |
equation_counts_per_page: Dict[int, int] = {}
|
| 549 |
|
| 550 |
# Reset globals
|
|
@@ -555,7 +568,6 @@ def run_single_pdf_preprocessing(pdf_path: str) -> Tuple[int, int, int, str, flo
|
|
| 555 |
t0 = time.time()
|
| 556 |
if not os.path.exists(pdf_path):
|
| 557 |
report = f"β FATAL ERROR: Input PDF not found at {pdf_path}."
|
| 558 |
-
# Add the new return value (empty dict)
|
| 559 |
return 0, 0, 0, report, time.time() - start_time, {}, []
|
| 560 |
|
| 561 |
try:
|
|
@@ -563,7 +575,6 @@ def run_single_pdf_preprocessing(pdf_path: str) -> Tuple[int, int, int, str, flo
|
|
| 563 |
logging.warning(f"β
Loaded YOLO model from: {WEIGHTS_PATH}")
|
| 564 |
except Exception as e:
|
| 565 |
report = f"β ERROR loading YOLO model: {e}\n(Ensure 'best.pt' is available and valid.)"
|
| 566 |
-
# Add the new return value (empty dict)
|
| 567 |
return 0, 0, 0, report, time.time() - start_time, {}, []
|
| 568 |
t1 = time.time()
|
| 569 |
log_messages.append(f"Model Loading Time: {t1-t0:.4f}s")
|
|
@@ -576,7 +587,6 @@ def run_single_pdf_preprocessing(pdf_path: str) -> Tuple[int, int, int, str, flo
|
|
| 576 |
logging.warning(f"β
Opened PDF with {doc.page_count} pages")
|
| 577 |
except Exception as e:
|
| 578 |
report = f"β ERROR loading PDF file: {e}"
|
| 579 |
-
# Add the new return value (empty dict)
|
| 580 |
return 0, 0, 0, report, time.time() - start_time, {}, []
|
| 581 |
t3 = time.time()
|
| 582 |
log_messages.append(f"PDF Initialization Time: {t3-t2:.4f}s")
|
|
@@ -605,7 +615,7 @@ def run_single_pdf_preprocessing(pdf_path: str) -> Tuple[int, int, int, str, flo
|
|
| 605 |
page_equations, _ = run_yolo_detection_and_count(original_img, model, page_num)
|
| 606 |
detect_time = time.time() - detect_start
|
| 607 |
|
| 608 |
-
#
|
| 609 |
equation_counts_per_page[page_num] = page_equations
|
| 610 |
|
| 611 |
page_total_time = time.time() - page_start_time
|
|
@@ -616,6 +626,11 @@ def run_single_pdf_preprocessing(pdf_path: str) -> Tuple[int, int, int, str, flo
|
|
| 616 |
detection_loop_time = t5 - t4
|
| 617 |
log_messages.append(f"Total Detection Loop Time ({total_pages} pages): {detection_loop_time:.4f}s")
|
| 618 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 619 |
# 4. Final Report Generation
|
| 620 |
total_execution_time = t5 - start_time
|
| 621 |
|
|
@@ -632,38 +647,37 @@ def run_single_pdf_preprocessing(pdf_path: str) -> Tuple[int, int, int, str, flo
|
|
| 632 |
f"\n```"
|
| 633 |
)
|
| 634 |
|
| 635 |
-
# Return the
|
| 636 |
-
return total_pages, GLOBAL_EQUATION_COUNT, GLOBAL_FIGURE_COUNT, report, total_execution_time,
|
| 637 |
|
| 638 |
|
| 639 |
# ============================================================================
|
| 640 |
# --- GRADIO INTERFACE FUNCTION (Updated) ---
|
| 641 |
# ============================================================================
|
| 642 |
|
| 643 |
-
|
| 644 |
-
def gradio_process_pdf(pdf_file) -> Tuple[str, str, str, str, Dict[int, int], List[str]]:
|
| 645 |
"""
|
| 646 |
Gradio wrapper function to handle file upload and return results.
|
| 647 |
"""
|
| 648 |
if pdf_file is None:
|
| 649 |
-
# Return an empty dict
|
| 650 |
return "N/A", "N/A", "N/A", "Please upload a PDF file.", {}, []
|
| 651 |
|
| 652 |
pdf_path = pdf_file.name
|
| 653 |
|
| 654 |
try:
|
| 655 |
-
# Unpack the new return value: equation_counts_per_page
|
| 656 |
num_pages, num_equations, num_figures, report, total_time, equation_counts_per_page, _ = run_single_pdf_preprocessing(
|
| 657 |
pdf_path
|
| 658 |
)
|
| 659 |
|
| 660 |
-
# Return results (
|
| 661 |
return str(num_pages), str(num_equations), str(num_figures), report, equation_counts_per_page, []
|
| 662 |
|
| 663 |
except Exception as e:
|
| 664 |
error_msg = f"An unexpected error occurred: {e}"
|
| 665 |
logging.error(error_msg, exc_info=True)
|
| 666 |
-
# Return an empty dict
|
| 667 |
return "Error", "Error", "Error", error_msg, {}, []
|
| 668 |
|
| 669 |
|
|
@@ -699,13 +713,13 @@ if __name__ == "__main__":
|
|
| 699 |
interface = gr.Interface(
|
| 700 |
fn=gradio_process_pdf,
|
| 701 |
inputs=input_file,
|
| 702 |
-
# Outputs
|
| 703 |
outputs=[
|
| 704 |
output_pages,
|
| 705 |
output_equations,
|
| 706 |
output_figures,
|
| 707 |
output_report,
|
| 708 |
-
output_page_counts,
|
| 709 |
output_gallery
|
| 710 |
],
|
| 711 |
title="π YOLO Counting with Per-Page Data & Timing",
|
|
@@ -716,4 +730,6 @@ if __name__ == "__main__":
|
|
| 716 |
)
|
| 717 |
|
| 718 |
print("\nStarting Gradio application...")
|
| 719 |
-
interface.launch(inbrowser=True)
|
|
|
|
|
|
|
|
|
| 352 |
|
| 353 |
|
| 354 |
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
|
| 359 |
+
|
| 360 |
+
|
| 361 |
+
|
| 362 |
+
|
| 363 |
+
|
| 364 |
+
|
| 365 |
+
|
| 366 |
+
|
| 367 |
+
|
| 368 |
import fitz # PyMuPDF
|
| 369 |
import numpy as np
|
| 370 |
import cv2
|
|
|
|
| 545 |
|
| 546 |
|
| 547 |
# ============================================================================
|
| 548 |
+
# --- MAIN DOCUMENT PROCESSING FUNCTION (Fixed for JSON serialization) ---
|
| 549 |
# ============================================================================
|
| 550 |
|
| 551 |
+
# NOTE: The return signature now uses Dict[str, int] for the equation counts
|
| 552 |
+
def run_single_pdf_preprocessing(pdf_path: str) -> Tuple[int, int, int, str, float, Dict[str, int], List[str]]:
|
| 553 |
"""
|
| 554 |
+
Runs the pipeline, returns counts, report, total time, page counts dict (str keys), and empty list.
|
| 555 |
"""
|
| 556 |
global GLOBAL_FIGURE_COUNT, GLOBAL_EQUATION_COUNT
|
| 557 |
start_time = time.time()
|
| 558 |
log_messages = []
|
| 559 |
|
| 560 |
+
# Dictionary to store {page_number (int): equation_count (int)}
|
| 561 |
equation_counts_per_page: Dict[int, int] = {}
|
| 562 |
|
| 563 |
# Reset globals
|
|
|
|
| 568 |
t0 = time.time()
|
| 569 |
if not os.path.exists(pdf_path):
|
| 570 |
report = f"β FATAL ERROR: Input PDF not found at {pdf_path}."
|
|
|
|
| 571 |
return 0, 0, 0, report, time.time() - start_time, {}, []
|
| 572 |
|
| 573 |
try:
|
|
|
|
| 575 |
logging.warning(f"β
Loaded YOLO model from: {WEIGHTS_PATH}")
|
| 576 |
except Exception as e:
|
| 577 |
report = f"β ERROR loading YOLO model: {e}\n(Ensure 'best.pt' is available and valid.)"
|
|
|
|
| 578 |
return 0, 0, 0, report, time.time() - start_time, {}, []
|
| 579 |
t1 = time.time()
|
| 580 |
log_messages.append(f"Model Loading Time: {t1-t0:.4f}s")
|
|
|
|
| 587 |
logging.warning(f"β
Opened PDF with {doc.page_count} pages")
|
| 588 |
except Exception as e:
|
| 589 |
report = f"β ERROR loading PDF file: {e}"
|
|
|
|
| 590 |
return 0, 0, 0, report, time.time() - start_time, {}, []
|
| 591 |
t3 = time.time()
|
| 592 |
log_messages.append(f"PDF Initialization Time: {t3-t2:.4f}s")
|
|
|
|
| 615 |
page_equations, _ = run_yolo_detection_and_count(original_img, model, page_num)
|
| 616 |
detect_time = time.time() - detect_start
|
| 617 |
|
| 618 |
+
# Store the count in the dictionary (INT keys)
|
| 619 |
equation_counts_per_page[page_num] = page_equations
|
| 620 |
|
| 621 |
page_total_time = time.time() - page_start_time
|
|
|
|
| 626 |
detection_loop_time = t5 - t4
|
| 627 |
log_messages.append(f"Total Detection Loop Time ({total_pages} pages): {detection_loop_time:.4f}s")
|
| 628 |
|
| 629 |
+
# FIX APPLIED HERE: Convert integer keys to string keys for JSON serialization
|
| 630 |
+
equation_counts_per_page_str_keys: Dict[str, int] = {
|
| 631 |
+
str(k): v for k, v in equation_counts_per_page.items()
|
| 632 |
+
}
|
| 633 |
+
|
| 634 |
# 4. Final Report Generation
|
| 635 |
total_execution_time = t5 - start_time
|
| 636 |
|
|
|
|
| 647 |
f"\n```"
|
| 648 |
)
|
| 649 |
|
| 650 |
+
# Return the dictionary with string keys
|
| 651 |
+
return total_pages, GLOBAL_EQUATION_COUNT, GLOBAL_FIGURE_COUNT, report, total_execution_time, equation_counts_per_page_str_keys, []
|
| 652 |
|
| 653 |
|
| 654 |
# ============================================================================
|
| 655 |
# --- GRADIO INTERFACE FUNCTION (Updated) ---
|
| 656 |
# ============================================================================
|
| 657 |
|
| 658 |
+
def gradio_process_pdf(pdf_file) -> Tuple[str, str, str, str, Dict[str, int], List[str]]:
|
|
|
|
| 659 |
"""
|
| 660 |
Gradio wrapper function to handle file upload and return results.
|
| 661 |
"""
|
| 662 |
if pdf_file is None:
|
| 663 |
+
# Return an empty dict with string keys
|
| 664 |
return "N/A", "N/A", "N/A", "Please upload a PDF file.", {}, []
|
| 665 |
|
| 666 |
pdf_path = pdf_file.name
|
| 667 |
|
| 668 |
try:
|
| 669 |
+
# Unpack the new return value: equation_counts_per_page (with string keys)
|
| 670 |
num_pages, num_equations, num_figures, report, total_time, equation_counts_per_page, _ = run_single_pdf_preprocessing(
|
| 671 |
pdf_path
|
| 672 |
)
|
| 673 |
|
| 674 |
+
# Return results (6 items now)
|
| 675 |
return str(num_pages), str(num_equations), str(num_figures), report, equation_counts_per_page, []
|
| 676 |
|
| 677 |
except Exception as e:
|
| 678 |
error_msg = f"An unexpected error occurred: {e}"
|
| 679 |
logging.error(error_msg, exc_info=True)
|
| 680 |
+
# Return an empty dict on error
|
| 681 |
return "Error", "Error", "Error", error_msg, {}, []
|
| 682 |
|
| 683 |
|
|
|
|
| 713 |
interface = gr.Interface(
|
| 714 |
fn=gradio_process_pdf,
|
| 715 |
inputs=input_file,
|
| 716 |
+
# Outputs list remains the same, but the JSON component now receives string keys.
|
| 717 |
outputs=[
|
| 718 |
output_pages,
|
| 719 |
output_equations,
|
| 720 |
output_figures,
|
| 721 |
output_report,
|
| 722 |
+
output_page_counts,
|
| 723 |
output_gallery
|
| 724 |
],
|
| 725 |
title="π YOLO Counting with Per-Page Data & Timing",
|
|
|
|
| 730 |
)
|
| 731 |
|
| 732 |
print("\nStarting Gradio application...")
|
| 733 |
+
interface.launch(inbrowser=True)
|
| 734 |
+
|
| 735 |
+
|