4. 肿瘤区域分割与特征提取工程
在影像组学建模中,分割与特征提取是决定后续生存分析上限的关键环节。分割定义了“从哪里取数”,特征提取器定义了“取什么数”,批量流程则决定了“能否稳定地重复取数”。三者中任何一环失控,都会让后续的统计模型建立在不可复现的输入之上。本节围绕工程实现展开,重点说明工具选择、可重复分割策略、提取器配置以及批量处理流程的具体做法。
一、分割工具的选择与适用边界
肿瘤区域分割按自动化程度可分为手工、半自动与全自动三类。手工分割以 ITK-SNAP、3D Slicer 为代表,适合边界模糊、需要专家经验判断的病例,但耗时且一致性依赖操作者。半自动工具如 3D Slicer 中的 GrowCut、区域生长、水平集,以及 MITK 的交互式分割,能在少量种子点或初始轮廓基础上快速收敛,适合批量处理中“机器初筛 + 人工修正”的模式。全自动方法以 nnU-Net、U-Net 变体为主,适合数据量充足、目标器官或病灶形态相对稳定的场景,其优势是速度快、可完全复现,但需要独立验证集评估 Dice 与 HD95。
工具选择的核心不是“越自动越好”,而是与数据规模、标注资源、目标结构复杂度匹配。对于多中心、多扫描仪数据,建议优先采用全自动或半自动方案,并在流程中保留人工复核环节,避免系统性偏差被批量放大。
二、可重复分割策略
可重复分割的核心是控制变异来源。变异主要来自三方面:操作者内变异、操作者间变异、以及扫描参数与重建差异。工程上可采取以下策略:
- 固定分割协议:明确窗宽窗位、层厚、插值方式、是否包含瘤周区域、是否包含坏死区,并写入 SOP。
- 双人独立分割 + 仲裁:由两名有经验医师独立勾画,计算 Dice 一致性;对差异较大的病例由第三名高年资医师仲裁。
- 重复分割评估:随机抽取 10%~15% 病例进行二次分割,计算 ICC(组内相关系数)与 Dice,作为流程稳定性的量化指标。
- 版本化管理:每次分割结果保存为带版本号的掩膜文件,记录工具版本、操作者、日期与参数,便于回溯。
示例:某研究对 120 例肺癌 CT 进行分割,随机抽取 18 例由同一医师间隔两周重复勾画,得到平均 Dice 为 0.91,ICC 为 0.89;另抽取 15 例由两位医师独立勾画,平均 Dice 为 0.86。该结果说明流程整体稳定,但医师间差异仍需通过仲裁与共识训练进一步压缩。
三、特征提取器配置
特征提取器决定了从分割区域中能获得哪些定量描述。常用工具包括 PyRadiomics、IBEX、MaZda 与 CERR。以 PyRadiomics 为例,其配置通过 YAML 文件控制,关键参数包括:
imageType:
Original: {}
Wavelet: {}
LoG:
sigma: [1.0, 2.0, 3.0]
featureClass:
firstorder:
shape:
glcm:
glrlm:
glszm:
gldm:
ngtdm:
setting:
binWidth: 25
resampledPixelSpacing: [1, 1, 1]
interpolator: 'sitkBSpline'
normalize: true
force2D: false
其中 binWidth 影响灰度离散化粒度,resampledPixelSpacing 统一体素尺寸,normalize 控制强度归一化。若不做重采样,不同层厚与像素间距会直接改变纹理矩阵,导致特征不可比。建议在提取前统一重采样至 1×1×1 mm,并固定 binWidth,例如 25 HU。对于 CT,通常保留 Original、Wavelet、LoG 三类图像类型;对于 MRI,需额外考虑偏置场校正与强度归一化。
四、批量处理流程
批量处理的目标是“一次配置、全量执行、结果可追溯”。典型流程如下:
- 整理数据目录:图像与掩膜按病例 ID 配对,命名规则统一,例如
case_001_img.nii.gz与case_001_mask.nii.gz。 - 读取病例清单:生成 CSV,包含病例 ID、图像路径、掩膜路径、分组标签(如训练/验证)。
- 逐例提取:调用 PyRadiomics,加载图像与掩膜,执行重采样、归一化与特征计算。
- 结果汇总:将每例特征写入一行,列名为特征名,行索引为病例 ID,输出为 CSV。
- 质量检查:统计缺失值、常数特征、异常值,并记录提取日志。
以下为批量提取的核心代码骨架:
import pandas as pd
from radiomics import featureextractor
extractor = featureextractor.RadiomicsFeatureExtractor('params.yaml')
cases = pd.read_csv('cases.csv')
rows = []
for _, r in cases.iterrows():
result = extractor.execute(r['image'], r['mask'])
row = {'case_id': r['case_id']}
row.update({k: v for k, v in result.items() if not k.startswith('diagnostics')})
rows.append(row)
pd.DataFrame(rows).to_csv('features.csv', index=False)
执行后应检查 features.csv 的行数是否与病例数一致,列数是否与预期特征数一致。若某例提取失败,日志中会记录原因,常见问题包括掩膜为空、图像与掩膜尺寸不匹配、重采样后掩膜消失等。
五、结果核对与常见问题
批量提取完成后,建议先做三项核对:第一,检查 features.csv 的行数是否等于病例数,若少于病例数,说明有病例提取失败;第二,检查是否存在全为 NaN 或全为常数的列,这类特征在后续建模中无区分度,应剔除;第三,随机抽取 2~3 例,用单例脚本重新提取并与批量结果比对,确认流程一致。
常见问题包括:掩膜与图像方向不一致导致形状特征异常;重采样后小病灶掩膜消失,需调整插值方式或保留原始间距;binWidth 设置过小导致纹理矩阵稀疏,过大则丢失细节。对于 CT,binWidth 常取 25 HU;对于 MRI,因强度无绝对单位,建议先归一化再离散化。
分割与特征提取不是一次性任务,而是需要版本化、可追溯的工程环节。把工具选择、重复性评估、提取器参数与批量流程固定下来,后续的生存分析才有稳定的输入基础。建议在项目初期就建立分割 SOP、参数快照与特征矩阵核对清单,避免在建模阶段才发现输入不可复现。