ArchCoder commited on
Commit
fb04e74
Β·
verified Β·
1 Parent(s): df0c4c5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +92 -363
app.py CHANGED
@@ -1,416 +1,151 @@
1
  import gradio as gr
2
  import torch
3
- import torch.nn as nn
4
  import numpy as np
5
  import cv2
6
  from PIL import Image
7
  import matplotlib.pyplot as plt
8
  import io
 
9
  from torchvision import transforms
10
- import torchvision.models as models
11
- from torchvision.models import detection
12
- import warnings
13
- warnings.filterwarnings("ignore")
14
 
15
- # Global variables
16
- model = None
17
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
 
18
 
19
- class TumorDetector:
20
- def __init__(self):
21
- self.model = None
22
- self.device = device
23
-
24
- def load_maskrcnn_model(self):
25
- """Load Mask R-CNN for tumor instance segmentation"""
26
- try:
27
- print("πŸ”„ Loading Mask R-CNN for brain tumor detection...")
28
-
29
- # Use pretrained Mask R-CNN and fine-tune for brain tumors
30
- self.model = detection.maskrcnn_resnet50_fpn(pretrained=True)
31
-
32
- # Modify for brain tumor segmentation (2 classes: background, tumor)
33
- num_classes = 2
34
- in_features = self.model.roi_heads.box_predictor.cls_score.in_features
35
- self.model.roi_heads.box_predictor = detection.faster_rcnn.FastRCNNPredictor(in_features, num_classes)
36
-
37
- # Modify mask predictor
38
- in_features_mask = self.model.roi_heads.mask_predictor.conv5_mask.in_channels
39
- hidden_layer = 256
40
- self.model.roi_heads.mask_predictor = detection.mask_rcnn.MaskRCNNPredictor(
41
- in_features_mask, hidden_layer, num_classes
42
- )
43
-
44
- self.model.eval()
45
- self.model = self.model.to(self.device)
46
- print("βœ… Model loaded successfully!")
47
- return True
48
-
49
- except Exception as e:
50
- print(f"❌ Error loading model: {e}")
51
- return False
52
-
53
- def load_robust_model():
54
- """Load the most robust brain tumor detection model"""
55
  global model
56
  if model is None:
57
- detector = TumorDetector()
58
-
59
- # Try multiple model options
60
- if detector.load_maskrcnn_model():
61
- model = detector.model
62
- print("βœ… Using Mask R-CNN for comprehensive tumor detection")
63
- else:
64
- # Fallback to PyTorch Hub U-Net
65
- try:
66
- print("πŸ”„ Falling back to PyTorch Hub U-Net...")
67
- model = torch.hub.load(
68
- 'mateuszbuda/brain-segmentation-pytorch',
69
- 'unet',
70
- in_channels=3,
71
- out_channels=1,
72
- init_features=32,
73
- pretrained=True,
74
- force_reload=False
75
- )
76
- model.eval()
77
- model = model.to(device)
78
- print("βœ… Fallback model loaded!")
79
- except:
80
- model = None
81
- print("❌ All models failed to load!")
82
-
83
  return model
84
 
85
- def enhance_mri_image(image):
86
- """Advanced MRI enhancement for better tumor detection"""
87
- if isinstance(image, Image.Image):
88
- image_np = np.array(image)
89
- else:
90
- image_np = image
91
-
92
- # Convert to grayscale for processing
93
- if len(image_np.shape) == 3:
94
- gray = cv2.cvtColor(image_np, cv2.COLOR_RGB2GRAY)
95
- else:
96
- gray = image_np
97
-
98
- # Multi-step enhancement
99
- # 1. CLAHE for contrast
100
- clahe = cv2.createCLAHE(clipLimit=3.0, tileGridSize=(8,8))
101
- enhanced = clahe.apply(gray)
102
-
103
- # 2. Gaussian blur for noise reduction
104
- denoised = cv2.GaussianBlur(enhanced, (3,3), 0)
105
 
