Spaces:
Paused
Paused
Update app.py
Browse files
app.py
CHANGED
|
@@ -398,7 +398,7 @@ 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 |
-
"""分割处理函数:
|
| 402 |
if annot_value is None or len(annot_value) < 1:
|
| 403 |
return None, "⚠️ 请先上传图像"
|
| 404 |
|
|
@@ -419,62 +419,41 @@ def segment_with_choice(use_box_choice, annot_value, mode="Overlay"):
|
|
| 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"
|
| 423 |
except Exception as e:
|
| 424 |
print(f"❌ Segmentation error: {e}")
|
| 425 |
return None, f"分割失败: {str(e)}"
|
| 426 |
|
| 427 |
try:
|
| 428 |
-
|
| 429 |
-
|
|
|
|
|
|
|
|
|
|
| 430 |
except Exception as e:
|
| 431 |
-
print(f"❌
|
| 432 |
return None, f"图像读取失败: {str(e)}"
|
| 433 |
|
| 434 |
-
|
| 435 |
-
|
| 436 |
-
|
| 437 |
-
|
| 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_np = np.array(mask)
|
| 444 |
-
inst_mask = mask_np.astype(np.int32)
|
| 445 |
-
unique_ids = np.unique(inst_mask)
|
| 446 |
-
num_instances = len(unique_ids[unique_ids != 0])
|
| 447 |
-
print(f"✅ Instance IDs found: {unique_ids}, Total instances: {num_instances}")
|
| 448 |
-
|
| 449 |
-
if num_instances == 0:
|
| 450 |
-
return Image.new("RGB", mask.shape[::-1], (255, 0, 0)), "⚠️ 未检测到细胞"
|
| 451 |
-
|
| 452 |
-
# ==== Color Overlay (每个实例一个颜色 + 黄色轮廓) ====
|
| 453 |
-
overlay = img_np.copy()
|
| 454 |
alpha = 0.5
|
| 455 |
-
cmap = cm.get_cmap("nipy_spectral", num_instances + 1)
|
| 456 |
|
| 457 |
-
for inst_id in
|
| 458 |
-
if inst_id == 0:
|
| 459 |
continue
|
| 460 |
-
|
| 461 |
-
|
| 462 |
-
overlay[binary_mask == 1] = (1 - alpha) * overlay[binary_mask == 1] + alpha * color
|
| 463 |
-
|
| 464 |
-
# 轮廓绘制为黄色
|
| 465 |
-
contours = measure.find_contours(binary_mask, 0.5)
|
| 466 |
-
for contour in contours:
|
| 467 |
-
contour = contour.astype(np.int32)
|
| 468 |
-
overlay[contour[:, 0], contour[:, 1]] = [1.0, 1.0, 0.0]
|
| 469 |
|
| 470 |
overlay = np.clip(overlay * 255.0, 0, 255).astype(np.uint8)
|
|
|
|
| 471 |
|
|
|
|
|
|
|
| 472 |
result_text = f"✅ 检测到 {num_instances} 个细胞"
|
| 473 |
|
| 474 |
-
|
| 475 |
-
return Image.fromarray(colorize_mask(inst_mask, num_colors=512)), result_text
|
| 476 |
-
|
| 477 |
-
return Image.fromarray(overlay), result_text
|
| 478 |
|
| 479 |
# ===== 计数功能 =====
|
| 480 |
def count_cells_handler(image_path):
|
|
|
|
| 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 |
|
|
|
|
| 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):
|