3D Slicer 数据保存格式

软件版本:Slicer 5.6.2
问题描述:ROI勾画完后,怎么保存,需要保存哪些文件,重命名和保存的格式怎么选择,更后续特征提取等数据进一步处理有什么联系?

在 3D Slicer 中完成 ROI(感兴趣区域)勾画后,需要将结果保存为适合进一步特征提取和分析的数据格式。以下是详细的步骤:

1. ROI 勾画后保存

在 3D Slicer 中勾画 ROI 通常使用Segment Editor模块。完成后,可以按以下步骤保存:

  • 选择文件格式:在 Save 面板中,找到勾画好的 ROI(通常标为 .seg.nrrd.seg.mha 格式),这是用于标记和保存分割数据的格式。
  • 文件重命名:选择一个描述性名称,如 PatientID_ROI_Lesion1,以便于后续分析中的识别。

2. 保存的文件类型与用途

  • .seg.nrrd 或 .seg.mha:用于保存分割信息的主要格式,适合在 3D Slicer 和其他医学影像软件中使用。
  • .nrrd:3D Slicer 的默认格式,保存分割和原始影像数据的关联,可用于后续图像处理。
  • .nii(NIfTI 格式):对于深度学习等进一步处理,NIfTI 格式较为通用,可通过转换工具或在 3D Slicer 中转换为 .nii 格式。

3. 保存影像数据(可选)

为确保 ROI 分割与影像数据的一致性,建议同时保存原始影像数据(通常为 .nrrd.nii 格式)。这样可以在其他软件中调用影像数据并结合分割进行分析。

4. 与后续特征提取的关系

保存的分割数据可以直接加载到特征提取软件中,如 pyradiomicsSlicerRadiomics 模块。这里要确保:

  • 分辨率和原始影像一致:ROI 的分辨率和空间坐标应与原始影像一致,以确保特征计算的准确性。
  • 文件命名的一致性:建议对所有文件进行标准化命名(如包含患者 ID、扫描时间等),以便在批处理或自动分析时区分。

5. 保存格式选择和进一步处理

  • 格式选择:如果计划在 SlicerRadiomics 中提取特征,建议保存为 .nrrd.mha 格式,这些格式与 Slicer 更兼容。
  • 命名和管理:重命名时考虑数据分析的批处理需求,建议使用标准化命名规范(如 PatientID_ScanDate_ROI),便于数据匹配和自动化处理。
  • 后续处理联系:保存的 ROI 分割文件将作为特征提取的输入数据,确保文件格式和分辨率的一致性是进行准确特征提取的关键。

通过这些步骤和文件管理,可以确保在后续特征提取和数据处理过程中数据的一致性和可追溯性,提高分析效率和准确性。

1 个赞

1730167878898
image

每一个患者我需要勾画多个ROI,统一以每一个患者的名字及入组序号命名一个文件夹,同一个患者的ROI勾画文件都保存到对应的患者名下且以入组序号命名,如两张图所示。也就是说同一批数据,不同患者的勾画文件名并非完全相同(因为入组序号不同),后面可以批量特征提取不?

批量提取特征需要编程,一个目录下一个数据文件Volume和一个分割文件,可以参考下面代码:


在 3D Slicer 中安装 pyradiomics

  1. 打开 3D Slicer 软件。
  2. 在 3D Slicer 主界面的底部,找到 Python Interactor 窗口。如果未显示,可以从 View -> Python Interactor 菜单中打开。
  3. Python Interactor 中,输入以下命令来安装 pyradiomics 库:
slicer.util.pip_install("pyradiomics")
  1. 等待安装完成后,再次运行代码。

其他依赖库安装

如果还没有安装 SimpleITKnumpy,可以在 Python Interactor 中运行以下命令一起安装:

slicer.util.pip_install("SimpleITK numpy")

检查安装成功

安装完成后,您可以在 Python Interactor 中输入以下命令来验证是否安装成功:

import radiomics
import SimpleITK
import numpy

如果没有错误提示,说明安装成功,可以继续执行特征提取代码。