106
- # 3. Histogram equalization
107
- hist_eq = cv2.equalizeHist(denoised)
108
-
109
- # 4. Normalize intensity
110
- normalized = cv2.normalize(hist_eq, None, 0, 255, cv2.NORM_MINMAX)
111
-
112
- # 5. Edge enhancement
113
- kernel = np.array([[-1,-1,-1], [-1,9,-1], [-1,-1,-1]])
114
- sharpened = cv2.filter2D(normalized, -1, kernel)
115
-
116
- # Convert back to RGB
117
- enhanced_rgb = cv2.cvtColor(sharpened, cv2.COLOR_GRAY2RGB)
118
-
119
- return enhanced_rgb
120
-
121
- def preprocess_for_detection(image):
122
- """Preprocess image for comprehensive tumor detection"""
123
- # Enhance the image
124
- enhanced_image = enhance_mri_image(image)
125
- enhanced_pil = Image.fromarray(enhanced_image)
126
-
127
- # Resize to standard size
128
- enhanced_pil = enhanced_pil.resize((512, 512), Image.LANCZOS)
129
-
130
- # Convert to tensor with proper normalization
131
- transform = transforms.Compose([
132
- transforms.ToTensor(),
133
- transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
134
- ])
135
-
136
- image_tensor = transform(enhanced_pil).unsqueeze(0)
137
- return image_tensor, enhanced_pil
138
-
139
- def detect_all_tumors(image):
140
- """Comprehensive tumor detection and segmentation"""
141
- current_model = load_robust_model()
142
-
143
- if current_model is None:
144
- return None, "❌ Model failed to load. Please check your setup."
145
-
146
  if image is None:
147
- return None, "⚠️ Please upload a brain MRI image."
148
-
149
  try:
150
- print("🧠 Detecting ALL brain tumors in the image...")
 
151
 
152
- # Preprocess image
153
- input_tensor, processed_img = preprocess_for_detection(image)
154
- input_tensor = input_tensor.to(device)
155
-
156
- # Make prediction
 
 
 
 
157
  with torch.no_grad():
158
- if hasattr(current_model, 'roi_heads'): # Mask R-CNN
159
- predictions = current_model(input_tensor)
160
- # Process Mask R-CNN output
161
- boxes = predictions[0]['boxes'].cpu().numpy()
162
- masks = predictions[0]['masks'].cpu().numpy()
163
- scores = predictions[0]['scores'].cpu().numpy()
164
-
165
- # Filter high-confidence detections
166
- threshold = 0.5
167
- high_conf_mask = scores > threshold
168
- final_masks = masks[high_conf_mask]
169
- final_boxes = boxes[high_conf_mask]
170
- final_scores = scores[high_conf_mask]
171
-
172
- print(f"🎯 Detected {len(final_masks)} tumor(s) with confidence > {threshold}")
173
-
174
- else: # U-Net
175
- prediction = current_model(input_tensor)
176
- prediction = torch.sigmoid(prediction)
177
- prediction = prediction.squeeze().cpu().numpy()
178
-
179
- # Create binary mask
180
- binary_mask = (prediction > 0.3).astype(np.uint8)
181
-
182
- # Find connected components (separate tumors)
183
- num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(binary_mask)
184
- final_masks = []
185
- for i in range(1, num_labels):
186
- if stats[i, cv2.CC_STAT_AREA] > 100: # Filter small regions
187
- tumor_mask = (labels == i).astype(np.uint8)
188
- final_masks.append(tumor_mask)
189
-
190
- print(f"🎯 Detected {len(final_masks)} separate tumor region(s)")
191
-
192
- # Create comprehensive visualization
193
- original_array = np.array(image.resize((512, 512)))
194
- processed_array = np.array(processed_img)
195
 
