bla commited on
Commit
9c4d474
Β·
verified Β·
1 Parent(s): 0030818

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +153 -60
app.py CHANGED
@@ -8,23 +8,25 @@ import matplotlib.pyplot as plt
8
  from transformers import AutoModel, AutoProcessor
9
  from ultralytics import YOLO
10
 
11
-
12
- # Custom CSS for a more modern UI inspired by NextUI
13
  custom_css = """
14
  :root {
15
  --primary: #0070f3;
16
  --primary-foreground: #ffffff;
17
- --background: #f5f5f5;
 
18
  --card: #ffffff;
19
  --card-foreground: #111111;
20
  --border: #eaeaea;
21
  --ring: #0070f3;
22
- --shadow: 0 4px 14px 0 rgba(0, 118, 255, 0.1);
 
23
  }
24
 
25
  .dark {
26
  --primary: #0070f3;
27
  --primary-foreground: #ffffff;
 
28
  --background: #000000;
29
  --card: #111111;
30
  --card-foreground: #ffffff;
@@ -45,24 +47,27 @@ custom_css = """
45
  }
46
 
47
  .header {
48
- margin-bottom: 2rem;
49
  text-align: center;
50
  }
51
 
52
  .header h1 {
53
- font-size: 2.5rem;
54
  font-weight: 800;
55
  color: var(--card-foreground);
56
- margin-bottom: 0.5rem;
57
- background: linear-gradient(to right, #0070f3, #00bfff);
58
  -webkit-background-clip: text;
59
  -webkit-text-fill-color: transparent;
 
60
  }
61
 
62
  .header p {
63
  color: var(--card-foreground);
64
  opacity: 0.8;
65
- font-size: 1.1rem;
 
 
66
  }
67
 
68
  .tab-nav {
@@ -71,57 +76,67 @@ custom_css = """
71
  padding: 0.5rem;
72
  margin-bottom: 2rem;
73
  box-shadow: var(--shadow);
 
74
  }
75
 
76
  .tab-nav button {
77
- border-radius: var(--radius) !important;
78
  font-weight: 600 !important;
79
- transition: all 0.2s ease-in-out !important;
80
  padding: 0.75rem 1.5rem !important;
 
81
  }
82
 
83
  .tab-nav button.selected {
84
- background-color: var(--primary) !important;
85
  color: var(--primary-foreground) !important;
86
- transform: translateY(-2px);
87
- box-shadow: 0 4px 14px 0 rgba(0, 118, 255, 0.25);
88
  }
89
 
90
  .input-panel, .output-panel {
91
  background-color: var(--card);
92
  border-radius: var(--radius);
93
- padding: 1.5rem;
94
  box-shadow: var(--shadow);
95
  height: 100%;
96
  display: flex;
97
  flex-direction: column;
 
 
 
 
 
 
98
  }
99
 
100
  .input-panel h3, .output-panel h3 {
101
  font-size: 1.25rem;
102
  font-weight: 600;
103
- margin-bottom: 1rem;
104
  color: var(--card-foreground);
105
- border-bottom: 2px solid var(--primary);
 
106
  padding-bottom: 0.5rem;
107
  display: inline-block;
108
  }
109
 
110
  .gr-button-primary {
111
- background-color: var(--primary) !important;
112
  color: var(--primary-foreground) !important;
113
  border-radius: var(--radius) !important;
114
  font-weight: 600 !important;
115
- transition: all 0.2s ease-in-out !important;
116
  padding: 0.75rem 1.5rem !important;
117
- box-shadow: 0 4px 14px 0 rgba(0, 118, 255, 0.25) !important;
118
  width: 100%;
119
- margin-top: 1rem;
 
120
  }
121
 
122
  .gr-button-primary:hover {
123
  transform: translateY(-2px) !important;
124
- box-shadow: 0 6px 20px rgba(0, 118, 255, 0.35) !important;
125
  }
126
 
127
  .gr-form {
@@ -133,12 +148,14 @@ custom_css = """
133
  border: 1px solid var(--border) !important;
134
  border-radius: var(--radius) !important;
135
  padding: 0.75rem 1rem !important;
136
- transition: all 0.2s ease-in-out !important;
 
137
  }
138
 
139
  .gr-input:focus, .gr-select:focus {
140
  border-color: var(--primary) !important;
141
  box-shadow: 0 0 0 2px rgba(0, 118, 255, 0.25) !important;
 
142
  }
143
 
144
  .gr-panel {
@@ -149,37 +166,88 @@ custom_css = """
149
  border: 1px solid var(--border) !important;
150
  border-radius: var(--radius) !important;
151
  overflow: hidden;
 
 
 
 
 
 
152
  }
153
 
154
  .footer {
155
- margin-top: 2rem;
156
  border-top: 1px solid var(--border);
157
- padding-top: 1.5rem;
158
- font-size: 0.9rem;
159
  color: var(--card-foreground);
160
- opacity: 0.7;
161
  text-align: center;
162
  }
163
 
164
  .footer-card {
165
  background-color: var(--card);
166
  border-radius: var(--radius);
167
- padding: 1.5rem;
168
  box-shadow: var(--shadow);
 
 
 
 
 
 
169
  }
170
 
171
  .tips-grid {
172
  display: grid;
173
- grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
174
- gap: 1rem;
175
- margin-top: 1rem;
176
  }
177
 
178
  .tip-card {
179
  background-color: var(--card);
180
  border-radius: var(--radius);
181
- padding: 1rem;
182
- border-left: 3px solid var(--primary);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  }
184
  """
185
 
@@ -399,10 +467,10 @@ def create_svg_from_detections(json_results, img_width, img_height):
399
  svg_header = f'<svg width="{img_width}" height="{img_height}" xmlns="http://www.w3.org/2000/svg">'
400
  svg_content = ""
401
 
402
- # Color palette for different classes
403
  colors = [
404
- "#FF3B30", "#FF9500", "#FFCC00", "#4CD964",
405
- "#5AC8FA", "#007AFF", "#5856D6", "#FF2D55"
406
  ]
407
 
408
  for i, result in enumerate(json_results):
@@ -419,7 +487,7 @@ def create_svg_from_detections(json_results, img_width, img_height):
419
  # Select color based on class index
420
  color = colors[i % len(colors)]
421
 
422
- # Create rectangle element
423
  svg_content += f'''
424
  <rect
425
  x="{x:.2f}"
@@ -427,17 +495,30 @@ def create_svg_from_detections(json_results, img_width, img_height):
427
  width="{width:.2f}"
428
  height="{height:.2f}"
429
  stroke="{color}"
430
- stroke-width="2"
431
  fill="none"
 
 
432
  data-label="{label}"
433
  data-score="{score:.2f}"
434
  />
 
 
 
 
 
 
 
 
 
 
435
  <text
436
- x="{x:.2f}"
437
- y="{y-5:.2f}"
438
  font-family="Arial"
439
  font-size="12"
440
- fill="{color}"
 
441
  >{label} ({score:.2f})</text>'''
442
 
443
  svg_footer = "\n</svg>"
@@ -448,10 +529,10 @@ def create_svg_from_segmentation(json_results, img_width, img_height):
448
  svg_header = f'<svg width="{img_width}" height="{img_height}" xmlns="http://www.w3.org/2000/svg">'
449
  svg_content = ""
450
 
451
- # Color palette for different classes
452
  colors = [
453
- "#FF3B30", "#FF9500", "#FFCC00", "#4CD964",
454
- "#5AC8FA", "#007AFF", "#5856D6", "#FF2D55"
455
  ]
456
 
457
  for i, result in enumerate(json_results):
@@ -472,7 +553,7 @@ def create_svg_from_segmentation(json_results, img_width, img_height):
472
  <polygon
473
  points="{points_str}"
474
  stroke="{color}"
475
- stroke-width="2"
476
  fill="{color}33"
477
  data-label="{label}"
478
  data-score="{score:.2f}"
@@ -492,16 +573,29 @@ def create_svg_from_segmentation(json_results, img_width, img_height):
492
  width="{width:.2f}"
493
  height="{height:.2f}"
494
  stroke="{color}"
495
- stroke-width="1"
496
  fill="none"
 
 
497
  stroke-dasharray="5,5"
498
  />
 
 
 
 
 
 
 
 
 
 
499
  <text
500
- x="{x:.2f}"
501
- y="{y-5:.2f}"
502
  font-family="Arial"
503
  font-size="12"
504
- fill="{color}"
 
505
  >{label} ({score:.2f})</text>'''
506
 
507
  svg_footer = "\n</svg>"
@@ -556,10 +650,10 @@ with gr.Blocks(title="YOLO Vision Suite", css=custom_css) as demo:
556
  with gr.Row(equal_height=True):
557
  with gr.Column(elem_classes="input-panel", scale=1):
558
  gr.Markdown("### Input")
559
- input_image = gr.Image(label="Upload Image", type="numpy", height=300)
560
  text_prompt = gr.Textbox(
561
  label="Text Prompt",
562
- placeholder="person, car, dog",
563
  value="person, car, dog",
564
  elem_classes="gr-input"
565
  )
@@ -577,7 +671,7 @@ with gr.Blocks(title="YOLO Vision Suite", css=custom_css) as demo:
577
  label="Model Size",
578
  elem_classes="gr-select"
579
  )
580
- detect_button = gr.Button("Detect Objects", elem_classes="gr-button-primary")
581
 
582
  with gr.Column(elem_classes="output-panel", scale=1):
583
  gr.Markdown("### Results")
@@ -595,7 +689,7 @@ with gr.Blocks(title="YOLO Vision Suite", css=custom_css) as demo:
595
  with gr.Row(equal_height=True):
596
  with gr.Column(elem_classes="input-panel", scale=1):
597
  gr.Markdown("### Input")
598
- seg_input_image = gr.Image(label="Upload Image", type="numpy", height=300)
599
  with gr.Row():
600
  seg_confidence = gr.Slider(
601
  minimum=0.1,
@@ -610,7 +704,7 @@ with gr.Blocks(title="YOLO Vision Suite", css=custom_css) as demo:
610
  label="Model Size",
611
  elem_classes="gr-select"
612
  )
613
- segment_button = gr.Button("Segment Image", elem_classes="gr-button-primary")
614
 
615
  with gr.Column(elem_classes="output-panel", scale=1):
616
  gr.Markdown("### Results")
@@ -629,19 +723,19 @@ with gr.Blocks(title="YOLO Vision Suite", css=custom_css) as demo:
629
  gr.Markdown("### Tips & Information")
630
  with gr.Row(elem_classes="tips-grid"):
631
  with gr.Column(elem_classes="tip-card"):
632
- gr.Markdown("**Detection**")
633
  gr.Markdown("Enter comma-separated text prompts to specify what objects to detect")
634
 
635
  with gr.Column(elem_classes="tip-card"):
636
- gr.Markdown("**Segmentation**")
637
  gr.Markdown("The model will identify and segment common objects automatically")
638
 
639
  with gr.Column(elem_classes="tip-card"):
640
- gr.Markdown("**Models**")
641
  gr.Markdown("Larger models provide better accuracy but require more processing power")
642
 
643
  with gr.Column(elem_classes="tip-card"):
644
- gr.Markdown("**Output**")
645
  gr.Markdown("JSON output provides coordinates as percentages, compatible with SVG")
646
 
647
  # Set up event handlers
@@ -658,5 +752,4 @@ with gr.Blocks(title="YOLO Vision Suite", css=custom_css) as demo:
658
  )
659
 
660
  if __name__ == "__main__":
661
- demo.launch(share=True) # Set share=True to create a public link
662
-
 
8
  from transformers import AutoModel, AutoProcessor
9
  from ultralytics import YOLO
10
 
11
+ # Custom CSS for NextUI inspired look
 
12
  custom_css = """
13
  :root {
14
  --primary: #0070f3;
15
  --primary-foreground: #ffffff;
16
+ --secondary: #7928ca;
17
+ --background: #fafafa;
18
  --card: #ffffff;
19
  --card-foreground: #111111;
20
  --border: #eaeaea;
21
  --ring: #0070f3;
22
+ --shadow: 0 4px 14px 0 rgba(0, 118, 255, 0.2);
23
+ --radius: 0.75rem;
24
  }
25
 
26
  .dark {
27
  --primary: #0070f3;
28
  --primary-foreground: #ffffff;
29
+ --secondary: #9353d3;
30
  --background: #000000;
31
  --card: #111111;
32
  --card-foreground: #ffffff;
 
47
  }
48
 
49
  .header {
50
+ margin-bottom: 2.5rem;
51
  text-align: center;
52
  }
53
 
54
  .header h1 {
55
+ font-size: 3rem;
56
  font-weight: 800;
57
  color: var(--card-foreground);
58
+ margin-bottom: 0.75rem;
59
+ background: linear-gradient(to right, var(--primary), var(--secondary));
60
  -webkit-background-clip: text;
61
  -webkit-text-fill-color: transparent;
62
+ letter-spacing: -0.025em;
63
  }
64
 
65
  .header p {
66
  color: var(--card-foreground);
67
  opacity: 0.8;
68
+ font-size: 1.2rem;
69
+ max-width: 600px;
70
+ margin: 0 auto;
71
  }
72
 
73
  .tab-nav {
 
76
  padding: 0.5rem;
77
  margin-bottom: 2rem;
78
  box-shadow: var(--shadow);
79
+ overflow: hidden;
80
  }
81
 
82
  .tab-nav button {
83
+ border-radius: calc(var(--radius) - 0.25rem) !important;
84
  font-weight: 600 !important;
85
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1) !important;
86
  padding: 0.75rem 1.5rem !important;
87
+ margin: 0.25rem !important;
88
  }
89
 
90
  .tab-nav button.selected {
91
+ background: linear-gradient(to right, var(--primary), var(--secondary)) !important;
92
  color: var(--primary-foreground) !important;
93
+ transform: translateY(-1px);
94
+ box-shadow: 0 4px 14px 0 rgba(0, 118, 255, 0.3);
95
  }
96
 
97
  .input-panel, .output-panel {
98
  background-color: var(--card);
99
  border-radius: var(--radius);
100
+ padding: 1.75rem;
101
  box-shadow: var(--shadow);
102
  height: 100%;
103
  display: flex;
104
  flex-direction: column;
105
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
106
+ }
107
+
108
+ .input-panel:hover, .output-panel:hover {
109
+ transform: translateY(-2px);
110
+ box-shadow: 0 6px 20px rgba(0, 118, 255, 0.25);
111
  }
112
 
113
  .input-panel h3, .output-panel h3 {
114
  font-size: 1.25rem;
115
  font-weight: 600;
116
+ margin-bottom: 1.25rem;
117
  color: var(--card-foreground);
118
+ border-bottom: 2px solid;
119
+ border-image: linear-gradient(to right, var(--primary), var(--secondary)) 1;
120
  padding-bottom: 0.5rem;
121
  display: inline-block;
122
  }
123
 
124
  .gr-button-primary {
125
+ background: linear-gradient(to right, var(--primary), var(--secondary)) !important;
126
  color: var(--primary-foreground) !important;
127
  border-radius: var(--radius) !important;
128
  font-weight: 600 !important;
129
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1) !important;
130
  padding: 0.75rem 1.5rem !important;
131
+ box-shadow: 0 4px 14px 0 rgba(0, 118, 255, 0.3) !important;
132
  width: 100%;
133
+ margin-top: 1.25rem;
134
+ border: none !important;
135
  }
136
 
137
  .gr-button-primary:hover {
138
  transform: translateY(-2px) !important;
139
+ box-shadow: 0 6px 20px rgba(0, 118, 255, 0.4) !important;
140
  }
141
 
142
  .gr-form {
 
148
  border: 1px solid var(--border) !important;
149
  border-radius: var(--radius) !important;
150
  padding: 0.75rem 1rem !important;
151
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1) !important;
152
+ background-color: var(--card) !important;
153
  }
154
 
155
  .gr-input:focus, .gr-select:focus {
156
  border-color: var(--primary) !important;
157
  box-shadow: 0 0 0 2px rgba(0, 118, 255, 0.25) !important;
158
+ outline: none !important;
159
  }
160
 
161
  .gr-panel {
 
166
  border: 1px solid var(--border) !important;
167
  border-radius: var(--radius) !important;
168
  overflow: hidden;
169
+ margin-top: 1rem;
170
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
171
+ }
172
+
173
+ .gr-accordion:hover {
174
+ border-color: var(--primary) !important;
175
  }
176
 
177
  .footer {
178
+ margin-top: 3rem;
179
  border-top: 1px solid var(--border);
180
+ padding-top: 2rem;
181
+ font-size: 0.95rem;
182
  color: var(--card-foreground);
183
+ opacity: 0.8;
184
  text-align: center;
185
  }
186
 
187
  .footer-card {
188
  background-color: var(--card);
189
  border-radius: var(--radius);
190
+ padding: 1.75rem;
191
  box-shadow: var(--shadow);
192
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
193
+ }
194
+
195
+ .footer-card:hover {
196
+ transform: translateY(-2px);
197
+ box-shadow: 0 6px 20px rgba(0, 118, 255, 0.25);
198
  }
199
 
200
  .tips-grid {
201
  display: grid;
202
+ grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
203
+ gap: 1.25rem;
204
+ margin-top: 1.25rem;
205
  }
206
 
207
  .tip-card {
208
  background-color: var(--card);
209
  border-radius: var(--radius);
210
+ padding: 1.25rem;
211
+ border-left: 3px solid;
212
+ border-image: linear-gradient(to bottom, var(--primary), var(--secondary)) 1 100%;
213
+ transition: transform 0.2s ease, box-shadow 0.2s ease;
214
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
215
+ }
216
+
217
+ .tip-card:hover {
218
+ transform: translateY(-2px);
219
+ box-shadow: 0 4px 12px rgba(0, 118, 255, 0.15);
220
+ }
221
+
222
+ /* Image upload area styling */
223
+ .image-container {
224
+ border: 2px dashed var(--border);
225
+ border-radius: var(--radius);
226
+ padding: 1.5rem;
227
+ text-align: center;
228
+ transition: all 0.2s ease;
229
+ }
230
+
231
+ .image-container:hover {
232
+ border-color: var(--primary);
233
+ }
234
+
235
+ /* Slider styling */
236
+ input[type=range] {
237
+ height: 6px;
238
+ border-radius: 10px;
239
+ background: linear-gradient(to right, var(--primary), var(--secondary)) !important;
240
+ }
241
+
242
+ input[type=range]::-webkit-slider-thumb {
243
+ background: var(--primary) !important;
244
+ border: 2px solid white;
245
+ box-shadow: 0 2px 6px rgba(0, 118, 255, 0.3);
246
+ }
247
+
248
+ /* Loading animation */
249
+ .gr-progress {
250
+ background: linear-gradient(to right, var(--primary), var(--secondary)) !important;
251
  }
252
  """
253
 
 
467
  svg_header = f'<svg width="{img_width}" height="{img_height}" xmlns="http://www.w3.org/2000/svg">'
468
  svg_content = ""
469
 
470
+ # NextUI-inspired color palette
471
  colors = [
472
+ "#0070F3", "#7928CA", "#FF0080", "#50E3C2",
473
+ "#F5A623", "#FF4D4D", "#0070F3", "#7928CA"
474
  ]
475
 
476
  for i, result in enumerate(json_results):
 
487
  # Select color based on class index
488
  color = colors[i % len(colors)]
489
 
490
+ # Create rectangle element with rounded corners
491
  svg_content += f'''
492
  <rect
493
  x="{x:.2f}"
 
495
  width="{width:.2f}"
496
  height="{height:.2f}"
497
  stroke="{color}"
498
+ stroke-width="2.5"
499
  fill="none"
500
+ rx="4"
501
+ ry="4"
502
  data-label="{label}"
503
  data-score="{score:.2f}"
504
  />
505
+ <rect
506
+ x="{x:.2f}"
507
+ y="{y-24:.2f}"
508
+ width="{min(width, len(label)*8 + 60):.2f}"
509
+ height="24"
510
+ fill="{color}"
511
+ rx="4"
512
+ ry="4"
513
+ opacity="0.9"
514
+ />
515
  <text
516
+ x="{x+5:.2f}"
517
+ y="{y-8:.2f}"
518
  font-family="Arial"
519
  font-size="12"
520
+ font-weight="bold"
521
+ fill="white"
522
  >{label} ({score:.2f})</text>'''
523
 
524
  svg_footer = "\n</svg>"
 
529
  svg_header = f'<svg width="{img_width}" height="{img_height}" xmlns="http://www.w3.org/2000/svg">'
530
  svg_content = ""
531
 
532
+ # NextUI-inspired color palette
533
  colors = [
534
+ "#0070F3", "#7928CA", "#FF0080", "#50E3C2",
535
+ "#F5A623", "#FF4D4D", "#0070F3", "#7928CA"
536
  ]
537
 
538
  for i, result in enumerate(json_results):
 
553
  <polygon
554
  points="{points_str}"
555
  stroke="{color}"
556
+ stroke-width="2.5"
557
  fill="{color}33"
558
  data-label="{label}"
559
  data-score="{score:.2f}"
 
573
  width="{width:.2f}"
574
  height="{height:.2f}"
575
  stroke="{color}"
576
+ stroke-width="1.5"
577
  fill="none"
578
+ rx="4"
579
+ ry="4"
580
  stroke-dasharray="5,5"
581
  />
582
+ <rect
583
+ x="{x:.2f}"
584
+ y="{y-24:.2f}"
585
+ width="{min(width, len(label)*8 + 60):.2f}"
586
+ height="24"
587
+ fill="{color}"
588
+ rx="4"
589
+ ry="4"
590
+ opacity="0.9"
591
+ />
592
  <text
593
+ x="{x+5:.2f}"
594
+ y="{y-8:.2f}"
595
  font-family="Arial"
596
  font-size="12"
597
+ font-weight="bold"
598
+ fill="white"
599
  >{label} ({score:.2f})</text>'''
600
 
601
  svg_footer = "\n</svg>"
 
650
  with gr.Row(equal_height=True):
651
  with gr.Column(elem_classes="input-panel", scale=1):
652
  gr.Markdown("### Input")
653
+ input_image = gr.Image(label="Upload Image", type="numpy", height=300, elem_classes="image-container")
654
  text_prompt = gr.Textbox(
655
  label="Text Prompt",
656
+ placeholder="Enter objects to detect (e.g., person, car, dog)",
657
  value="person, car, dog",
658
  elem_classes="gr-input"
659
  )
 
671
  label="Model Size",
672
  elem_classes="gr-select"
673
  )
674
+ detect_button = gr.Button("✨ Detect Objects", elem_classes="gr-button-primary")
675
 
676
  with gr.Column(elem_classes="output-panel", scale=1):
677
  gr.Markdown("### Results")
 
689
  with gr.Row(equal_height=True):
690
  with gr.Column(elem_classes="input-panel", scale=1):
691
  gr.Markdown("### Input")
692
+ seg_input_image = gr.Image(label="Upload Image", type="numpy", height=300, elem_classes="image-container")
693
  with gr.Row():
694
  seg_confidence = gr.Slider(
695
  minimum=0.1,
 
704
  label="Model Size",
705
  elem_classes="gr-select"
706
  )
707
+ segment_button = gr.Button("✨ Segment Image", elem_classes="gr-button-primary")
708
 
709
  with gr.Column(elem_classes="output-panel", scale=1):
710
  gr.Markdown("### Results")
 
723
  gr.Markdown("### Tips & Information")
724
  with gr.Row(elem_classes="tips-grid"):
725
  with gr.Column(elem_classes="tip-card"):
726
+ gr.Markdown("**πŸ” Detection**")
727
  gr.Markdown("Enter comma-separated text prompts to specify what objects to detect")
728
 
729
  with gr.Column(elem_classes="tip-card"):
730
+ gr.Markdown("**🧩 Segmentation**")
731
  gr.Markdown("The model will identify and segment common objects automatically")
732
 
733
  with gr.Column(elem_classes="tip-card"):
734
+ gr.Markdown("**βš™οΈ Models**")
735
  gr.Markdown("Larger models provide better accuracy but require more processing power")
736
 
737
  with gr.Column(elem_classes="tip-card"):
738
+ gr.Markdown("**πŸ“Š Output**")
739
  gr.Markdown("JSON output provides coordinates as percentages, compatible with SVG")
740
 
741
  # Set up event handlers
 
752
  )
753
 
754
  if __name__ == "__main__":
755
+ demo.launch(share=True) # Set share=True to create a public link