Area_Defining / app.py
UsmanGoraya's picture
Update app.py
62927c1 verified
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()