196
- # Create combined visualization
197
- fig, axes = plt.subplots(2, 3, figsize=(18, 12))
198
- fig.suptitle('🧠 Comprehensive Brain Tumor Detection', fontsize=20, fontweight='bold')
199
-
200
- # Row 1: Original, Enhanced, All Tumors
201
- axes[0,0].imshow(original_array)
202
- axes[0,0].set_title('Original MRI', fontsize=14, fontweight='bold')
203
- axes[0,0].axis('off')
204
-
205
- axes[0,1].imshow(processed_array)
206
- axes[0,1].set_title('Enhanced Image', fontsize=14, fontweight='bold')
207
- axes[0,1].axis('off')
208
-
209
- # Combined tumor overlay
210
- combined_overlay = original_array.copy()
211
- colors = [(255,0,0), (0,255,0), (0,0,255), (255,255,0), (255,0,255)] # Different colors for different tumors
212
 
213
- if len(final_masks) > 0:
214
- for i, mask in enumerate(final_masks):
215
- color = colors[i % len(colors)]
216
- if len(mask.shape) == 3:
217
- mask = mask[0] # Handle Mask R-CNN format
218
- mask_resized = cv2.resize(mask, (512, 512))
219
- combined_overlay[mask_resized > 0.5] = color
220
-
221
- combined_overlay = cv2.addWeighted(original_array, 0.6, combined_overlay, 0.4, 0)
 
 
 
 
 
 
 
222
 
223
- axes[0,2].imshow(combined_overlay)
224
- axes[0,2].set_title(f'All Tumors Detected ({len(final_masks)})', fontsize=14, fontweight='bold')
225
- axes[0,2].axis('off')
226
-
227
- # Row 2: Individual tumor analysis
228
- if len(final_masks) >= 1:
229
- mask1 = final_masks[0]
230
- if len(mask1.shape) == 3:
231
- mask1 = mask1[0]
232
- mask1_colored = np.zeros((512, 512, 3), dtype=np.uint8)
233
- mask1_resized = cv2.resize(mask1, (512, 512))
234
- mask1_colored[:, :, 0] = mask1_resized * 255
235
- axes[1,0].imshow(mask1_colored)
236
- axes[1,0].set_title('Tumor Region 1', fontsize=14)
237
- axes[1,0].axis('off')
238
- else:
239
- axes[1,0].text(0.5, 0.5, 'No Tumor\nDetected', ha='center', va='center', fontsize=16)
240
- axes[1,0].axis('off')
241
-
242
- if len(final_masks) >= 2:
243
- mask2 = final_masks[1]
244
- if len(mask2.shape) == 3:
245
- mask2 = mask2[0]
246
- mask2_colored = np.zeros((512, 512, 3), dtype=np.uint8)
247
- mask2_resized = cv2.resize(mask2, (512, 512))
248
- mask2_colored[:, :, 1] = mask2_resized * 255
249
- axes[1,1].imshow(mask2_colored)
250
- axes[1,1].set_title('Tumor Region 2', fontsize=14)
251
- axes[1,1].axis('off')
252
- else:
253
- axes[1,1].text(0.5, 0.5, 'Single Tumor\nOnly', ha='center', va='center', fontsize=16)
254
- axes[1,1].axis('off')
255
-
256
- # Statistics pie chart
257
- if len(final_masks) > 0:
258
- total_pixels = 512 * 512
259
- tumor_pixels = sum([np.sum(cv2.resize(mask[0] if len(mask.shape) == 3 else mask, (512, 512))) for mask in final_masks])
260
- healthy_pixels = total_pixels - tumor_pixels
261
-
262
- if tumor_pixels > 0:
263
- axes[1,2].pie([healthy_pixels, tumor_pixels],
264
- labels=['Healthy', 'Tumor'],
265
- colors=['lightblue', 'red'],
266
- autopct='%1.1f%%',
267
- startangle=90)
268
- axes[1,2].set_title('Tissue Distribution', fontsize=14, fontweight='bold')
269
- else:
270
- axes[1,2].text(0.5, 0.5, 'No Tumors\nDetected', ha='center', va='center', fontsize=16)
271
- axes[1,2].axis('off')
272
- else:
273
- axes[1,2].text(0.5, 0.5, 'Healthy\nBrain', ha='center', va='center', fontsize=16, color='green')
274
- axes[1,2].axis('off')
275
-
276
  plt.tight_layout()
