自动计算分割体体积的代码-python

import slicer
import vtk
import numpy as np

def get_first_seg_and_ref_volume():
    segs = slicer.util.getNodesByClass('vtkMRMLSegmentationNode')
    if not segs:
        raise RuntimeError("没有 Segmentation 节点。请先用 Segment Editor 做阈值分割并 Apply。")
    seg = segs[0]
    ref = seg.GetNodeReference(
        slicer.vtkMRMLSegmentationNode.GetReferenceImageGeometryReferenceRole()
    )
    if ref is None:
        vols = slicer.util.getNodesByClass('vtkMRMLScalarVolumeNode')
        if not vols:
            raise RuntimeError("没有体积节点 (ScalarVolume)。请先载入 CT/MR。")
        ref = vols[0]
    return seg, ref

def voxel_count_volume(seg, ref):
    logic = slicer.modules.segmentations.logic()
    segObj = seg.GetSegmentation()
    nSeg = segObj.GetNumberOfSegments()
    results = {}
    for i in range(nSeg):
        sid = segObj.GetNthSegmentID(i)
        name = segObj.GetSegment(sid).GetName()
        ids = vtk.vtkStringArray()
        ids.InsertNextValue(sid)
        lm = slicer.mrmlScene.AddNewNodeByClass('vtkMRMLLabelMapVolumeNode', f'_tmp_{name}_LM')
        ok = logic.ExportSegmentsToLabelmapNode(seg, ids, lm, ref)
        if not ok or lm.GetImageData() is None:
            # 段为空或导出失败
            slicer.mrmlScene.RemoveNode(lm)
            results[name] = None
            continue
        arr = slicer.util.arrayFromVolume(lm)
        count = int((arr > 0).sum())
        sx, sy, sz = lm.GetSpacing()
        v_mm3 = count * sx * sy * sz
        v_mL = v_mm3 / 1000.0
        results[name] = v_mL
        slicer.mrmlScene.RemoveNode(lm)
    return results

# 主入口
seg, ref = get_first_seg_and_ref_volume()
volumes = voxel_count_volume(seg, ref)

print(f"参考体积: {ref.GetName()}")
print("=== 各段体积(mL) ===")
for name, vol in volumes.items():
    if vol is None:
        print(f"{name}: 无法计算(导出失败或段为空)")
    else:
        print(f"{name}: {vol:.3f} mL")