Spaces:
Runtime error
Runtime error
| import gradio as gr | |
| try: | |
| import fitz # from PyMuPDF | |
| except ImportError: | |
| raise ImportError("PyMuPDF is not installed. Make sure to include 'pymupdf' in your requirements.txt.") | |
| import numpy as np | |
| import pandas as pd | |
| from PIL import Image | |
| import io | |
| def extract_pdf_images(pdf_bytes): | |
| doc = fitz.open(stream=pdf_bytes, filetype="pdf") | |
| images = [] | |
| for page in doc: | |
| pix = page.get_pixmap(matrix=fitz.Matrix(2, 2)) | |
| img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples) | |
| images.append(img) | |
| return images | |
| def calculate_area(drawing_data, page_number, pdf_file, area_type): | |
| if drawing_data is None or "layers" not in drawing_data: | |
| return None, "No drawing found.", None | |
| try: | |
| coords = [] | |
| for layer in drawing_data["layers"]: | |
| for shape in layer["paths"]: | |
| if shape["type"] == "polygon": | |
| coords.extend([[pt["x"], pt["y"]] for pt in shape["points"]]) | |
| coords = np.array(coords) | |
| if len(coords) < 3: | |
| return None, "Draw a closed polygon to calculate area.", None | |
| area_px = 0.5 * np.abs(np.dot(coords[:, 0], np.roll(coords[:, 1], 1)) - | |
| np.dot(coords[:, 1], np.roll(coords[:, 0], 1))) | |
| area_sft = area_px / (96**2) * 144 | |
| rd_label = f"Page {page_number + 1}" | |
| result_df = pd.DataFrame([{ | |
| "RD": rd_label, | |
| "Area Type": area_type, | |
| "Area (sq.ft)": round(area_sft, 2) | |
| }]) | |
| excel_io = io.BytesIO() | |
| with pd.ExcelWriter(excel_io, engine="openpyxl") as writer: | |
| result_df.to_excel(writer, index=False, sheet_name="Area Summary") | |
| excel_bytes = excel_io.getvalue() | |
| return f"Estimated {area_type}: {area_sft:.2f} sq.ft", None, excel_bytes | |
| except Exception as e: | |
| return None, str(e), None | |
| with gr.Blocks() as demo: | |
| gr.Markdown("## ๐ Canal Cross Section Area Calculator (Gradio Version)") | |
| gr.Markdown("Upload a multi-page PDF of canal cross sections. Select a page, draw polygon on the image, and compute area (in sqft).") | |
| pdf_input = gr.File(label="๐ Upload PDF", type="binary") | |
| area_type = gr.Radio(choices=["Cutting Area", "Filling Area"], value="Cutting Area", label="Area Type") | |
| page_slider = gr.Slider(minimum=0, maximum=0, step=1, label="Select Page") | |
| image_display = gr.Image(label="Cross Section Page", interactive=False) | |
| drawing = gr.Sketchpad(label="Draw Area on Image", shape="polygon") | |
| calculate_btn = gr.Button("๐งฎ Calculate Area") | |
| result_text = gr.Textbox(label="Result") | |
| download_excel = gr.File(label="๐ฅ Download Excel", interactive=False) | |
| error_output = gr.Textbox(label="Errors", visible=False) | |
| def load_pdf(pdf_file): | |
| if pdf_file is None: | |
| return gr.Image.update(value=None), gr.update(maximum=0), None | |
| images = extract_pdf_images(pdf_file) | |
| return images[0], gr.update(maximum=len(images) - 1), images | |
| def update_page(images, page_index): | |
| return images[page_index] | |
| pdf_file_state = gr.State() | |
| images_state = gr.State() | |
| pdf_input.change(load_pdf, inputs=[pdf_input], outputs=[image_display, page_slider, images_state]) | |
| page_slider.change(update_page, inputs=[images_state, page_slider], outputs=image_display) | |
| calculate_btn.click( | |
| calculate_area, | |
| inputs=[drawing, page_slider, pdf_input, area_type], | |
| outputs=[result_text, error_output, download_excel] | |
| ) | |
| demo.launch() | |