277
-
278
- # Save result
279
  buf = io.BytesIO()
280
- plt.savefig(buf, format='png', dpi=150, bbox_inches='tight', facecolor='white')
281
  buf.seek(0)
282
  plt.close()
283
-
284
  result_image = Image.open(buf)
285
-
286
- # Calculate comprehensive statistics
287
- total_tumor_pixels = 0
288
- tumor_areas = []
289
 
290
- if len(final_masks) > 0:
291
- for i, mask in enumerate(final_masks):
292
- if len(mask.shape) == 3:
293
- mask = mask[0]
294
- mask_resized = cv2.resize(mask, (512, 512))
295
- pixels = np.sum(mask_resized > 0.5)
296
- total_tumor_pixels += pixels
297
- tumor_areas.append(pixels)
298
-
299
- total_percentage = (total_tumor_pixels / (512*512)) * 100
300
-
301
- # Comprehensive analysis report
302
- analysis_text = f"""
303
- ## 🧠 Comprehensive Brain Tumor Analysis
304
-
305
- ### 🎯 Detection Summary:
306
- - **Tumors Detected**: **{len(final_masks)} tumor region(s)**
307
- - **Total Tumor Area**: {total_tumor_pixels:,} pixels ({total_percentage:.2f}%)
308
- - **Detection Model**: {'Mask R-CNN Instance Segmentation' if hasattr(current_model, 'roi_heads') else 'Enhanced U-Net Segmentation'}
309
-
310
- ### πŸ“Š Individual Tumor Analysis:
311
- """
312
 
313
- for i, area in enumerate(tumor_areas):
314
- percentage = (area / (512*512)) * 100
315
- analysis_text += f"- **Tumor {i+1}**: {area:,} pixels ({percentage:.2f}%)\n"
316
-
317
- analysis_text += f"""
318
-
319
- ### πŸ”¬ Technical Details:
320
- - **Enhancement**: CLAHE + Histogram Equalization + Edge Enhancement
321
- - **Resolution**: 512Γ—512 pixels for high-precision detection
322
- - **Detection Threshold**: Multiple confidence levels
323
- - **Processing**: GPU-accelerated inference
324
 
325
- ### 🎯 Clinical Insights:
326
- - **Status**: {'πŸ”΄ MULTIPLE TUMORS DETECTED' if len(final_masks) > 1 else 'πŸ”΄ TUMOR DETECTED' if len(final_masks) == 1 else '🟒 NO TUMORS DETECTED'}
327
- - **Complexity**: {'High (multiple lesions)' if len(final_masks) > 1 else 'Standard (single lesion)' if len(final_masks) == 1 else 'Normal brain'}
328
- - **Recommendation**: {'Immediate specialist consultation' if total_percentage > 2.0 else 'Medical evaluation advised' if total_percentage > 0 else 'Regular monitoring'}
329
 
330
- ### ⚠️ Medical Disclaimer:
331
- This AI analysis is for **research purposes only**. Results should be verified by qualified radiologists. Not for diagnostic use.
 
 
332
  """
333
-
334
- print("βœ… Comprehensive tumor analysis completed!")
335
  return result_image, analysis_text
336
-
337
  except Exception as e:
338
- error_msg = f"❌ Error during tumor detection: {str(e)}"
339
- print(error_msg)
340
- return None, error_msg
341
 
342
  def clear_all():
