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

从ROI的Z轴堆栈生成高质量3D网格的方法及参数优化问询

问题:从3D ROI标签堆栈生成保留凹面特征的封闭表面网格

我有一组存储为TIFF文件的3D ROI标签堆栈,每个ROI代表单个细胞。我希望生成适用于下游形状分析的表面网格(使用trimesh)。

我尝试过Marching Cubes方法:

from skimage import measure
import trimesh
import numpy as np

mask = labels == lab_id  # binary mask for one ROI
verts, faces, normals, values = measure.marching_cubes(mask.astype(np.float32), level=0.5)
mesh = trimesh.Trimesh(vertices=verts, faces=faces)

但生成的部分网格存在表面缺失、孔洞或多个不连通的“块”;同时尝试的Open3D Poisson表面重建也未能正确捕捉形状。

我还尝试过以下方法:

import trimesh
coords = np.argwhere(mask)  # N x 3 points

pc = trimesh.points.PointCloud(coords)

mesh = pc.convex_hull

但凸包会丢失所有凹面特征,导致每个细胞形态大致相同。

请问从3D ROI堆栈生成美观平滑的封闭轮廓网格,同时保留凹面特征、避免块或表面缺失的推荐方法是什么?我尝试过的两种方法中是否有特定参数可提升网格生成的可靠性?


解决方案

一、优化Marching Cubes参数与预处理

Marching Cubes出现孔洞、表面缺失的核心原因通常是mask存在不连续、噪点,或参数匹配度低,可通过以下步骤修复:

  1. 预处理二进制Mask
    先清理mask的瑕疵,避免后续网格生成受干扰:

    from scipy.ndimage import binary_closing, binary_fill_holes, label
    
    # 用3x3x3结构元素做闭运算,填补小缝隙
    mask_clean = binary_closing(mask, structure=np.ones((3,3,3)))
    # 填充内部孔洞
    mask_clean = binary_fill_holes(mask_clean)
    # 只保留最大的连通分量,去除噪点块
    labeled_mask, num_components = label(mask_clean)
    if num_components > 1:
        component_sizes = np.bincount(labeled_mask.ravel())
        largest_component = component_sizes.argmax()
        mask_clean = labeled_mask == largest_component
    
  2. 调整Marching Cubes关键参数

    • 设置spacing:如果3D ROI各轴分辨率不一致(比如Z轴分辨率低于XY轴),传入对应比例的spacing,保证网格比例准确,减少扭曲导致的孔洞:
      # 示例:Z轴分辨率2μm,XY轴1μm
      verts, faces, normals, values = measure.marching_cubes(
          mask_clean.astype(np.float32),
          level=0.5,
          spacing=(2.0, 1.0, 1.0)
      )
      
    • 启用allow_degenerate=False:过滤面积为0的退化三角形,减少网格异常结构。
  3. 网格后处理修复
    生成初始网格后,用trimesh自带工具修复瑕疵:

    # 移除孤立顶点和退化面
    mesh.remove_unreferenced_vertices()
    mesh.remove_degenerate_faces()
    # 填充简单孔洞
    mesh.fill_holes()
    # 合并重复顶点,消除冗余结构
    mesh.merge_vertices()
    

二、改进点云驱动的表面重建(替代凸包)

凸包会丢失凹面,改用带法线的点云做泊松重建可保留细节,关键是给点云添加准确法线:

  1. 生成带法线的表面点云
    从清理后的mask提取表面点,并计算法线:

    from skimage import measure
    
    # 提取mask表面点
    surface_points = measure.find_contours(mask_clean, level=0.5)[0]
    # 基于邻域点估计法线,k值根据点密度调整
    pc = trimesh.points.PointCloud(surface_points)
    pc.normals = trimesh.points.normals(pc.vertices, k=10)
    
  2. 优化Open3D泊松重建参数
    调整参数解决之前重建失败的问题:

    import open3d as o3d
    
    # 转换为Open3D点云格式
    o3d_pc = o3d.geometry.PointCloud()
    o3d_pc.points = o3d.utility.Vector3dVector(pc.vertices)
    o3d_pc.normals = o3d.utility.Vector3dVector(pc.normals)
    # 泊松重建:depth控制分辨率,scale避免表面收缩
    mesh, densities = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(
        o3d_pc,
        depth=8,  # 数值越大网格越精细,按需调整
        scale=1.1
    )
    # 过滤低密度噪点面
    vertices_to_remove = densities < np.quantile(densities, 0.01)
    mesh.remove_vertices_by_mask(vertices_to_remove)
    # 转换回trimesh格式
    trimesh_mesh = trimesh.Trimesh(vertices=np.asarray(mesh.vertices), faces=np.asarray(mesh.triangles))
    

三、推荐工作流

兼顾精度与可靠性的完整流程:

  1. 预处理mask(闭运算→填充孔洞→保留最大连通分量)
  2. 带spacing参数的Marching Cubes生成初始网格
  3. trimesh工具修复网格(去冗余→填孔洞)
  4. 可选轻度平滑,避免过度丢失细节:
    mesh.smooth_laplacian(iterations=5, lamb=0.5)
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 01:27:16