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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +53 -23
app.py CHANGED
@@ -397,8 +397,39 @@ def colorize_mask(mask: np.ndarray, num_colors: int = 512) -> np.ndarray:
397
  return palette_arr[color_idx]
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, "⚠️ 请先上传图像"
@@ -407,7 +438,6 @@ def segment_with_choice(use_box_choice, annot_value, mode="Overlay"):
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)
@@ -417,30 +447,25 @@ def segment_with_choice(use_box_choice, annot_value, mode="Overlay"):
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)
@@ -451,31 +476,36 @@ def segment_with_choice(use_box_choice, annot_value, mode="Overlay"):
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):
 
397
  return palette_arr[color_idx]
398
 
399
  # ===== 分割功能 =====
400
+ # ===== 彩色 mask 可视化 =====
401
+ def colorize_mask(mask: np.ndarray, num_colors: int = 512) -> np.ndarray:
402
+ """将实例掩码转换为彩色图像,每个实例一个颜色"""
403
+ mask = mask.astype(np.int32)
404
+
405
+ def hsv_to_rgb(hh, ss, vv):
406
+ i = int(hh * 6.0)
407
+ f = hh * 6.0 - i
408
+ p = vv * (1.0 - ss)
409
+ q = vv * (1.0 - f * ss)
410
+ t = vv * (1.0 - (1.0 - f) * ss)
411
+ i = i % 6
412
+ if i == 0: r, g, b = vv, t, p
413
+ elif i == 1: r, g, b = q, vv, p
414
+ elif i == 2: r, g, b = p, vv, t
415
+ elif i == 3: r, g, b = p, q, vv
416
+ elif i == 4: r, g, b = t, p, vv
417
+ else: r, g, b = vv, p, q
418
+ return int(r*255), int(g*255), int(b*255)
419
+
420
+ palette = [(0, 0, 0)]
421
+ for k in range(1, num_colors):
422
+ hue = (k % num_colors) / float(num_colors)
423
+ palette.append(hsv_to_rgb(hue, 1.0, 0.95))
424
+
425
+ color_idx = mask % num_colors
426
+ palette_arr = np.array(palette, dtype=np.uint8)
427
+ return palette_arr[color_idx]
428
+
429
+
430
+ # ===== 推理 + 实例彩色可视化 =====
431
  def segment_with_choice(use_box_choice, annot_value, mode="Overlay"):
432
+ """分割推理 + 可视化,与原始逻辑完全对齐"""
433
  if annot_value is None or len(annot_value) < 1:
434
  print("❌ No annotation input")
435
  return None, "⚠️ 请先上传图像"
 
438
  bboxes = annot_value[1] if len(annot_value) > 1 else []
439
 
440
  print(f"🖼️ Image path: {img_path}")
 
441
  box_array = None
442
  if use_box_choice == "Yes" and bboxes:
443
  box = parse_first_bbox(bboxes)
 
447
  print(f"📦 Using box: {box_array}")
448
 
449
  try:
450
+ # 调用分割模型
451
  mask = run_seg(SEG_MODEL, img_path, box=box_array, device=SEG_DEVICE)
452
  print("📏 Mask shape:", mask.shape, "dtype:", mask.dtype, "unique:", np.unique(mask))
453
  except Exception as e:
454
  print(f"❌ Error during inference: {e}")
455
  return None, f"分割失败: {str(e)}"
456
 
457
+ # 读取原图
458
  try:
459
+ img = Image.open(img_path).convert("RGB")
460
+ img_rgb = img.resize(mask.shape[::-1], resample=Image.BILINEAR)
 
 
 
 
 
 
461
  img_np = np.array(img_rgb, dtype=np.float32)
462
  if img_np.max() > 1.5:
463
  img_np = img_np / 255.0
464
  except Exception as e:
465
+ print(f"❌ Failed to open/convert image: {e}")
466
+ return None, f"图像读取失败: {str(e)}"
467
 
468
+ # 生成实例掩码
469
  mask_np = np.array(mask)
470
  inst_mask = mask_np.astype(np.int32)
471
  unique_ids = np.unique(inst_mask)
 
476
  print("⚠️ No instance found, returning dummy red image")
477
  return Image.new("RGB", mask.shape[::-1], (255, 0, 0)), "⚠️ 未检测到细胞"
478
 
479
+ # ==== 🎨 Overlay (每个实例一个颜色 + 黄色轮廓) ====
480
  overlay = img_np.copy()
481
+ alpha = 0.75 # 增强透明度,更清晰
482
+ cmap = cm.get_cmap("tab20", num_instances + 1) # 亮色系更清楚
483
 
484
  for inst_id in np.unique(inst_mask):
485
  if inst_id == 0:
486
  continue
487
  binary_mask = (inst_mask == inst_id).astype(np.uint8)
488
+ color = np.array(cmap(inst_id / (num_instances + 1))[:3])
489
  overlay[binary_mask == 1] = (1 - alpha) * overlay[binary_mask == 1] + alpha * color
490
 
491
+ # 🟡 绘制粗黄色轮廓
492
  contours = measure.find_contours(binary_mask, 0.5)
493
  for contour in contours:
494
  contour = contour.astype(np.int32)
495
+ for dy in [-1, 0, 1]:
496
+ for dx in [-1, 0, 1]:
497
+ yy = np.clip(contour[:, 0] + dy, 0, overlay.shape[0] - 1).astype(np.int32)
498
+ xx = np.clip(contour[:, 1] + dx, 0, overlay.shape[1] - 1).astype(np.int32)
499
+ overlay[yy, xx] = [1.0, 1.0, 0.0] # 粗边缘线
500
 
501
  overlay = np.clip(overlay * 255.0, 0, 255).astype(np.uint8)
502
+ result_text = f"✅ 检测到 {num_instances} 个细胞"
503
 
 
504
  if mode == "Instance Mask Only":
505
+ # 输出纯彩色 mask
506
+ return Image.fromarray(colorize_mask(inst_mask, num_colors=512)), result_text
507
 
508
+ return Image.fromarray(overlay), result_text
509
 
510
  # ===== 计数功能 =====
511
  def count_cells_handler(image_path):