343
- return None, None, "Upload a brain MRI image for comprehensive tumor analysis."
344
-
345
- # Enhanced CSS
346
- css = """
347
- .gradio-container {
348
- max-width: 1400px !important;
349
- margin: auto !important;
350
- }
351
- #title {
352
- text-align: center;
353
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
354
- color: white;
355
- padding: 30px;
356
- border-radius: 15px;
357
- margin-bottom: 30px;
358
- box-shadow: 0 10px 20px rgba(0,0,0,0.1);
359
- }
360
- """
361
-
362
- # Create comprehensive Gradio interface
363
- with gr.Blocks(css=css, title="🧠 Comprehensive Brain Tumor Detection") as app:
364
 
 
 
 
365
  gr.HTML("""
366
- <div id="title">
367
- <h1>🧠 Advanced Brain Tumor Detection AI</h1>
368
- <p style="font-size: 18px; margin-top: 15px;">
369
- Detects ALL Tumors β€’ Instance Segmentation β€’ Multi-Tumor Analysis
370
- </p>
371
- <p style="font-size: 14px; margin-top: 10px; opacity: 0.9;">
372
- Powered by Mask R-CNN + Enhanced Image Processing
373
- </p>
374
  </div>
375
  """)
376
-
377
  with gr.Row():
378
  with gr.Column(scale=1):
379
- gr.Markdown("### πŸ“€ Upload Brain MRI")
380
-
381
  image_input = gr.Image(
382
- label="Brain MRI Scan",
383
  type="pil",
384
  sources=["upload", "webcam"],
385
- height=350
386
  )
387
-
388
- with gr.Row():
389
- analyze_btn = gr.Button("πŸ” Detect All Tumors", variant="primary", scale=2, size="lg")
390
- clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary", scale=1)
391
-
392
  with gr.Column(scale=2):
393
- gr.Markdown("### πŸ“Š Comprehensive Analysis")
394
-
395
  output_image = gr.Image(
396
- label="Complete Tumor Analysis",
397
  type="pil",
398
- height=600
399
  )
400
-
401
  analysis_output = gr.Markdown(
402
- value="Upload a brain MRI image to detect and analyze ALL tumors present.",
403
- elem_id="analysis"
404
  )
405
-
406
  # Event handlers
407
  analyze_btn.click(
408
- fn=detect_all_tumors,
409
  inputs=[image_input],
410
- outputs=[output_image, analysis_output],
411
- show_progress=True
412
  )
413
-
414
  clear_btn.click(
415
  fn=clear_all,
416
  inputs=[],
@@ -418,10 +153,4 @@ with gr.Blocks(css=css, title="🧠 Comprehensive Brain Tumor Detection") as app
418
  )
419
 
420
  if __name__ == "__main__":
421
- print("πŸš€ Starting Comprehensive Brain Tumor Detection System...")
422
- app.launch(
423
- server_name="0.0.0.0",
424
- server_port=7860,
425
- show_error=True,
426
- share=False
427
- )
 
1
  import gradio as gr
2
  import torch
 
3
  import numpy as np
4
  import cv2
5
  from PIL import Image
6
  import matplotlib.pyplot as plt
7
  import io
8
+ import segmentation_models_pytorch as smp
9
  from torchvision import transforms
 
 
 
 
10
 
 
 
11
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
12
+ model = None
13
 
