ArchCoder commited on
Commit
bccb310
·
verified ·
1 Parent(s): 82c9eec

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -4
app.py CHANGED
@@ -266,7 +266,7 @@ def generate_attention_heatmap(attention_maps):
266
  return heatmap
267
 
268
  def analyze_image(image, ground_truth, filename):
269
- """Main analysis function - FIXED VERSION"""
270
  if model is None:
271
  return None, "Model not loaded. Please restart the application."
272
 
@@ -274,28 +274,66 @@ def analyze_image(image, ground_truth, filename):
274
  return None, "Please select an image first."
275
 
276
  try:
 
 
 
 
 
277
  # Preprocess
278
  input_tensor = preprocess_for_model(image).to(device)
 
 
279
 
280
  # Get prediction and attention maps
281
  with torch.no_grad():
282
- # Get model output (prediction + attention maps)
283
  model_output, attention_maps = model(input_tensor)
284
 
285
- # Apply sigmoid and threshold to get binary mask
 
 
 
286
  pred_mask = torch.sigmoid(model_output)
 
 
 
 
 
 
 
287
  binary_mask = (pred_mask > 0.5).float()
 
 
288
 
289
- # Convert to numpy for further processing
290
  binary_mask_np = binary_mask.squeeze().cpu().numpy()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
291
 
292
  # Post-processing (morphological operations)
 
293
  kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
294
  binary_mask_np = cv2.morphologyEx(binary_mask_np.astype(np.uint8), cv2.MORPH_OPEN, kernel)
295
  binary_mask_np = cv2.morphologyEx(binary_mask_np, cv2.MORPH_CLOSE, kernel)
 
296
 
297
  # Generate attention heatmap
 
298
  att_heatmap = generate_attention_heatmap(attention_maps)
 
299
 
300
  # Create visualization
301
  if ground_truth is not None:
@@ -324,8 +362,12 @@ def analyze_image(image, ground_truth, filename):
324
 
325
  # Ground truth
326
  gt_array = np.array(ground_truth.resize((256, 256)))
 
 
 
327
  # Normalize ground truth to binary (0 or 1)
328
  gt_binary = (gt_array > 128).astype(np.uint8)
 
329
 
330
  axes[1,0].imshow(gt_binary, cmap='gray')
331
  axes[1,0].set_title('Ground Truth Mask', fontsize=12, weight='bold')
@@ -349,6 +391,13 @@ def analyze_image(image, ground_truth, filename):
349
  # Dice score
350
  dice = (2 * intersection) / (np.sum(pred_binary) + np.sum(gt_binary_bool) + 1e-8)
351
 
 
 
 
 
 
 
 
352
  axes[1,2].text(0.1, 0.6, f'IoU: {iou:.4f}', fontsize=16, weight='bold')
353
  axes[1,2].text(0.1, 0.4, f'Dice: {dice:.4f}', fontsize=16, weight='bold')
354
  axes[1,2].set_xlim(0, 1)
@@ -381,6 +430,10 @@ def analyze_image(image, ground_truth, filename):
381
  total_pixels = binary_mask_np.size
382
  tumor_percentage = (tumor_pixels / total_pixels) * 100
383
 
 
 
 
 