注意事项

  • 在 3D Slicer 的 Python 环境中安装包时,请确保网络连接正常。
  • pip_install 命令只能在 3D Slicer 的 Python 环境中运行,不能在系统的独立 Python 环境中执行。

完成这些步骤后,您应该可以顺利运行特征提取代码了。


自动按照路径提取特征的代码:

import os
import radiomics
import logging
from radiomics import featureextractor
import SimpleITK as sitk
import numpy as np
import csv

# 设置日志级别为ERROR,避免输出优化提示
radiomics.logger.setLevel(logging.ERROR)

# 定义影像和分割文件目录
directory = "O:/OneDrive/桌面/test/"

# 自动搜索影像和分割文件
files = [f for f in os.listdir(directory) if f.endswith('.nrrd')]
image_file = None
seg_file = None

for f in files:
    if "seg" in f.lower():  # 识别分割文件
        seg_file = f
    else:  # 默认其他文件为影像文件
        image_file = f

# 确保找到影像和分割文件
if not image_file or not seg_file:
    raise ValueError("请确保目录中包含影像文件和以'seg.nrrd'结尾的分割文件。")

# 设置影像和分割文件路径
image_path = os.path.join(directory, image_file)
mask_path = os.path.join(directory, seg_file)

# 初始化特征提取器并配置参数
extractor = featureextractor.RadiomicsFeatureExtractor()
extractor.disableAllFeatures()
extractor.enableFeatureClassByName('firstorder')  # 启用firstorder特征
extractor.enableFeatureClassByName('glcm')        # 启用glcm特征
extractor.enableFeatureClassByName('shape')       # 启用3D shape特征

# 设置提取器的参数
extractor.settings['force2D'] = False
extractor.settings['symmetricalGLCM'] = True

# 输出CSV文件路径
output_csv_path = os.path.join(directory, "radiomics_features.csv")

# 加载分割文件并获取标签名称
segmentation = sitk.ReadImage(mask_path)
label_stats = sitk.LabelStatisticsImageFilter()
label_stats.Execute(segmentation, segmentation)

# 获取标签名称和ID的映射
label_names = {int(label): f"Segmentation_segment_{int(label)}" for label in label_stats.GetLabels() if label != 0}

# 提取特征并构建数据表格
feature_table = []

# 针对每个标签提取特征
for label_value, label_name in label_names.items():
    # 创建单个标签的掩膜
    label_mask = sitk.BinaryThreshold(segmentation, lowerThreshold=label_value, upperThreshold=label_value, insideValue=1, outsideValue=0)
    
    try:
        features = extractor.execute(image_path, label_mask)
        print(f"{label_name} 特征提取成功!")

        # 将每个标签的特征结果添加到表格
        for key, value in features.items():
            feature_type, feature_name = key.split('_', 1)
            feature_table.append({
                "Image type": "original",
                "Feature Class": feature_type,
                "Feature Name": feature_name,
                label_name: value
            })

    except Exception as e:
        print(f"{label_name} 特征提取时发生错误: {e}")

# 获取所有列的标签名称
all_labels = list(label_names.values())

# 汇总同一特征名的多标签列数据
output_data = {}
for row in feature_table:
    feature_key = (row["Image type"], row["Feature Class"], row["Feature Name"])
    if feature_key not in output_data:
        output_data[feature_key] = {label: "" for label in all_labels}  # 初始化标签列为空
        output_data[feature_key].update({
            "Image type": row["Image type"],
            "Feature Class": row["Feature Class"],
            "Feature Name": row["Feature Name"]
        })
    label_column_name = list(row.keys())[-1]
    output_data[feature_key][label_column_name] = row[label_column_name]

# 写入CSV文件,列出每个特征的名称及对应标签值
with open(output_csv_path, "w", newline='') as f:
    writer = csv.writer(f)
    header = ["Image type", "Feature Class", "Feature Name"] + all_labels  # 表头:特征名称 + 标签名称
    writer.writerow(header)

    for feature_key, label_values in output_data.items():
        row = [label_values["Image type"], label_values["Feature Class"], label_values["Feature Name"]]
        row += [label_values.get(label, "N/A") for label in all_labels]
        writer.writerow(row)

print(f"特征提取结果已保存至 {output_csv_path}")