You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何准确计数重叠的细胞Filopodia分割掩码中的丝状体

解决Filopodia二值掩码计数难题的方案

针对丝状体重叠(含结状/环状结构)导致的计数不准确问题,可从拓扑分析优化、预处理分割、深度学习实例分割三个方向解决,以下是具体实现:

一、改进拓扑分析逻辑(修复原代码缺陷)

原代码仅依赖端点计数,无法处理环状结构,需结合分支点、孔洞数修正计数逻辑:

1. 补充分支点检测函数

import numpy as np
from skimage.morphology import skeletonize
from skimage import measure
from collections import Counter

def find_endpoints(img):
    (rows, cols) = np.nonzero(img)
    skel_coords = []
    for (r, c) in zip(rows, cols):
        col_neigh, row_neigh = np.meshgrid([c-1, c, c+1], [r-1, r, r+1])
        col_neigh = col_neigh.astype(int)
        row_neigh = row_neigh.astype(int)
        pix_neighbourhood = img[row_neigh, col_neigh].ravel() != 0
        # 中心像素非零,邻居仅1个非零 → 端点
        if np.sum(pix_neighbourhood) == 2:
            skel_coords.append((r, c))
    return len(skel_coords)

def find_branch_points(img):
    (rows, cols) = np.nonzero(img)
    branch_coords = []
    for (r, c) in zip(rows, cols):
        col_neigh, row_neigh = np.meshgrid([c-1, c, c+1], [r-1, r, r+1])
        col_neigh = col_neigh.astype(int)
        row_neigh = row_neigh.astype(int)
        pix_neighbourhood = img[row_neigh, col_neigh].ravel() != 0
        # 中心像素非零,邻居≥3个非零 → 分支点
        if np.sum(pix_neighbourhood) >= 4:
            branch_coords.append((r, c))
    return len(branch_coords)

2. 结合连通分支、孔洞数的计数函数

def count_filopodia(mask):
    skel = skeletonize(mask)
    labeled_skel = measure.label(skel, connectivity=2)
    props = measure.regionprops(labeled_skel)
    
    total_count = 0
    
    for prop in props:
        region_skel = (labeled_skel == prop.label)
        n_end = find_endpoints(region_skel)
        n_branch = find_branch_points(region_skel)
        # 计算当前连通分支的孔洞数:欧拉数=1-孔洞数(单个分支)
        n_holes = 1 - prop.euler_number
        
        if n_holes == 0:
            # 树状结构:端点数+分支点数-1(每个端点对应一条独立丝状体,分支点补充分叉)
            count = n_end + n_branch - 1
        else:
            # 环状结构:树状部分计数 + 孔洞对应的丝状体(环至少对应1条)
            tree_count = max(n_end + n_branch - 1, 0)
            count = tree_count + n_holes
        
        # 纯环结构(无端点/分支点)至少计为1条
        total_count += max(count, 1)
    
    return total_count

二、预处理:用分水岭分割减少重叠干扰

对于严重重叠的掩码,先通过距离变换+分水岭分割拆分重叠结构,再计数:

from skimage.segmentation import watershed
from skimage.feature import peak_local_max
from skimage.morphology import distance_transform_edt

def preprocess_overlapped_mask(mask):
    # 距离变换:计算每个前景像素到背景的距离
    dist = distance_transform_edt(mask)
    # 提取局部极大值作为分割种子
    local_max = peak_local_max(dist, indices=False, footprint=np.ones((3,3)), labels=mask)
    markers = measure.label(local_max)
    # 分水岭分割拆分重叠区域
    segmented_mask = watershed(-dist, markers, mask=mask)
    return segmented_mask

# 使用方式
segmented = preprocess_overlapped_mask(original_mask)
total = count_filopodia(segmented)

三、深度学习实例分割(最可靠的复杂场景方案)

针对极端重叠的场景,用Cellpose、Mask R-CNN等模型做实例分割,直接计数独立的Filopodia实例:

Cellpose实现示例

from cellpose import models, io

# 加载预训练模型(cyto模型适用于细胞结构,也可自定义训练)
model = models.Cellpose(model_type='cyto')
# 读取二值掩码或原始图像
img = io.imread('filopodia_mask.png')
# 执行实例分割
masks, _, _, _ = model.eval(img, diameter=None, channels=[0,0])
# 计数(减去背景类)
filopodia_count = len(np.unique(masks)) - 1

内容的提问来源于stack exchange,提问作者rikyeah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:09:52