14
+ def load_model():
15
+ """Load the most popular pretrained model"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  global model
17
  if model is None:
18
+ # Most used: UNet with EfficientNet-B4 backbone
19
+ model = smp.Unet(
20
+ encoder_name="efficientnet-b4", # Most popular backbone
21
+ encoder_weights="imagenet", # Use ImageNet pretrained weights
22
+ in_channels=3, # Input channels
23
+ classes=1, # Output classes
24
+ )
25
+ model = model.to(device)
26
+ model.eval()
27
+ print("βœ… Model loaded successfully!")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  return model
29
 
30
+ def predict_tumor(image):
31
+ current_model = load_model()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  if image is None:
34
+ return None, "⚠️ Please upload an image first."
35
+
36
  try:
37
+ # Simple preprocessing
38
+ image = image.convert('RGB').resize((256, 256))
39
 
40
+ # Convert to tensor
41
+ transform = transforms.Compose([
42
+ transforms.ToTensor(),
43
+ transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
44
+ ])
45
+
46
+ input_tensor = transform(image).unsqueeze(0).to(device)
47
+
48
+ # Predict
49
  with torch.no_grad():
50
+ prediction = torch.sigmoid(current_model(input_tensor))
51
+ mask = (prediction > 0.5).float().squeeze().cpu().numpy()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
 
53
+ # Create visualization
54
+ fig, axes = plt.subplots(1, 3, figsize=(15, 5))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
+ # Original
57
+ axes[0].imshow(image)
58
+ axes[0].set_title('Original Image')
59
+ axes[0].axis('off')
60
+
61
+ # Mask
62
+ axes[1].imshow(mask, cmap='hot')
63
+ axes[1].set_title('Tumor Prediction')
64
+ axes[1].axis('off')
65
+
66
+ # Overlay
67
+ overlay = np.array(image)
68
+ overlay[mask > 0.5] = [255, 0, 0] # Red for tumor
69
+ axes[2].imshow(overlay)
70
+ axes[2].set_title('Overlay')
71
+ axes[2].axis('off')
72
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
  plt.tight_layout()
74
+
75
+ # Save to image
76
  buf = io.BytesIO()
77
+ plt.savefig(buf, format='png', bbox_inches='tight')
78
  buf.seek(0)
79
  plt.close()
80
+
81
  result_image = Image.open(buf)
 
 
 
 
82
 
83
+ # Stats
84
+ tumor_pixels = np.sum(mask > 0.5)
85
+ total_pixels = mask.size
86
+ tumor_percentage = (tumor_pixels / total_pixels) * 100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
+ analysis_text = f"""
89
+ ## 🧠 Brain Tumor Analysis
 
 
 
 
 
 
 
 
 
90
 
91
+ **πŸ“Š Results:**
92
+ - Tumor area: {tumor_percentage:.2f}% of brain
93
+ - Status: {'πŸ”΄ TUMOR DETECTED' if tumor_percentage > 1 else '🟒 NO SIGNIFICANT TUMOR'}
 
94
 
95
+ **πŸ”¬ Model:**
96
+ - Architecture: U-Net + EfficientNet-B4
97
+ - Framework: segmentation-models-pytorch
98
+ - Device: {device.type.upper()}
99
  """
100
+
 
101
  return result_image, analysis_text
102
+
103
  except Exception as e:
104
+ return None, f"❌ Error: {str(e)}"
 
 
105
 
106
  def clear_all():
107
+ return None, None, "Upload an image to analyze"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
+ # Create Gradio interface
110
+ with gr.Blocks(title="🧠 Brain Tumor Segmentation") as app:
111
+
112
  gr.HTML("""
113
+ <div style="text-align: center; padding: 20px; background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); color: white; border-radius: 10px; margin-bottom: 20px;">
114
+ <h1>🧠 Brain Tumor Segmentation</h1>
115
+ <p>Using the most popular segmentation-models-pytorch</p>
 
 
 
 
 
116
  </div>
117
  """)
118
+
119
  with gr.Row():
120
  with gr.Column(scale=1):
 
 
121
  image_input = gr.Image(
122
+ label="Upload Brain MRI",
123
  type="pil",
124
  sources=["upload", "webcam"],
125
+ height=300
126
  )
127
+
128
+ analyze_btn = gr.Button("πŸ” Analyze", variant="primary", size="lg")
129
+ clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary")
130
+
 
131
  with gr.Column(scale=2):
 
 
132
  output_image = gr.Image(
133
+ label="Results",
134
  type="pil",
135
+ height=400
136
  )
137
+
138
  analysis_output = gr.Markdown(
139
+ value="Upload an image to get started"
 
140
  )
141
+
142
  # Event handlers
143
  analyze_btn.click(
144
+ fn=predict_tumor,
145
  inputs=[image_input],
146
+ outputs=[output_image, analysis_output]
 
147
  )
148
+
149
  clear_btn.click(
150
  fn=clear_all,
151
  inputs=[],
 
153
  )
154
 
155
  if __name__ == "__main__":
156
+ app.launch()