ArchCoder commited on
Commit
c5d3869
Β·
verified Β·
1 Parent(s): 6f09e0c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +268 -124
app.py CHANGED
@@ -1,127 +1,212 @@
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
  from torchvision import transforms
 
 
 
9
 
10
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
11
  model = None
12
 
13
- def load_brain_tumor_model():
14
- """Load ACTUAL brain tumor segmentation model"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  global model
16
  if model is None:
17
  try:
18
- # Use the ACTUAL brain segmentation model from PyTorch Hub
19
- print("πŸ”„ Loading brain tumor segmentation model...")
20
- model = torch.hub.load(
21
- 'mateuszbuda/brain-segmentation-pytorch',
22
- 'unet',
23
- in_channels=3,
24
- out_channels=1,
25
- init_features=32,
26
- pretrained=True,
27
- force_reload=False
28
- )
 
 
29
  model.eval()
30
- model = model.to(device)
31
- print("βœ… Brain tumor model loaded successfully!")
32
  except Exception as e:
33
- print(f"❌ Error loading model: {e}")
34
  model = None
35
  return model
36
 
37
- def preprocess_for_brain_model(image):
38
- """Correct preprocessing for brain tumor model"""
39
- # Convert to RGB if needed
40
- if image.mode != 'RGB':
41
- image = image.convert('RGB')
42
 
43
- # Resize to expected size
44
- image = image.resize((256, 256), Image.LANCZOS)
45
-
46
- # Apply the CORRECT normalization for brain segmentation model
47
- transform = transforms.Compose([
48
- transforms.ToTensor(),
49
- transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
50
  ])
51
 
52
- return transform(image).unsqueeze(0)
53
 
54
  def predict_tumor(image):
55
- current_model = load_brain_tumor_model()
56
 
57
  if current_model is None:
58
- return None, "❌ Brain tumor model failed to load."
59
 
60
  if image is None:
61
  return None, "⚠️ Please upload an image first."
62
 
63
  try:
64
- print("🧠 Processing with brain tumor model...")
65
 
66
- # Use correct preprocessing for brain model
67
- input_tensor = preprocess_for_brain_model(image).to(device)
68
 
69
- # Predict with brain tumor model
70
  with torch.no_grad():
71
- prediction = torch.sigmoid(current_model(input_tensor))
72
- pred_np = prediction.squeeze().cpu().numpy()
73
 
74
- # FIXED: Better thresholding for clean masks
75
- # Use a higher threshold to get clean regions
76
- threshold = 0.5
77
- binary_mask = (pred_np > threshold).astype(np.uint8)
78
 
79
- # FIXED: Aggressive cleanup to get solid regions like your target image
80
- if np.sum(binary_mask) > 0:
81
- # Remove tiny scattered dots
82
- kernel_small = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
83
- binary_mask = cv2.morphologyEx(binary_mask, cv2.MORPH_OPEN, kernel_small)
84
-
85
- # Fill holes and connect nearby regions
86
- kernel_large = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (7,7))
87
- binary_mask = cv2.morphologyEx(binary_mask, cv2.MORPH_CLOSE, kernel_large)
88
-
89
- # Keep only significant regions (remove small artifacts)
90
- num_labels, labels, stats, centroids = cv2.connectedComponentsWithStats(binary_mask)
91
- clean_mask = np.zeros_like(binary_mask)
92
-
93
- for i in range(1, num_labels):
94
- area = stats[i, cv2.CC_STAT_AREA]
95
- if area > 100: # Only keep regions larger than 100 pixels
96
- clean_mask[labels == i] = 1
97
-
98
- binary_mask = clean_mask
99
-
100
- # Create the CORRECT visualization format
101
- fig, axes = plt.subplots(1, 3, figsize=(15, 5))
102
- fig.suptitle('🧠 Brain Tumor Segmentation Results', fontsize=16, fontweight='bold')
103
 
104
- # Original image
105
- axes[0].imshow(image)
106
- axes[0].set_title('Original MRI', fontsize=12, fontweight='bold')
107
- axes[0].axis('off')
108
 
109
- # Clean binary mask (like your target image)
110
- mask_display = binary_mask * 255 # Convert to 0-255 range
111
- axes[1].imshow(mask_display, cmap='gray', vmin=0, vmax=255)
112
- axes[1].set_title('Tumor Segmentation', fontsize=12, fontweight='bold')
113
- axes[1].axis('off')
114
 
115
- # Overlay
116
- overlay = np.array(image.resize((256, 256)))
117
- if np.sum(binary_mask) > 0:
118
- # Create clean red overlay
119
- overlay[binary_mask == 1] = [255, 0, 0] # Pure red for tumor
120
- overlay = cv2.addWeighted(np.array(image.resize((256, 256))), 0.7, overlay, 0.3, 0)
121
 
122
- axes[2].imshow(overlay)
123
- axes[2].set_title('Overlay (Red = Tumor)', fontsize=12, fontweight='bold')
124
- axes[2].axis('off')
 
125
 
126
  plt.tight_layout()
127
 
@@ -133,60 +218,91 @@ def predict_tumor(image):
133
 
134
  result_image = Image.open(buf)
135
 
136
- # Calculate statistics
137
- tumor_pixels = np.sum(binary_mask)
138
- total_pixels = binary_mask.size
139
  tumor_percentage = (tumor_pixels / total_pixels) * 100
140
 
 
 
 
 
141
  analysis_text = f"""
