UsmanGoraya commited on
Commit
c03caab
·
verified ·
1 Parent(s): 0947c97

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -0
app.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import fitz # PyMuPDF
3
+ import numpy as np
4
+ import pandas as pd
5
+ from PIL import Image
6
+ import io
7
+
8
+ def extract_pdf_images(pdf_bytes):
9
+ doc = fitz.open(stream=pdf_bytes, filetype="pdf")
10
+ images = []
11
+ for page in doc:
12
+ pix = page.get_pixmap(matrix=fitz.Matrix(2, 2))
13
+ img = Image.frombytes("RGB", [pix.width, pix.height], pix.samples)
14
+ images.append(img)
15
+ return images
16
+
17
+ def calculate_area(drawing_data, page_number, pdf_file, area_type):
18
+ if drawing_data is None or "layers" not in drawing_data:
19
+ return None, "No drawing found.", None
20
+
21
+ try:
22
+ coords = []
23
+ for layer in drawing_data["layers"]:
24
+ for shape in layer["paths"]:
25
+ if shape["type"] == "polygon":
26
+ coords.extend([[pt["x"], pt["y"]] for pt in shape["points"]])
27
+
28
+ coords = np.array(coords)
29
+ if len(coords) < 3:
30
+ return None, "Draw a closed polygon to calculate area.", None
31
+
32
+ area_px = 0.5 * np.abs(np.dot(coords[:, 0], np.roll(coords[:, 1], 1)) -
33
+ np.dot(coords[:, 1], np.roll(coords[:, 0], 1)))
34
+ area_sft = area_px / (96**2) * 144
35
+
36
+ rd_label = f"Page {page_number + 1}"
37
+ result_df = pd.DataFrame([{
38
+ "RD": rd_label,
39
+ "Area Type": area_type,
40
+ "Area (sq.ft)": round(area_sft, 2)
41
+ }])
42
+
43
+ excel_io = io.BytesIO()
44
+ with pd.ExcelWriter(excel_io, engine="openpyxl") as writer:
45
+ result_df.to_excel(writer, index=False, sheet_name="Area Summary")
46
+ excel_bytes = excel_io.getvalue()
47
+
48
+ return f"Estimated {area_type}: {area_sft:.2f} sq.ft", None, excel_bytes
49
+ except Exception as e:
50
+ return None, str(e), None
51
+
52
+ with gr.Blocks() as demo:
53
+ gr.Markdown("## 📐 Canal Cross Section Area Calculator (Gradio Version)")
54
+ gr.Markdown("Upload a multi-page PDF of canal cross sections. Select a page, draw polygon on the image, and compute area (in sqft).")
55
+
56
+ pdf_input = gr.File(label="📄 Upload PDF", type="binary")
57
+ area_type = gr.Radio(choices=["Cutting Area", "Filling Area"], value="Cutting Area", label="Area Type")
58
+ page_slider = gr.Slider(minimum=0, maximum=0, step=1, label="Select Page")
59
+ image_display = gr.Image(label="Cross Section Page", interactive=False)
60
+ drawing = gr.Sketchpad(label="Draw Area on Image", shape="polygon")
61
+ calculate_btn = gr.Button("🧮 Calculate Area")
62
+ result_text = gr.Textbox(label="Result")
63
+ download_excel = gr.File(label="📥 Download Excel", interactive=False)
64
+ error_output = gr.Textbox(label="Errors", visible=False)
65
+
66
+ def load_pdf(pdf_file):
67
+ if pdf_file is None:
68
+ return gr.Image.update(value=None), gr.update(maximum=0), None
69
+ images = extract_pdf_images(pdf_file)
70
+ return images[0], gr.update(maximum=len(images) - 1), images
71
+
72
+ def update_page(images, page_index):
73
+ return images[page_index]
74
+
75
+ pdf_file_state = gr.State()
76
+ images_state = gr.State()
77
+
78
+ pdf_input.change(load_pdf, inputs=[pdf_input], outputs=[image_display, page_slider, images_state])
79
+ page_slider.change(update_page, inputs=[images_state, page_slider], outputs=image_display)
80
+
81
+ calculate_btn.click(
82
+ calculate_area,
83
+ inputs=[drawing, page_slider, pdf_input, area_type],
84
+ outputs=[result_text, error_output, download_excel]
85
+ )
86
+
87
+ demo.launch()