Shengxiao0709 commited on
Commit
7a2e7df
·
verified ·
1 Parent(s): b8d7827

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +50 -28
app.py CHANGED
@@ -398,62 +398,84 @@ def colorize_mask(mask: np.ndarray, num_colors: int = 512) -> np.ndarray:
398
 
399
  # ===== 分割功能 =====
400
  def segment_with_choice(use_box_choice, annot_value, mode="Overlay"):
401
- """分割处理函数:输出对齐 overlay_instances 逻辑"""
402
  if annot_value is None or len(annot_value) < 1:
 
403
  return None, "⚠️ 请先上传图像"
404
 
405
  img_path = annot_value[0]
406
  bboxes = annot_value[1] if len(annot_value) > 1 else []
407
 
408
- print(f"🖼️ Segmentation - Image: {img_path}")
409
-
410
  box_array = None
411
  if use_box_choice == "Yes" and bboxes:
412
  box = parse_first_bbox(bboxes)
413
  if box:
414
  xmin, ymin, xmax, ymax = map(int, box)
415
- box_array = (xmin, ymin, xmax, ymax)
416
  print(f"📦 Using box: {box_array}")
417
 
418
  try:
 
419
  mask = run_seg(SEG_MODEL, img_path, box=box_array, device=SEG_DEVICE)
420
- if mask is None:
421
- return None, "❌ 分割失败"
422
- print(f"✅ Segmentation done - Mask shape: {mask.shape}")
423
  except Exception as e:
424
- print(f"❌ Segmentation error: {e}")
425
  return None, f"分割失败: {str(e)}"
426
 
427
  try:
428
- # 读取原图(支持 JPG / PNG / TIF)
429
- img = Image.open(img_path).convert("RGB")
430
- img_rgb = np.array(img, dtype=np.float32)
431
- if img_rgb.max() > 1.5:
432
- img_rgb = img_rgb / 255.0
433
  except Exception as e:
434
- print(f"❌ Image load error: {e}")
435
- return None, f"图像读取失败: {str(e)}"
436
 
437
- # === 实例 mask 可视化(与你提供的 overlay_instances 完全一致) ===
438
- mask_np = np.array(mask).astype(np.int32)
439
- overlay = img_rgb.copy()
440
- cmap = cm.get_cmap("tab20", np.max(mask_np) + 1)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
441
  alpha = 0.5
 
442
 
443
- for inst_id in np.unique(mask_np):
444
- if inst_id == 0: # 背景跳过
445
  continue
446
- color = np.array(cmap(inst_id)[:3]) # RGB
447
- overlay[mask_np == inst_id] = (1 - alpha) * overlay[mask_np == inst_id] + alpha * color
 
 
 
 
 
 
 
448
 
449
  overlay = np.clip(overlay * 255.0, 0, 255).astype(np.uint8)
450
- overlay_img = Image.fromarray(overlay)
451
 
452
- # === 返回统计结果 ===
453
- num_instances = len(np.unique(mask_np)) - (1 if 0 in np.unique(mask_np) else 0)
454
- result_text = f"✅ 检测到 {num_instances} 个细胞"
455
 
456
- return overlay_img, result_text
457
 
458
  # ===== 计数功能 =====
459
  def count_cells_handler(image_path):
 
398
 
399
  # ===== 分割功能 =====
400
  def segment_with_choice(use_box_choice, annot_value, mode="Overlay"):
401
+ """分割处理函数(与原始版本完全对齐,适配新版 run_seg 接口)"""
402
  if annot_value is None or len(annot_value) < 1:
403
+ print("❌ No annotation input")
404
  return None, "⚠️ 请先上传图像"
405
 
406
  img_path = annot_value[0]
407
  bboxes = annot_value[1] if len(annot_value) > 1 else []
408
 
409
+ print(f"🖼️ Image path: {img_path}")
410
+
411
  box_array = None
412
  if use_box_choice == "Yes" and bboxes:
413
  box = parse_first_bbox(bboxes)
414
  if box:
415
  xmin, ymin, xmax, ymax = map(int, box)
416
+ box_array = [[xmin, ymin, xmax, ymax]]
417
  print(f"📦 Using box: {box_array}")
418
 
419
  try:
420
+ # 🔹 调用新版 run_seg 接口
421
  mask = run_seg(SEG_MODEL, img_path, box=box_array, device=SEG_DEVICE)
422
+ print("📏 Mask shape:", mask.shape, "dtype:", mask.dtype, "unique:", np.unique(mask))
 
 
423
  except Exception as e:
424
+ print(f"❌ Error during inference: {e}")
425
  return None, f"分割失败: {str(e)}"
426
 
427
  try:
428
+ img = Image.open(img_path)
429
+ print("📷 Image mode:", img.mode, "size:", img.size)
 
 
 
430
  except Exception as e:
431
+ print(f"❌ Failed to open image: {e}")
432
+ return None, f"图像打开失败: {str(e)}"
433
 
434
+ try:
435
+ img_rgb = img.convert("RGB").resize(mask.shape[::-1], resample=Image.BILINEAR)
436
+ img_np = np.array(img_rgb, dtype=np.float32)
437
+ if img_np.max() > 1.5:
438
+ img_np = img_np / 255.0
439
+ except Exception as e:
440
+ print(f"❌ Error in image conversion/resizing: {e}")
441
+ return None, f"图像预处理失败: {str(e)}"
442
+
443
+ # 🔹 mask → 实例掩码
444
+ mask_np = np.array(mask)
445
+ inst_mask = mask_np.astype(np.int32)
446
+ unique_ids = np.unique(inst_mask)
447
+ num_instances = len(unique_ids[unique_ids != 0])
448
+ print(f"✅ Instance IDs found: {unique_ids}, Total instances: {num_instances}")
449
+
450
+ if num_instances == 0:
451
+ print("⚠️ No instance found, returning dummy red image")
452
+ return Image.new("RGB", mask.shape[::-1], (255, 0, 0)), "⚠️ 未检测到细胞"
453
+
454
+ # ==== 🎨 Color Overlay (每个实例一个颜色) ====
455
+ overlay = img_np.copy()
456
  alpha = 0.5
457
+ cmap = cm.get_cmap("nipy_spectral", num_instances + 1)
458
 
459
+ for inst_id in np.unique(inst_mask):
460
+ if inst_id == 0:
461
  continue
462
+ binary_mask = (inst_mask == inst_id).astype(np.uint8)
463
+ color = np.array(cmap(inst_id / (num_instances + 1))[:3]) # RGB only
464
+ overlay[binary_mask == 1] = (1 - alpha) * overlay[binary_mask == 1] + alpha * color
465
+
466
+ # 🟡 绘制轮廓
467
+ contours = measure.find_contours(binary_mask, 0.5)
468
+ for contour in contours:
469
+ contour = contour.astype(np.int32)
470
+ overlay[contour[:, 0], contour[:, 1]] = [1.0, 1.0, 0.0] # 黄色轮廓
471
 
472
  overlay = np.clip(overlay * 255.0, 0, 255).astype(np.uint8)
 
473
 
474
+ # 🔹 两种显示模式
475
+ if mode == "Instance Mask Only":
476
+ return Image.fromarray(colorize_mask(inst_mask, num_colors=512)), f"✅ 检测到 {num_instances} 个细胞"
477
 
478
+ return Image.fromarray(overlay), f"✅ 检测到 {num_instances} 个细胞"
479
 
480
  # ===== 计数功能 =====
481
  def count_cells_handler(image_path):