142
- ## 🧠 Brain Tumor Analysis Results
143
 
144
  ### πŸ“Š Detection Summary:
145
  - **Status**: {'πŸ”΄ TUMOR DETECTED' if tumor_pixels > 50 else '🟒 NO SIGNIFICANT TUMOR'}
146
  - **Tumor Area**: {tumor_percentage:.2f}% of brain region
147
  - **Tumor Pixels**: {tumor_pixels:,} pixels
148
- - **Max Confidence**: {pred_np.max():.3f}
 
149
 
150
- ### πŸ”¬ Model Information:
151
- - **Architecture**: U-Net specifically trained for brain segmentation
152
- - **Source**: mateuszbuda/brain-segmentation-pytorch
153
- - **Training Data**: LGG MRI dataset (medical-grade)
154
- - **Processing**: Clean binary segmentation (like medical standards)
155
  - **Device**: {device.type.upper()}
156
 
157
- ### πŸ“ˆ Quality Metrics:
158
- - **Segmentation Type**: βœ… Clean binary mask (medical standard)
159
- - **Noise Removal**: βœ… Scattered artifacts removed
160
- - **Region Connectivity**: βœ… Coherent tumor regions
161
- - **Threshold**: {threshold} (optimized for clean results)
 
 
 
 
 
 
162
 
163
  ### ⚠️ Medical Disclaimer:
164
- This analysis is for **research and educational purposes only**.
165
- Not intended for clinical diagnosis. Consult medical professionals.
 
 
 
166
  """
167
 
168
- print(f"βœ… Clean segmentation completed! Tumor area: {tumor_percentage:.2f}%")
169
  return result_image, analysis_text
170
 
171
  except Exception as e:
172
- error_msg = f"❌ Error: {str(e)}"
173
  print(error_msg)
174
  return None, error_msg
175
 
176
  def clear_all():
177
- return None, None, "Upload a brain MRI image for clean tumor segmentation"
178
 
179
- # Create Gradio interface
180
- with gr.Blocks(title="🧠 Clean Brain Tumor Segmentation") as app:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
 
182
  gr.HTML("""
183
- <div style="text-align: center; padding: 25px; background: linear-gradient(135deg, #1e40af 0%, #1e3a8a 100%); color: white; border-radius: 15px; margin-bottom: 25px;">
184
- <h1>🧠 Clean Brain Tumor Segmentation</h1>
185
  <p style="font-size: 18px; margin-top: 15px;">