384
  analysis_text = f"""
385
  # Analysis Results
386
 
@@ -410,6 +463,7 @@ def analyze_image(image, ground_truth, filename):
410
  print(error_msg) # For debugging
411
  return None, error_msg
412
 
 
413
  # Initialize model and dataset at startup
414
  print("Initializing application components...")
415
  model_loaded = download_and_load_model()
 
266
  return heatmap
267
 
268
  def analyze_image(image, ground_truth, filename):
269
+ """Main analysis function - DEBUG VERSION"""
270
  if model is None:
271
  return None, "Model not loaded. Please restart the application."
272
 
 
274
  return None, "Please select an image first."
275
 
276
  try:
277
+ print("="*50)
278
+ print("DEBUG: Starting analysis...")
279
+ print(f"Input image mode: {image.mode}")
280
+ print(f"Input image size: {image.size}")
281
+
282
  # Preprocess
283
  input_tensor = preprocess_for_model(image).to(device)
284
+ print(f"Input tensor shape: {input_tensor.shape}")
285
+ print(f"Input tensor min/max: {input_tensor.min():.4f}/{input_tensor.max():.4f}")
286
 
287
  # Get prediction and attention maps
288
  with torch.no_grad():
289
+ print("Getting model output...")
290
  model_output, attention_maps = model(input_tensor)
291
 
292
+ print(f"Model output shape: {model_output.shape}")
293
+ print(f"Model output min/max BEFORE sigmoid: {model_output.min():.4f}/{model_output.max():.4f}")
294
+
295
+ # Apply sigmoid
296
  pred_mask = torch.sigmoid(model_output)
297
+ print(f"After sigmoid min/max: {pred_mask.min():.4f}/{pred_mask.max():.4f}")
298
+
299
+ # Check values before thresholding
300
+ unique_vals = torch.unique(pred_mask)
301
+ print(f"Unique values in prediction: {unique_vals[:10]}") # Show first 10 unique values
302
+
303
+ # Apply threshold
304
  binary_mask = (pred_mask > 0.5).float()
305
+ print(f"Binary mask shape: {binary_mask.shape}")
306
+ print(f"Binary mask sum (number of 1s): {binary_mask.sum()}")
307
 
308
+ # Convert to numpy
309
  binary_mask_np = binary_mask.squeeze().cpu().numpy()
310
+ print(f"Numpy binary mask shape: {binary_mask_np.shape}")
311
+ print(f"Numpy binary mask unique values: {np.unique(binary_mask_np)}")
312
+ print(f"Numpy binary mask sum: {np.sum(binary_mask_np)}")
313
+
314
+ # Try different thresholds if 0.5 doesn't work
315
+ if np.sum(binary_mask_np) == 0:
316
+ print("No pixels detected with threshold 0.5, trying lower thresholds...")
317
+ for thresh in [0.3, 0.2, 0.1, 0.05]:
318
+ test_mask = (pred_mask > thresh).float().squeeze().cpu().numpy()
319
+ pixel_count = np.sum(test_mask)
320
+ print(f"Threshold {thresh}: {pixel_count} pixels")
321
+ if pixel_count > 0:
322
+ print(f"Using threshold {thresh} instead of 0.5")
323
+ binary_mask_np = test_mask
324
+ break
325
 
326
  # Post-processing (morphological operations)
327
+ print("Applying morphological operations...")
328
  kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
329
  binary_mask_np = cv2.morphologyEx(binary_mask_np.astype(np.uint8), cv2.MORPH_OPEN, kernel)
330
  binary_mask_np = cv2.morphologyEx(binary_mask_np, cv2.MORPH_CLOSE, kernel)
331
+ print(f"After morphological ops sum: {np.sum(binary_mask_np)}")
332
 
333
  # Generate attention heatmap
334
+ print("Generating attention heatmap...")
335
  att_heatmap = generate_attention_heatmap(attention_maps)
336
+ print(f"Attention heatmap shape: {att_heatmap.shape}")
337
 
338
  # Create visualization
339
  if ground_truth is not None:
 
362
 
363
  # Ground truth
364
  gt_array = np.array(ground_truth.resize((256, 256)))
365
+ print(f"Ground truth array shape: {gt_array.shape}")
366
+ print(f"Ground truth unique values: {np.unique(gt_array)}")
367
+
368
  # Normalize ground truth to binary (0 or 1)
369
  gt_binary = (gt_array > 128).astype(np.uint8)
370
+ print(f"GT binary sum: {np.sum(gt_binary)}")
371
 
372
  axes[1,0].imshow(gt_binary, cmap='gray')
373
  axes[1,0].set_title('Ground Truth Mask', fontsize=12, weight='bold')
 
391
  # Dice score
392
  dice = (2 * intersection) / (np.sum(pred_binary) + np.sum(gt_binary_bool) + 1e-8)
393
 
394
+ print(f"Final IoU: {iou:.4f}")
395
+ print(f"Final Dice: {dice:.4f}")
396
+ print(f"Intersection: {intersection}")
397
+ print(f"Union: {union}")
398
+ print(f"Pred pixels: {np.sum(pred_binary)}")
399
+ print(f"GT pixels: {np.sum(gt_binary_bool)}")
400
+
401
  axes[1,2].text(0.1, 0.6, f'IoU: {iou:.4f}', fontsize=16, weight='bold')
402
  axes[1,2].text(0.1, 0.4, f'Dice: {dice:.4f}', fontsize=16, weight='bold')
403
  axes[1,2].set_xlim(0, 1)
 
430
  total_pixels = binary_mask_np.size
431
  tumor_percentage = (tumor_pixels / total_pixels) * 100
432
 
433
+ print(f"Final tumor pixels: {tumor_pixels}")
434
+ print(f"Final tumor percentage: {tumor_percentage:.2f}%")
435
+ print("="*50)
436
+
437
  analysis_text = f"""
438
  # Analysis Results
439
 
 
463
  print(error_msg) # For debugging
464
  return None, error_msg
465
 
466
+
467
  # Initialize model and dataset at startup
468
  print("Initializing application components...")
469
  model_loaded = download_and_load_model()