HapiHygi-Innovations commited on
Commit
6409e2f
Β·
verified Β·
1 Parent(s): b7ebbb5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +629 -25
app.py CHANGED
@@ -1364,6 +1364,142 @@ def supa_login(email, password):
1364
  except Exception as e:
1365
  return f"❌ Login error: {e}", True
1366
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1367
  # Final app logic (your current full app can go here)
1368
  def launch_main_app():
1369
  import gradio as gr
@@ -1462,6 +1598,8 @@ def launch_main_app():
1462
  models_coinref_p2 = gr.State(None)
1463
  device_p2 = gr.State(None)
1464
  gallery_segmentation_p4 = gr.State()
 
 
1465
 
1466
  full_app_interface.load(
1467
  fn=lambda: [GLOBAL_HOLES, GLOBAL_RIM, GLOBAL_COIN, device_p2],
@@ -1708,6 +1846,20 @@ def launch_main_app():
1708
  download_all_file = gr.File(visible=False)
1709
  download_all_error = gr.File(visible=False)
1710
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1711
  with gr.Column(visible=False) as col:
1712
  gr.Markdown("## 🎯 Prediction Accuracy Analysis", elem_id="centered-title")
1713
 
@@ -1771,6 +1923,20 @@ def launch_main_app():
1771
  error_plot = gr.Image(label="πŸ“‰ Error Plot", height=400, width=600, interactive=False, visible=False)
1772
  with gr.Row():
1773
  avg_error_text = gr.Textbox(label="🎯 Average Error %", interactive=False, elem_id='centered-title')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1774
 
1775
  run_pipeline_btn.click(fn=lambda: gr.update(visible=True), outputs=group_to_show)
1776
  run_pipeline_btn.click(fn=lambda: gr.update(value="πŸ”„ Processing... (Please Wait)"), outputs=process)
@@ -1927,6 +2093,437 @@ def launch_main_app():
1927
 
1928
  return zip_path, gr.update(value="")
1929
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1930
  submit_btn.click(
1931
  fn=lambda *args: (
1932
  compare_measurements(*args)[0],
@@ -1939,7 +2536,12 @@ def launch_main_app():
1939
  then(fn=download_all_results,
1940
  inputs=[a1, b1, c1, d1, e1, f1, g1, h1, a2, b2, c2, d2, e2, f2, g2, h2, avg_error_text, error_plot],
1941
  outputs=[download_all_error, progress]).\
1942
- then(upload_zip_error, inputs=[email, download_all_error], outputs=[])
 
 
 
 
 
1943
 
1944
  submit_btn.click(fn=lambda: gr.update(visible=True), inputs=[], outputs=[error])
1945
 
@@ -2220,29 +2822,12 @@ def launch_main_app():
2220
  remaining_lid_img_p12, remaining_str, out_image, top_width_str, a1, b1, c1, d1, e1, f1, g1, h1
2221
  ],
2222
  outputs=[download_all_file, progress]).\
2223
- then(upload_zip, inputs=[email, download_all_file], outputs=[col])
2224
-
2225
- with gr.Row():
2226
- gr.Markdown("")
2227
- with gr.Row():
2228
- gr.Markdown("")
2229
- with gr.Row():
2230
- gr.Markdown("")
2231
- with gr.Row():
2232
- gr.Markdown("\nFor any queries, Feel free to contact πŸ“§ core.atsc@gmail.com", elem_id='centered-title')
2233
-
2234
- with gr.Row():
2235
- gr.Markdown(
2236
- """
2237
- ---
2238
- #### πŸ‘¨β€πŸ’» Created by Heet Savaliya
2239
- πŸ“§ Email: savaliyaheet19@gmail.com
2240
- πŸ”— [LinkedIn](https://www.linkedin.com/in/heet-savaliya-03b863252/)
2241
- πŸ”— [GitHub](https://github.com/heetsavaliya)
2242
- Β© 2025 Heet Savaliya
2243
- """,
2244
- elem_id="footer-text",
2245
- )
2246
 
2247
  with gr.Blocks(title="πŸ§ͺ Toilet Segmentation & Measurement App") as full_app_interface:
2248
  auth_state = gr.State(False) # Used to track login state
@@ -2295,6 +2880,25 @@ with gr.Blocks(title="πŸ§ͺ Toilet Segmentation & Measurement App") as full_app_i
2295
 
2296
  auth_state.change(toggle_app, inputs=auth_state, outputs=protected_content)
2297
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2298
  # πŸš€ Launch App
2299
  if __name__ == "__main__":
2300
- full_app_interface.launch()
 
1364
  except Exception as e:
1365
  return f"❌ Login error: {e}", True
1366
 
1367
+ import matplotlib.pyplot as plt
1368
+ import matplotlib.patches as patches
1369
+ import numpy as np
1370
+ from PIL import Image
1371
+ import os
1372
+
1373
+ def draw_shapes_with_zorder(
1374
+ polygons_data=None,
1375
+ ellipses_data=None,
1376
+ filename="multiple_shapes.png",
1377
+ fig_size=(10, 8),
1378
+ transparent_bg=False
1379
+ ):
1380
+ fig, ax = plt.subplots(figsize=fig_size)
1381
+ ax.set_aspect('equal', adjustable='box')
1382
+ ax.set_axis_off()
1383
+ ax.set_facecolor('#f0f0f0')
1384
+
1385
+ min_x, max_x = float('inf'), float('-inf')
1386
+ min_y, max_y = float('inf'), float('-inf')
1387
+
1388
+ all_coords = []
1389
+ if polygons_data:
1390
+ for poly_info in polygons_data:
1391
+ points = poly_info.get('points')
1392
+ if points:
1393
+ all_coords.extend(points)
1394
+ polygon = patches.Polygon(
1395
+ points,
1396
+ closed=True,
1397
+ facecolor=poly_info.get('facecolor', '#ADD8E6'),
1398
+ edgecolor=poly_info.get('edgecolor', 'blue'),
1399
+ linewidth=poly_info.get('linewidth', 2),
1400
+ zorder=poly_info.get('zorder', 1)
1401
+ )
1402
+ ax.add_patch(polygon)
1403
+
1404
+ if ellipses_data:
1405
+ for ellipse_info in ellipses_data:
1406
+ e_cx = ellipse_info.get('center_x')
1407
+ e_cy = ellipse_info.get('center_y')
1408
+ e_w = ellipse_info.get('width')
1409
+ e_h = ellipse_info.get('height')
1410
+ e_angle = ellipse_info.get('angle', 0)
1411
+
1412
+ if e_cx is None or e_cy is None or e_w is None or e_h is None:
1413
+ continue
1414
+
1415
+ all_coords.append((e_cx - e_w / 2, e_cy - e_h / 2))
1416
+ all_coords.append((e_cx + e_w / 2, e_cy + e_h / 2))
1417
+ all_coords.append((e_cx - e_w / 2, e_cy + e_h / 2))
1418
+ all_coords.append((e_cx + e_w / 2, e_cy - e_h / 2))
1419
+
1420
+ ellipse = patches.Ellipse(
1421
+ (e_cx, e_cy),
1422
+ e_w,
1423
+ e_h,
1424
+ angle=e_angle,
1425
+ facecolor=ellipse_info.get('facecolor', '#FFD700'),
1426
+ edgecolor=ellipse_info.get('edgecolor', 'orange'),
1427
+ linewidth=ellipse_info.get('linewidth', 2),
1428
+ zorder=ellipse_info.get('zorder', 1)
1429
+ )
1430
+ ax.add_patch(ellipse)
1431
+
1432
+ if all_coords:
1433
+ coords_array = np.array(all_coords)
1434
+ min_x, min_y = np.min(coords_array, axis=0)
1435
+ max_x, max_y = np.max(coords_array, axis=0)
1436
+
1437
+ padding_x = (max_x - min_x) * 0.2 if (max_x - min_x) > 0 else 1.0
1438
+ padding_y = (max_y - min_y) * 0.2 if (max_y - min_y) > 0 else 1.0
1439
+
1440
+ ax.set_xlim(min_x - padding_x, max_x + padding_x)
1441
+ ax.set_ylim(min_y - padding_y, max_y + padding_y)
1442
+ else:
1443
+ ax.set_xlim(0, 10)
1444
+ ax.set_ylim(0, 8)
1445
+
1446
+ plt.savefig(filename, dpi=300, bbox_inches='tight', pad_inches=0, transparent=transparent_bg)
1447
+ plt.close(fig) # Close to avoid memory leak
1448
+
1449
+ return Image.open(filename) # Return as PIL.Image object for Gradio
1450
+
1451
+ # --- Example Usage ---
1452
+
1453
+ # Define data for multiple polygons
1454
+ my_polygons = [
1455
+ {
1456
+ 'points': [(0.56, 14.72), (0.56, 19.05), (19.5, 19.05), (19.5, 14.53)],
1457
+ 'facecolor': "#E6ADAD",
1458
+ 'edgecolor': 'brown',
1459
+ 'linewidth': 0,
1460
+ 'zorder': 2
1461
+ },
1462
+ {
1463
+ 'points': [(3, 14.72), (3, 9.45), (17, 9.45), (17, 14.6)],
1464
+ 'facecolor': '#E6ADAD',
1465
+ 'edgecolor': 'darkgreen',
1466
+ 'linewidth': 0,
1467
+ 'zorder': 1
1468
+ },
1469
+ {
1470
+ 'points': [(4.24, 18.74), (9.68, 18.74), (9.68, 17.34), (4.24, 17.34)],
1471
+ 'facecolor': '#f0f0f0',
1472
+ 'edgecolor': 'brown',
1473
+ 'linewidth': 0,
1474
+ 'zorder': 4
1475
+ },
1476
+ {
1477
+ 'points': [(12.25, 18.74), (15.88, 18.74), (15.88, 17.34), (12.25, 17.34)],
1478
+ 'facecolor': '#f0f0f0',
1479
+ 'edgecolor': 'darkgreen',
1480
+ 'linewidth': 0,
1481
+ 'zorder': 4
1482
+ }
1483
+ ]
1484
+
1485
+ # Define data for multiple ellipses
1486
+ my_ellipses = [
1487
+ {
1488
+ 'center_x': 10.0, 'center_y': 9.45, 'width': 9.0, 'height': 12.0, 'angle': 0,
1489
+ 'facecolor': '#f0f0f0',
1490
+ 'edgecolor': 'blue',
1491
+ 'linewidth': 0,
1492
+ 'zorder': 4
1493
+ },
1494
+ {
1495
+ 'center_x': 10.0, 'center_y': 9.45, 'width': 14.0, 'height': 17.0, 'angle': 0,
1496
+ 'facecolor': '#E6ADAD',
1497
+ 'edgecolor': 'purple',
1498
+ 'linewidth': 0,
1499
+ 'zorder': 3
1500
+ }
1501
+ ]
1502
+
1503
  # Final app logic (your current full app can go here)
1504
  def launch_main_app():
1505
  import gradio as gr
 
1598
  models_coinref_p2 = gr.State(None)
1599
  device_p2 = gr.State(None)
1600
  gallery_segmentation_p4 = gr.State()
1601
+ polygons, ellipses = gr.State(), gr.State()
1602
+ polygons1, ellipses1 = gr.State(), gr.State()
1603
 
1604
  full_app_interface.load(
1605
  fn=lambda: [GLOBAL_HOLES, GLOBAL_RIM, GLOBAL_COIN, device_p2],
 
1846
  download_all_file = gr.File(visible=False)
1847
  download_all_error = gr.File(visible=False)
1848
 
1849
+ res_stat1 = gr.State()
1850
+ step1 = gr.State()
1851
+
1852
+ with gr.Column():
1853
+ with gr.Row():
1854
+ result_status1 = gr.Textbox(label="", visible=False, interactive=False, elem_id='pretty-box')
1855
+ with gr.Row():
1856
+ with gr.Column():
1857
+ result_image11 = gr.Image(label="Chassy Image", visible=False, interactive=False)
1858
+ with gr.Column():
1859
+ result_image21 = gr.Image(label="Toilet Image", visible=False, interactive=False)
1860
+ with gr.Column():
1861
+ result_image31 = gr.Image(label="Overlapped Image", visible=False, interactive=False)
1862
+
1863
  with gr.Column(visible=False) as col:
1864
  gr.Markdown("## 🎯 Prediction Accuracy Analysis", elem_id="centered-title")
1865
 
 
1923
  error_plot = gr.Image(label="πŸ“‰ Error Plot", height=400, width=600, interactive=False, visible=False)
1924
  with gr.Row():
1925
  avg_error_text = gr.Textbox(label="🎯 Average Error %", interactive=False, elem_id='centered-title')
1926
+
1927
+ res_stat = gr.State()
1928
+ step = gr.State()
1929
+
1930
+ with gr.Column():
1931
+ with gr.Row():
1932
+ result_status = gr.Textbox(label="", visible=False, interactive=False, elem_id='pretty-box')
1933
+ with gr.Row():
1934
+ with gr.Column():
1935
+ result_image1 = gr.Image(label="Chassy Image", visible=False, interactive=False)
1936
+ with gr.Column():
1937
+ result_image2 = gr.Image(label="Toilet Image", visible=False, interactive=False)
1938
+ with gr.Column():
1939
+ result_image3 = gr.Image(label="Overlapped Image", visible=False, interactive=False)
1940
 
1941
  run_pipeline_btn.click(fn=lambda: gr.update(visible=True), outputs=group_to_show)
1942
  run_pipeline_btn.click(fn=lambda: gr.update(value="πŸ”„ Processing... (Please Wait)"), outputs=process)
 
2093
 
2094
  return zip_path, gr.update(value="")
2095
 
2096
+ import matplotlib.pyplot as plt
2097
+ import matplotlib.patches as patches
2098
+ import numpy as np
2099
+ from PIL import Image
2100
+ import os
2101
+
2102
+ def draw_shapes_with_zorder(
2103
+ polygons_data=None,
2104
+ ellipses_data=None,
2105
+ res_stat=True,
2106
+ filename="chasis_image.png",
2107
+ fig_size=(20, 15),
2108
+ transparent_bg=False
2109
+ ):
2110
+ if not res_stat:
2111
+ return None
2112
+
2113
+ fig, ax = plt.subplots(figsize=fig_size)
2114
+ ax.set_aspect('equal', adjustable='box')
2115
+ ax.set_axis_off()
2116
+ ax.set_facecolor('#f0f0f0')
2117
+
2118
+ min_x, max_x = float('inf'), float('-inf')
2119
+ min_y, max_y = float('inf'), float('-inf')
2120
+
2121
+ all_coords = []
2122
+ if polygons_data:
2123
+ for poly_info in polygons_data:
2124
+ points = poly_info.get('points')
2125
+ if points:
2126
+ all_coords.extend(points)
2127
+ polygon = patches.Polygon(
2128
+ points,
2129
+ closed=True,
2130
+ facecolor=poly_info.get('facecolor', '#ADD8E6'),
2131
+ edgecolor=poly_info.get('edgecolor', 'blue'),
2132
+ linewidth=poly_info.get('linewidth', 2),
2133
+ zorder=poly_info.get('zorder', 1)
2134
+ )
2135
+ ax.add_patch(polygon)
2136
+
2137
+ if ellipses_data:
2138
+ for ellipse_info in ellipses_data:
2139
+ e_cx = ellipse_info.get('center_x')
2140
+ e_cy = ellipse_info.get('center_y')
2141
+ e_w = ellipse_info.get('width')
2142
+ e_h = ellipse_info.get('height')
2143
+ e_angle = ellipse_info.get('angle', 0)
2144
+
2145
+ if e_cx is None or e_cy is None or e_w is None or e_h is None:
2146
+ continue
2147
+
2148
+ all_coords.append((e_cx - e_w / 2, e_cy - e_h / 2))
2149
+ all_coords.append((e_cx + e_w / 2, e_cy + e_h / 2))
2150
+ all_coords.append((e_cx - e_w / 2, e_cy + e_h / 2))
2151
+ all_coords.append((e_cx + e_w / 2, e_cy - e_h / 2))
2152
+
2153
+ ellipse = patches.Ellipse(
2154
+ (e_cx, e_cy),
2155
+ e_w,
2156
+ e_h,
2157
+ angle=e_angle,
2158
+ facecolor=ellipse_info.get('facecolor', '#FFD700'),
2159
+ edgecolor=ellipse_info.get('edgecolor', 'orange'),
2160
+ linewidth=ellipse_info.get('linewidth', 2),
2161
+ zorder=ellipse_info.get('zorder', 1)
2162
+ )
2163
+ ax.add_patch(ellipse)
2164
+
2165
+ if all_coords:
2166
+ coords_array = np.array(all_coords)
2167
+ min_x, min_y = np.min(coords_array, axis=0)
2168
+ max_x, max_y = np.max(coords_array, axis=0)
2169
+
2170
+ padding_x = (max_x - min_x) * 0.2 if (max_x - min_x) > 0 else 1.0
2171
+ padding_y = (max_y - min_y) * 0.2 if (max_y - min_y) > 0 else 1.0
2172
+
2173
+ ax.set_xlim(min_x - padding_x, max_x + padding_x)
2174
+ ax.set_ylim(min_y - padding_y, max_y + padding_y)
2175
+ else:
2176
+ ax.set_xlim(0, 10)
2177
+ ax.set_ylim(0, 8)
2178
+
2179
+ plt.savefig(filename, dpi=300, bbox_inches='tight', pad_inches=0, transparent=transparent_bg)
2180
+ plt.close(fig) # Close to avoid memory leak
2181
+
2182
+ res = Image.open(filename) # Return as PIL.Image object for Gradio
2183
+ return gr.update(visible=True, value=res)
2184
+
2185
+ # --- Example Usage ---
2186
+
2187
+ # Define data for multiple polygons
2188
+ my_polygons = gr.State([
2189
+ {
2190
+ 'points': [(0.56, 14.72), (0.56, 19.05), (19.5, 19.05), (19.5, 14.53)],
2191
+ 'facecolor': "#E6ADAD",
2192
+ 'edgecolor': 'brown',
2193
+ 'linewidth': 0,
2194
+ 'zorder': 2
2195
+ },
2196
+ {
2197
+ 'points': [(3, 14.72), (3, 9.45), (17, 9.45), (17, 14.6)],
2198
+ 'facecolor': '#E6ADAD',
2199
+ 'edgecolor': 'darkgreen',
2200
+ 'linewidth': 0,
2201
+ 'zorder': 1
2202
+ },
2203
+ {
2204
+ 'points': [(4.24, 18.74), (9.68, 18.74), (9.68, 17.34), (4.24, 17.34)],
2205
+ 'facecolor': '#f0f0f0',
2206
+ 'edgecolor': 'brown',
2207
+ 'linewidth': 0,
2208
+ 'zorder': 4
2209
+ },
2210
+ {
2211
+ 'points': [(12.25, 18.74), (15.88, 18.74), (15.88, 17.34), (12.25, 17.34)],
2212
+ 'facecolor': '#f0f0f0',
2213
+ 'edgecolor': 'darkgreen',
2214
+ 'linewidth': 0,
2215
+ 'zorder': 4
2216
+ }
2217
+ ])
2218
+
2219
+ # Define data for multiple ellipses
2220
+ my_ellipses = gr.State([
2221
+ {
2222
+ 'center_x': 10.0, 'center_y': 9.45, 'width': 9.0, 'height': 12.0, 'angle': 0,
2223
+ 'facecolor': '#f0f0f0',
2224
+ 'edgecolor': 'blue',
2225
+ 'linewidth': 0,
2226
+ 'zorder': 4
2227
+ },
2228
+ {
2229
+ 'center_x': 10.0, 'center_y': 9.45, 'width': 14.0, 'height': 17.0, 'angle': 0,
2230
+ 'facecolor': '#E6ADAD',
2231
+ 'edgecolor': 'purple',
2232
+ 'linewidth': 0,
2233
+ 'zorder': 3
2234
+ }
2235
+ ])
2236
+
2237
+ import matplotlib.pyplot as plt
2238
+ import matplotlib.patches as patches
2239
+ import numpy as np
2240
+ from PIL import Image
2241
+ import os
2242
+
2243
+ def draw_shapes_with_zorder2(
2244
+ polygons_data=None,
2245
+ ellipses_data=None,
2246
+ res_stat=True,
2247
+ step=0, out_ref_ratios_p5=None,
2248
+ filename="toilet_image.png",
2249
+ title="Custom Shapes Drawing",
2250
+ ):
2251
+ if not res_stat:
2252
+ return None
2253
+
2254
+ fig, ax = plt.subplots(figsize=(20, 15))
2255
+ ax.set_axis_off()
2256
+ ax.set_aspect('equal', adjustable='box')
2257
+ ax.set_facecolor('#f0f0f0')
2258
+
2259
+ ratio = out_ref_ratios_p5.get("closed", 1.0) if out_ref_ratios_p5 else 1.0
2260
+ vertical_shift = int(step * ratio)
2261
+
2262
+ min_x, max_x = float('inf'), float('-inf')
2263
+ min_y, max_y = float('inf'), float('-inf')
2264
+
2265
+ if polygons_data:
2266
+ for poly_info in polygons_data:
2267
+ points = poly_info.get('points')
2268
+ if not points:
2269
+ continue
2270
+
2271
+ # Apply vertical shift to y-coordinates
2272
+ shifted_points = [(x, y - vertical_shift) for (x, y) in points]
2273
+
2274
+ for x, y in shifted_points:
2275
+ min_x = min(min_x, x)
2276
+ max_x = max(max_x, x)
2277
+ min_y = min(min_y, y)
2278
+ max_y = max(max_y, y)
2279
+
2280
+ polygon = patches.Polygon(
2281
+ shifted_points,
2282
+ closed=True,
2283
+ facecolor=poly_info.get('facecolor', '#ADD8E6'),
2284
+ edgecolor=poly_info.get('edgecolor', 'blue'),
2285
+ linewidth=poly_info.get('linewidth', 2),
2286
+ label=poly_info.get('label', 'Polygon'),
2287
+ zorder=poly_info.get('zorder', 1)
2288
+ )
2289
+ ax.add_patch(polygon)
2290
+
2291
+ if ellipses_data:
2292
+ for ellipse_info in ellipses_data:
2293
+ e_cx = ellipse_info.get('center_x')
2294
+ e_cy = ellipse_info.get('center_y')
2295
+ e_w = ellipse_info.get('width')
2296
+ e_h = ellipse_info.get('height')
2297
+ e_angle = ellipse_info.get('angle', 0)
2298
+
2299
+ if e_cx is None or e_cy is None or e_w is None or e_h is None:
2300
+ continue
2301
+
2302
+ e_cy_shifted = e_cy - vertical_shift
2303
+
2304
+ min_x = min(min_x, e_cx - e_w / 2)
2305
+ max_x = max(max_x, e_cx + e_w / 2)
2306
+ min_y = min(min_y, e_cy_shifted - e_h / 2)
2307
+ max_y = max(max_y, e_cy_shifted + e_h / 2)
2308
+
2309
+ ellipse = patches.Ellipse(
2310
+ (e_cx, e_cy_shifted),
2311
+ e_w,
2312
+ e_h,
2313
+ angle=e_angle,
2314
+ facecolor=ellipse_info.get('facecolor', '#f0f0f0'),
2315
+ edgecolor=ellipse_info.get('edgecolor', '#f0f0f0'),
2316
+ linewidth=ellipse_info.get('linewidth', 2),
2317
+ label=ellipse_info.get('label', 'Ellipse'),
2318
+ zorder=ellipse_info.get('zorder', 1)
2319
+ )
2320
+ ax.add_patch(ellipse)
2321
+
2322
+ if min_x != float('inf') and max_x != float('-inf'):
2323
+ padding_x = (max_x - min_x) * 0.2 if (max_x - min_x) > 0 else 1.0
2324
+ padding_y = (max_y - min_y) * 0.2 if (max_y - min_y) > 0 else 1.0
2325
+ ax.set_xlim(min_x - padding_x, max_x + padding_x)
2326
+ ax.set_ylim(min_y - padding_y, max_y + padding_y)
2327
+ else:
2328
+ ax.set_xlim(0, 10)
2329
+ ax.set_ylim(0, 8)
2330
+
2331
+ plt.savefig(filename, dpi=300, bbox_inches='tight')
2332
+ plt.close(fig)
2333
+
2334
+ res = Image.open(filename)
2335
+ return gr.update(visible=True, value=res)
2336
+
2337
+ import sympy
2338
+ from sympy import symbols, Eq, solve, N
2339
+
2340
+ def find_tangent_points_from_external(px, py, cx, cy, a, b):
2341
+ x, y = symbols('x y')
2342
+
2343
+ # Ellipse equation
2344
+ ellipse_eq_sym = Eq((x - cx)**2 / a**2 + (y - cy)**2 / b**2, 1)
2345
+
2346
+ # Polar equation for (px, py)
2347
+ polar_eq_sym = Eq(
2348
+ (x - cx) * (px - cx) / a**2 +
2349
+ (y - cy) * (py - cy) / b**2, 1
2350
+ )
2351
+
2352
+ # Solve the system to find tangent points
2353
+ solutions = solve([ellipse_eq_sym, polar_eq_sym], (x, y))
2354
+
2355
+ tangent_points = []
2356
+ for sol in solutions:
2357
+ # Check the type of solution to handle both dict and tuple cases
2358
+ if isinstance(sol, dict):
2359
+ # If solution is a dictionary {x: val_x, y: val_y}
2360
+ if all(s.is_real for s in sol.values()):
2361
+ tangent_points.append((float(N(sol[x])), float(N(sol[y]))))
2362
+ elif isinstance(sol, tuple) and len(sol) == 2:
2363
+ # If solution is a tuple (val_x, val_y)
2364
+ # Make sure sol[0] and sol[1] are SymPy expressions before calling .is_real
2365
+ if sol[0].is_real and sol[1].is_real:
2366
+ tangent_points.append((float(N(sol[0])), float(N(sol[1]))))
2367
+
2368
+ return tangent_points
2369
+
2370
+ def get_specific_tangent_points(
2371
+ center_x, center_y, width, height,
2372
+ point1_x, point1_y, point2_x, point2_y
2373
+ ):
2374
+ a = width / 2
2375
+ b = height / 2
2376
+
2377
+ # Find tangent points for P1
2378
+ tangent_points_p1 = find_tangent_points_from_external(point1_x, point1_y, center_x, center_y, a, b)
2379
+
2380
+ # Find tangent points for P2
2381
+ tangent_points_p2 = find_tangent_points_from_external(point2_x, point2_y, center_x, center_y, a, b)
2382
+
2383
+ # --- Select the "left" tangent point for P1 ---
2384
+ # Sort by x-coordinate to easily pick left/right
2385
+ tangent_points_p1.sort(key=lambda p: p[0])
2386
+ selected_tangent_point_p1 = tangent_points_p1[0] # The one with smaller x-coordinate is "left"
2387
+
2388
+ # --- Select the "right" tangent point for P2 ---
2389
+ tangent_points_p2.sort(key=lambda p: p[0])
2390
+ selected_tangent_point_p2 = tangent_points_p2[1] # The one with larger x-coordinate is "right"
2391
+
2392
+ return selected_tangent_point_p2, selected_tangent_point_p1
2393
+
2394
+ # --- Example Usage ---
2395
+ def guide(a2, b2, c2, d2, e2, f2, g2, h2, res_stat):
2396
+ if not res_stat:
2397
+ return None, None
2398
+
2399
+ a2, b2, c2, d2, e2, f2, g2, h2 = float(a2), float(b2), float(c2), float(d2), float(e2), float(f2), float(g2), float(h2)
2400
+
2401
+ # Ellipse parameters
2402
+ ellipse_center_x = 10
2403
+ ellipse_center_y = 10
2404
+ ellipse_width = f2 # a = 5
2405
+ ellipse_height = g2 # b = 3
2406
+
2407
+ # External points (always above the ellipse, not exactly on top of center)
2408
+ point_1_x, point_1_y = 10 - (h2/2), 10 + (e2/2) + a2 + b2
2409
+
2410
+ point_2_x, point_2_y = 10 + (h2/2), 10 + (e2/2) + a2 + b2
2411
+
2412
+ tangent_points = get_specific_tangent_points(
2413
+ ellipse_center_x, ellipse_center_y,
2414
+ ellipse_width, ellipse_height,
2415
+ point_1_x, point_1_y, point_2_x, point_2_y
2416
+ )
2417
+
2418
+ polygons = [
2419
+ {
2420
+ 'points': [(10 - (h2/2), 10 + (e2/2) + a2 + b2), (10 + (h2/2), 10 + (e2/2) + a2 + b2), (tangent_points[0][0], tangent_points[0][1]), (tangent_points[1][0], tangent_points[1][1])],
2421
+ 'facecolor': '#ADD8E6', # Peach
2422
+ 'edgecolor': 'brown',
2423
+ 'linewidth': 0,
2424
+ 'label': 'Irregular Quad',
2425
+ 'zorder': 2 # This will be on top of the green triangle
2426
+ }
2427
+ ]
2428
+
2429
+ # Define data for multiple ellipses
2430
+ ellipses = [
2431
+ {
2432
+ 'center_x': 10.0, 'center_y': 10, 'width': d2, 'height': e2, 'angle': 0,
2433
+ 'facecolor': '#f0f0f0', # Light blue
2434
+ 'edgecolor': 'blue',
2435
+ 'linewidth': 0,
2436
+ 'label': 'Rotated Ellipse',
2437
+ 'zorder': 4 # This will be on top of both polygons
2438
+ },
2439
+ {
2440
+ 'center_x': 10.0, 'center_y': 10, 'width': f2, 'height': g2, 'angle': 0,
2441
+ 'facecolor': '#ADD8E6', # Pink
2442
+ 'edgecolor': 'purple',
2443
+ 'linewidth': 0,
2444
+ 'label': 'Small Circle',
2445
+ 'zorder': 3 # This will be on top of everything else
2446
+ },
2447
+ {
2448
+ 'center_x': 10 - (c2/2) + 0.75, 'center_y': 10 + (e2/2) + b2, 'width': 0.75, 'height': 0.75, 'angle': 0,
2449
+ 'facecolor': '#f0f0f0', # Light blue
2450
+ 'edgecolor': 'blue',
2451
+ 'linewidth': 0,
2452
+ 'label': 'Rotated Ellipse',
2453
+ 'zorder': 4 # This will be on top of both polygons
2454
+ },
2455
+ {
2456
+ 'center_x': 10 + (c2/2) - 0.75, 'center_y': 10 + (e2/2) + b2, 'width': 0.75, 'height': 0.75, 'angle': 0,
2457
+ 'facecolor': '#f0f0f0', # Pink
2458
+ 'edgecolor': 'purple',
2459
+ 'linewidth': 0,
2460
+ 'label': 'Small Circle',
2461
+ 'zorder': 4 # This will be on top of everything else
2462
+ }
2463
+ ]
2464
+ return polygons, ellipses
2465
+
2466
+ from PIL import Image
2467
+
2468
+ def overlay_images_centered(background_path, foreground_path, res_stat, step, out_ref_ratios_p5):
2469
+ if not res_stat:
2470
+ return None
2471
+
2472
+ # Load images from NumPy arrays
2473
+ bg = Image.fromarray(background_path).convert("RGBA")
2474
+ fg = Image.fromarray(foreground_path).convert("RGBA")
2475
+
2476
+ # Make #f0f0f0 pixels transparent
2477
+ new_data = [
2478
+ (255, 255, 255, 0) if pixel[:3] == (240, 240, 240) else pixel
2479
+ for pixel in fg.getdata()
2480
+ ]
2481
+ fg.putdata(new_data)
2482
+
2483
+ # Get sizes
2484
+ bg_w, bg_h = bg.size
2485
+ fg_w, fg_h = fg.size
2486
+ ratio = out_ref_ratios_p5.get("closed", 1.0)
2487
+ vertical_shift = int(step * ratio)
2488
+
2489
+ # Create a blank transparent image (same size as background)
2490
+ shifted_fg = Image.new("RGBA", bg.size, (255, 255, 255, 0))
2491
+
2492
+ # Center the foreground, shifted UP by vertical_shift pixels
2493
+ pos_x = (bg_w - fg_w) // 2
2494
+ pos_y = (bg_h - fg_h) // 2 - vertical_shift
2495
+ shifted_fg.paste(fg, (pos_x, pos_y), fg)
2496
+
2497
+ # Reduce opacity to 50%
2498
+ alpha = shifted_fg.split()[3].point(lambda a: int(a * 0.5))
2499
+ shifted_fg.putalpha(alpha)
2500
+
2501
+ # Composite foreground onto background
2502
+ result = Image.alpha_composite(bg, shifted_fg).convert("RGB")
2503
+
2504
+ return gr.update(visible=True, value=result)
2505
+
2506
+ def checkstatus(b2, c2, g2):
2507
+ hole_rad = 0.375
2508
+ max_range = 18.1
2509
+ top_val = max_range - 0.31 - hole_rad
2510
+ bottom_val = top_val - 1.4 + (hole_rad * 2)
2511
+ min_width = 4.5 + hole_rad
2512
+ max_width = 11.52 - hole_rad
2513
+
2514
+ max_step = 0.5
2515
+ step_size = 0.05
2516
+ steps = int(max_step / step_size) + 1 # Includes 0.0 step
2517
+
2518
+ for i in range(steps):
2519
+ step = i * step_size
2520
+ if float(bottom_val) < float(g2) + float(b2) + float(step) < float(top_val) and float(min_width) < float(c2) < float(max_width):
2521
+ msg = "βœ… Our Product can fit in your Washroom."
2522
+ return gr.update(value=msg, visible=True), True, step
2523
+
2524
+ msg = "❌ Unfortunately we cannot fit our product in your washroom."
2525
+ return gr.update(value=msg, visible=True), False, None
2526
+
2527
  submit_btn.click(
2528
  fn=lambda *args: (
2529
  compare_measurements(*args)[0],
 
2536
  then(fn=download_all_results,
2537
  inputs=[a1, b1, c1, d1, e1, f1, g1, h1, a2, b2, c2, d2, e2, f2, g2, h2, avg_error_text, error_plot],
2538
  outputs=[download_all_error, progress]).\
2539
+ then(upload_zip_error, inputs=[email, download_all_error], outputs=[]).\
2540
+ then(checkstatus, inputs=[b2, c2, g2], outputs=[result_status, res_stat, step]).\
2541
+ then(fn=draw_shapes_with_zorder, inputs=[my_polygons, my_ellipses, res_stat], outputs=[result_image1]).\
2542
+ then(fn=guide, inputs=[a2, b2, c2, d2, e2, f2, g2, h2, res_stat], outputs=[polygons, ellipses]).\
2543
+ then(fn=draw_shapes_with_zorder2, inputs=[polygons, ellipses, res_stat, step, out_ref_ratios_p5], outputs=[result_image2]).\
2544
+ then(fn=overlay_images_centered, inputs=[result_image1, result_image2, res_stat, step, out_ref_ratios_p5], outputs=[result_image3])
2545
 
2546
  submit_btn.click(fn=lambda: gr.update(visible=True), inputs=[], outputs=[error])
2547
 
 
2822
  remaining_lid_img_p12, remaining_str, out_image, top_width_str, a1, b1, c1, d1, e1, f1, g1, h1
2823
  ],
2824
  outputs=[download_all_file, progress]).\
2825
+ then(upload_zip, inputs=[email, download_all_file], outputs=[col]).\
2826
+ then(checkstatus, inputs=[b1, c1, g1], outputs=[result_status1, res_stat1, step1]).\
2827
+ then(fn=draw_shapes_with_zorder, inputs=[my_polygons, my_ellipses, res_stat1], outputs=[result_image11]).\
2828
+ then(fn=guide, inputs=[a1, b1, c1, d1, e1, f1, g1, h1, res_stat1], outputs=[polygons1, ellipses1]).\
2829
+ then(fn=draw_shapes_with_zorder2, inputs=[polygons1, ellipses1, res_stat1, step1, out_ref_ratios_p5], outputs=[result_image21]).\
2830
+ then(fn=overlay_images_centered, inputs=[result_image11, result_image21, res_stat1, step1, out_ref_ratios_p5], outputs=[result_image31])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2831
 
2832
  with gr.Blocks(title="πŸ§ͺ Toilet Segmentation & Measurement App") as full_app_interface:
2833
  auth_state = gr.State(False) # Used to track login state
 
2880
 
2881
  auth_state.change(toggle_app, inputs=auth_state, outputs=protected_content)
2882
 
2883
+ with gr.Row():
2884
+ gr.Markdown("")
2885
+ with gr.Row():
2886
+ gr.Markdown("")
2887
+ with gr.Row():
2888
+ gr.Markdown("")
2889
+ with gr.Row():
2890
+ gr.Markdown("\nFor any queries, Feel free to contact πŸ“§ core.atsc@gmail.com", elem_id='centered-title')
2891
+
2892
+ with gr.Row():
2893
+ gr.Markdown(
2894
+ """
2895
+ ---
2896
+ #### [πŸ‘¨β€πŸ’»](mailto:savaliyaheet19@gmail.com) [*Created by*](https://github.com/heetsavaliya) [**Heet Savaliya**](https://www.linkedin.com/in/heet-savaliya-03b863252/), [**PDEU**](https://www.linkedin.com/in/heet-savaliya-03b863252/)
2897
+ Β© 2025 HapiHygi Innovations Private Limited. All rights reserved.
2898
+ """,
2899
+ elem_id="footer-text",
2900
+ )
2901
+
2902
  # πŸš€ Launch App
2903
  if __name__ == "__main__":
2904
+ full_app_interface.launch()