186
- Medical-Grade Binary Segmentation β€’ Clean Output Masks
187
  </p>
188
  <p style="font-size: 14px; margin-top: 10px; opacity: 0.9;">
189
- Using brain-specific trained model (mateuszbuda/brain-segmentation-pytorch)
190
  </p>
191
  </div>
192
  """)
@@ -203,35 +319,62 @@ with gr.Blocks(title="🧠 Clean Brain Tumor Segmentation") as app:
203
  )
204
 
205
  with gr.Row():
206
- analyze_btn = gr.Button("πŸ” Generate Clean Segmentation", variant="primary", scale=2, size="lg")
207
  clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary", scale=1)
208
 
209
  gr.HTML("""
210
- <div style="margin-top: 20px; padding: 20px; background: linear-gradient(135deg, #f0f9ff 0%, #e0f2fe 100%); border-radius: 10px; border-left: 4px solid #1e40af;">
211
- <h4 style="color: #1e40af; margin-bottom: 15px;">βœ… Clean Segmentation Features:</h4>
212
  <ul style="margin: 10px 0; padding-left: 20px; line-height: 1.6;">
213
- <li><strong>Medical Model:</strong> Trained specifically on brain MRI data</li>
214
- <li><strong>Clean Output:</strong> Solid white regions (no scattered dots)</li>
215
- <li><strong>Binary Masks:</strong> Medical-standard format</li>
216
- <li><strong>Artifact Removal:</strong> Eliminates noise and false positives</li>
217
- <li><strong>Connected Regions:</strong> Coherent tumor boundaries</li>
218
  </ul>
219
  </div>
