Caoyufu
(曹玉福)
1
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")