220
  """)
221
 
222
  with gr.Column(scale=2):
223
- gr.Markdown("### πŸ“Š Clean Segmentation Results")
224
 
225
  output_image = gr.Image(
226
- label="Clean Binary Segmentation",
227
  type="pil",
228
- height=400
229
  )
230
 
231
  analysis_output = gr.Markdown(
232
- value="Upload a brain MRI image to generate clean tumor segmentation masks.",
233
  elem_id="analysis"
234
  )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
  # Event handlers
237
  analyze_btn.click(
@@ -248,9 +391,10 @@ with gr.Blocks(title="🧠 Clean Brain Tumor Segmentation") as app:
248
  )
249
 
250
  if __name__ == "__main__":
251
- print("πŸš€ Starting Clean Brain Tumor Segmentation System...")
252
- print("βœ… Using brain-specific trained model")
253
- print("🎯 Optimized for clean binary output masks")
 
254
 
255
  app.launch(
256
  server_name="0.0.0.0",
 
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.transforms.functional as TF
11
+ import urllib.request
12
+ import os
13
 
14
  device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
15
  model = None
16
 
17
+ # Define your Attention U-Net architecture (from your training code)
18
+ class DoubleConv(nn.Module):
19
+ def __init__(self, in_channels, out_channels):
20
+ super(DoubleConv, self).__init__()
21
+ self.conv = nn.Sequential(
22
+ nn.Conv2d(in_channels, out_channels, 3, 1, 1, bias=False),
23
+ nn.BatchNorm2d(out_channels),
24
+ nn.ReLU(inplace=True),
25
+ nn.Conv2d(out_channels, out_channels, 3, 1, 1, bias=False),
26
+ nn.BatchNorm2d(out_channels),
27
+ nn.ReLU(inplace=True),
28
+ )
29
+
30
+ def forward(self, x):
31
+ return self.conv(x)
32
+
33
+ class AttentionBlock(nn.Module):
34
+ def __init__(self, F_g, F_l, F_int):
35
+ super(AttentionBlock, self).__init__()
36
+ self.W_g = nn.Sequential(
37
+ nn.Conv2d(F_g, F_int, kernel_size=1, stride=1, padding=0, bias=True),
38
+ nn.BatchNorm2d(F_int)
39
+ )
40
+
41
+ self.W_x = nn.Sequential(
42
+ nn.Conv2d(F_l, F_int, kernel_size=1, stride=1, padding=0, bias=True),
43
+ nn.BatchNorm2d(F_int)
44
+ )
45
+
46
+ self.psi = nn.Sequential(
47
+ nn.Conv2d(F_int, 1, kernel_size=1, stride=1, padding=0, bias=True),
48
+ nn.BatchNorm2d(1),
49
+ nn.Sigmoid()
50
+ )
51
+
52
+ self.relu = nn.ReLU(inplace=True)
53
+
54
+ def forward(self, g, x):
55
+ g1 = self.W_g(g)
56
+ x1 = self.W_x(x)
57
+ psi = self.relu(g1 + x1)
58
+ psi = self.psi(psi)
59
+ return x * psi
60
+
61
+ class AttentionUNET(nn.Module):
62
+ def __init__(self, in_channels=1, out_channels=1, features=[32, 64, 128, 256]):
63
+ super(AttentionUNET, self).__init__()
64
+ self.out_channels = out_channels
65
+ self.ups = nn.ModuleList()
66
+ self.downs = nn.ModuleList()
67
+ self.attentions = nn.ModuleList()
68
+ self.pool = nn.MaxPool2d(kernel_size=2, stride=2)
69
+
70
+ # Down part of UNET
71
+ for feature in features:
72
+ self.downs.append(DoubleConv(in_channels, feature))
73
+ in_channels = feature
74
+
75
+ # Bottleneck
76
+ self.bottleneck = DoubleConv(features[-1], features[-1]*2)
77
+
78
+ # Up part of UNET
79
+ for feature in reversed(features):
80
+ self.ups.append(nn.ConvTranspose2d(feature*2, feature, kernel_size=2, stride=2))
81
+ self.attentions.append(AttentionBlock(F_g=feature, F_l=feature, F_int=feature // 2))
82
+ self.ups.append(DoubleConv(feature*2, feature))
83
+
84
+ self.final_conv = nn.Conv2d(features[0], out_channels, kernel_size=1)
85
+
86
+ def forward(self, x):
87
+ skip_connections = []
88
+
89
+ for down in self.downs:
90
+ x = down(x)
91
+ skip_connections.append(x)
92
+ x = self.pool(x)
93
+
94
+ x = self.bottleneck(x)
95
+ skip_connections = skip_connections[::-1] #reverse list
96
+
97
+ for idx in range(0, len(self.ups), 2): #do up and double_conv
98
+ x = self.ups[idx](x)
99
+ skip_connection = skip_connections[idx//2]
100
+
101
+ if x.shape != skip_connection.shape:
102
+ x = TF.resize(x, size=skip_connection.shape[2:])
103
+
104
+ skip_connection = self.attentions[idx // 2](skip_connection, x)
105
+ concat_skip = torch.cat((skip_connection, x), dim=1)
106
+ x = self.ups[idx+1](concat_skip)
107
+
108
+ return self.final_conv(x)
109
+
110
+ def download_model():
111
+ """Download your trained model from HuggingFace"""
112
+ model_url = "https://huggingface.co/spaces/ArchCoder/the-op-segmenter/resolve/main/best_attention_model.pth.tar"
113
+ model_path = "best_attention_model.pth.tar"
114
+
115
+ if not os.path.exists(model_path):
116
+ print("πŸ“₯ Downloading your trained model...")
117
+ try:
118
+ urllib.request.urlretrieve(model_url, model_path)
119
+ print("βœ… Model downloaded successfully!")
120
+ except Exception as e:
121
+ print(f"❌ Failed to download model: {e}")
122
+ return None
123
+ else:
124
+ print("βœ… Model already exists!")
125
+
126
+ return model_path
127
+
128
+ def load_your_attention_model():
129
+ """Load YOUR trained Attention U-Net model"""
130
  global model
131
  if model is None:
132
  try:
133
+ print("πŸ”„ Loading your trained Attention U-Net model...")
134
+
135
+ # Download model if needed
136
+ model_path = download_model()
137
+ if model_path is None:
138
+ return None
139
+
140
+ # Initialize your model architecture
141
+ model = AttentionUNET(in_channels=1, out_channels=1).to(device)
142
+
143
+ # Load your trained weights
144
+ checkpoint = torch.load(model_path, map_location=device, weights_only=True)
145
+ model.load_state_dict(checkpoint["state_dict"])
146
  model.eval()
147
+
148
+ print("βœ… Your Attention U-Net model loaded successfully!")
149
  except Exception as e:
150
+ print(f"❌ Error loading your model: {e}")
151
  model = None
152
  return model
153
 
154
+ def preprocess_for_your_model(image):
155
+ """Preprocessing exactly like your Colab code"""
156
+ # Convert to grayscale (like your Colab code)
157
+ if image.mode != 'L':
158
+ image = image.convert('L')
159
 
160
+ # Use the exact same transform as your Colab code
161
+ val_test_transform = transforms.Compose([
162
+ transforms.Resize((256,256)),
163
+ transforms.ToTensor()
 
 
 
164
  ])
165
 
166
+ return val_test_transform(image).unsqueeze(0) # Add batch dimension
167
 
168
  def predict_tumor(image):
169
+ current_model = load_your_attention_model()
170
 
171
  if current_model is None:
172
+ return None, "❌ Failed to load your trained model."
173
 
174
  if image is None:
175
  return None, "⚠️ Please upload an image first."
176
 
177
  try:
178
+ print("🧠 Processing with YOUR trained Attention U-Net...")
179
 
180
+ # Use the exact preprocessing from your Colab code
181
+ input_tensor = preprocess_for_your_model(image).to(device)
182
 
183
+ # Predict using your model (exactly like your Colab code)
184
  with torch.no_grad():
185
+ pred_mask = torch.sigmoid(current_model(input_tensor))
186
+ pred_mask_binary = (pred_mask > 0.5).float()
187
 
188
+ # Convert to numpy (like your Colab code)
189
+ pred_mask_np = pred_mask_binary.cpu().squeeze().numpy()
190
+ original_np = np.array(image.convert('L').resize((256, 256)))
 
191
 
192
+ # Create inverted mask for visualization (like your Colab code)
193
+ inv_pred_mask_np = np.where(pred_mask_np == 1, 0, 255)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
194
 
195
+ # Create tumor-only image (like your Colab code)
196
+ tumor_only = np.where(pred_mask_np == 1, original_np, 255)
 
 
197
 
198
+ # Create visualization (matching your Colab 4-panel layout)
199
+ fig, axes = plt.subplots(1, 4, figsize=(20, 5))
200
+ fig.suptitle('🧠 Your Attention U-Net Results', fontsize=16, fontweight='bold')
 
 
201
 
202
+ titles = ["Original Image", "Tumor Segmentation", "Inverted Mask", "Tumor Only"]
203
+ images = [original_np, pred_mask_np * 255, inv_pred_mask_np, tumor_only]
204
+ cmaps = ['gray', 'hot', 'gray', 'gray']
 
 
 
205
 
206
+ for i, ax in enumerate(axes):
207
+ ax.imshow(images[i], cmap=cmaps[i])
208
+ ax.set_title(titles[i], fontsize=12, fontweight='bold')
209
+ ax.axis('off')
210
 
211
  plt.tight_layout()
212
 
 
218
 
219
  result_image = Image.open(buf)
220
 
221
+ # Calculate statistics (like your Colab code)
222
+ tumor_pixels = np.sum(pred_mask_np)
223
+ total_pixels = pred_mask_np.size
224
  tumor_percentage = (tumor_pixels / total_pixels) * 100
225
 
226
+ # Calculate confidence metrics
227
+ max_confidence = torch.max(pred_mask).item()
228
+ mean_confidence = torch.mean(pred_mask).item()
229
+
230
  analysis_text = f"""
231
+ ## 🧠 Your Attention U-Net Analysis Results
232
 
233
  ### πŸ“Š Detection Summary:
234
  - **Status**: {'πŸ”΄ TUMOR DETECTED' if tumor_pixels > 50 else '🟒 NO SIGNIFICANT TUMOR'}
235
  - **Tumor Area**: {tumor_percentage:.2f}% of brain region
236
  - **Tumor Pixels**: {tumor_pixels:,} pixels
237
+ - **Max Confidence**: {max_confidence:.4f}
238
+ - **Mean Confidence**: {mean_confidence:.4f}
239
 
240
+ ### πŸ”¬ Your Model Information:
241
+ - **Architecture**: YOUR trained Attention U-Net
242
+ - **Training Performance**: Dice: 0.8420, IoU: 0.7297
243
+ - **Input**: Grayscale (single channel)
244
+ - **Output**: Binary segmentation mask
245
  - **Device**: {device.type.upper()}
246
 
247
+ ### 🎯 Model Performance:
248
+ - **Training Accuracy**: 98.90%
249
+ - **Best Dice Score**: 0.8420
250
+ - **Best IoU Score**: 0.7297
251
+ - **Training Dataset**: Brain tumor segmentation dataset
252
+
253
+ ### πŸ“ˆ Processing Details:
254
+ - **Preprocessing**: Resize(256Γ—256) + ToTensor (your exact method)
255
+ - **Threshold**: 0.5 (sigmoid > 0.5)
256
+ - **Architecture**: Attention gates + Skip connections
257
+ - **Features**: [32, 64, 128, 256] channels
258
 
259
  ### ⚠️ Medical Disclaimer:
260
+ This is YOUR trained AI model for **research and educational purposes only**.
261
+ Results should be validated by medical professionals. Not for clinical diagnosis.
262
+
263
+ ### πŸ† Model Quality:
264
+ βœ… This is your own trained model with proven {tumor_percentage:.2f}% detection capability!
265
  """
266
 
267
+ print(f"βœ… Your model analysis completed! Tumor area: {tumor_percentage:.2f}%")
268
  return result_image, analysis_text
269
 
270
  except Exception as e:
271
+ error_msg = f"❌ Error with your model: {str(e)}"
272
  print(error_msg)
273
  return None, error_msg
274
 
275
  def clear_all():
276
+ return None, None, "Upload a brain MRI image to test YOUR trained Attention U-Net model"
277
 
278
+ # Enhanced CSS for your model
279
+ css = """
280
+ .gradio-container {
281
+ max-width: 1400px !important;
282
+ margin: auto !important;
283
+ }
284
+ #title {
285
+ text-align: center;
286
+ background: linear-gradient(135deg, #8B5CF6 0%, #7C3AED 100%);
287
+ color: white;
288
+ padding: 30px;
289
+ border-radius: 15px;
290
+ margin-bottom: 25px;
291
+ box-shadow: 0 8px 16px rgba(139, 92, 246, 0.3);
292
+ }
293
+ """
294
+
295
+ # Create Gradio interface for your model
296
+ with gr.Blocks(css=css, title="🧠 Your Attention U-Net Model", theme=gr.themes.Soft()) as app:
297
 
298
  gr.HTML("""
299
+ <div id="title">
300
+ <h1>🧠 YOUR Attention U-Net Model</h1>
301
  <p style="font-size: 18px; margin-top: 15px;">
302
+ Using Your Own Trained Model β€’ Dice: 0.8420 β€’ IoU: 0.7297
303
  </p>
304
  <p style="font-size: 14px; margin-top: 10px; opacity: 0.9;">
305
+ Loaded from: ArchCoder/the-op-segmenter HuggingFace Space
306
  </p>
307
  </div>
308
  """)
 
319
  )
320
 
321
  with gr.Row():
322
+ analyze_btn = gr.Button("πŸ” Analyze with YOUR Model", variant="primary", scale=2, size="lg")
323
  clear_btn = gr.Button("πŸ—‘οΈ Clear", variant="secondary", scale=1)
324
 
325
  gr.HTML("""
326
+ <div style="margin-top: 20px; padding: 20px; background: linear-gradient(135deg, #F3E8FF 0%, #EDE9FE 100%); border-radius: 10px; border-left: 4px solid #8B5CF6;">
327
+ <h4 style="color: #8B5CF6; margin-bottom: 15px;">πŸ† Your Model Features:</h4>
328
  <ul style="margin: 10px 0; padding-left: 20px; line-height: 1.6;">
329
+ <li><strong>Personal Model:</strong> Your own trained Attention U-Net</li>
330
+ <li><strong>Proven Performance:</strong> 84.2% Dice Score, 72.97% IoU</li>
331
+ <li><strong>Attention Gates:</strong> Advanced feature selection</li>
332
+ <li><strong>Clean Output:</strong> Binary segmentation masks</li>
333
+ <li><strong>4-Panel View:</strong> Complete analysis like your Colab</li>
334
  </ul>
335
  </div>
336
  """)
337
 
338
  with gr.Column(scale=2):
339
+ gr.Markdown("### πŸ“Š Your Model Results")
340
 
341
  output_image = gr.Image(
342
+ label="Your Attention U-Net Analysis",
343
  type="pil",
344
+ height=500
345
  )
346
 
347
  analysis_output = gr.Markdown(
348
+ value="Upload a brain MRI image to test YOUR trained Attention U-Net model.",
349
  elem_id="analysis"
350
  )
351
+
352
+ # Footer highlighting your model
353
+ gr.HTML("""
354
+ <div style="margin-top: 30px; padding: 25px; background-color: #F8FAFC; border-radius: 15px; border: 2px solid #8B5CF6;">
355
+ <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 30px;">
356
+ <div>
357
+ <h4 style="color: #8B5CF6; margin-bottom: 15px;">πŸ† Your Personal AI Model</h4>
358
+ <p><strong>Architecture:</strong> Attention U-Net with skip connections</p>
359
+ <p><strong>Performance:</strong> Dice: 0.8420, IoU: 0.7297, Accuracy: 98.90%</p>
360
+ <p><strong>Training:</strong> Your own dataset-specific training</p>
361
+ <p><strong>Features:</strong> [32, 64, 128, 256] channel progression</p>
362
+ </div>
363
+ <div>
364
+ <h4 style="color: #DC2626; margin-bottom: 15px;">⚠️ Your Model Disclaimer</h4>
365
+ <p style="color: #DC2626; font-weight: 600; line-height: 1.4;">
366
+ This is YOUR personally trained AI model for <strong>research purposes only</strong>.<br>
367
+ Results reflect your model's training performance.<br>
368
+ Always validate with medical professionals for any clinical application.
369
+ </p>
370
+ </div>
371
+ </div>
372
+ <hr style="margin: 20px 0; border: none; border-top: 2px solid #E5E7EB;">
373
+ <p style="text-align: center; color: #6B7280; margin: 10px 0; font-weight: 600;">
374
+ πŸš€ Your Personal Attention U-Net β€’ Downloaded from HuggingFace β€’ Research-Grade Performance
375
+ </p>
376
+ </div>
377
+ """)
378
 
379
  # Event handlers
380
  analyze_btn.click(
 
391
  )
392
 
393
  if __name__ == "__main__":
394
+ print("πŸš€ Starting YOUR Attention U-Net Model System...")
395
+ print("πŸ† Using your personally trained model")
396
+ print("πŸ“₯ Auto-downloading from HuggingFace...")
397
+ print("🎯 Expected performance: Dice 0.8420, IoU 0.7297")
398
 
399
  app.launch(
400
  server_name="0.0.0.0",