2. 3D医学影像数据获取与格式解析

在3D医学影像项目中,拿到数据只是起点,真正决定后续检测与分类能否复现的,是对数据格式、几何信息和灰度语义的准确解析。本节围绕DICOM标准、NIfTI格式、体素间距、方向矩阵、窗宽窗位与元数据读取六个核心概念展开,目标是让读者能够独立完成从原始序列到可计算体数据的转换,并理解每一步中哪些参数会影响最终结果。

一、DICOM:临床影像的事实标准

DICOM(Digital Imaging and Communications in Medicine)是医院PACS系统中影像存储与传输的标准。一个CT或MR检查通常由多个切片文件组成,每个文件包含两部分:像素数据(Pixel Data)和大量元数据标签(Tag)。标签以(group, element)形式编号,例如(0028,0010)表示Rows,(0028,0030)表示Pixel Spacing,(0020,0032)表示Image Position Patient,(0020,0037)表示Image Orientation Patient。

解析DICOM时,最容易被忽略的是像素值的物理含义。CT的像素值通常是HU(Hounsfield Unit)的线性变换结果,需要结合Rescale Slope (0028,1053)和Rescale Intercept (0028,1052)还原:HU = 像素值 × Slope + Intercept。例如某CT文件Slope=1、Intercept=-1024,像素值存储为0~4095,则还原后空气约为-1000 HU,水约为0 HU,骨组织可达+1000 HU以上。MR没有统一的HU体系,像素值只有相对意义,通常不做绝对物理量还原。

此外,DICOM序列的切片顺序不能依赖文件名排序。正确做法是读取每层的Image Position Patient,沿切片法向量方向投影后排序。若直接按文件名排序,遇到命名不规范的序列会导致体数据上下颠倒或层间错位。

二、NIfTI:面向计算与建模的体数据格式

NIfTI(Neuroimaging Informatics Technology Initiative)是科研与深度学习流程中更常用的格式,通常以.nii或.nii.gz保存。与DICOM“一层一文件”不同,NIfTI将整个3D体数据存放在单个文件中,并附带一个仿射矩阵(affine),描述体素索引到世界坐标的映射关系。NIfTI头中的qform和sform分别记录两种可能的空间变换,工程中一般优先使用sform。

从DICOM转NIfTI时,需要完成三件事:按空间位置重排切片、将像素值转换为HU或统一量纲、根据Image Position和Image Orientation构造仿射矩阵。常用工具包括dcm2niix、SimpleITK和pydicom+ nibabel组合。转换后应检查体数据尺寸、体素间距和方向是否与原始序列一致,避免出现轴顺序错误。

三、体素间距与方向矩阵

体素间距(spacing)是体素在三个物理方向上的实际尺寸,单位通常为毫米。CT常见层内间距为0.6~0.8 mm,层间距为1.0~1.5 mm,因此体素往往不是各向同性的。若直接按体素索引计算距离或做3D卷积,层方向会被压缩或拉伸。工程上通常先重采样到各向同性间距(如1 mm×1 mm×1 mm),再进行检测或分类。

方向矩阵描述体素轴与患者解剖轴(LPS:Left-Posterior-Superior)之间的对应关系。一个3×3方向矩阵的列向量分别表示体素i、j、k轴在世界坐标中的方向。常见情况是i轴指向患者左侧、j轴指向后方、k轴指向头侧。若方向矩阵出现负号,说明该轴方向与标准解剖方向相反。方向处理错误会导致左右肺、左右肾等对称结构被混淆,是医学影像模型最常见的隐性错误之一。

DICOM序列 → 体数据 → NIfTI 的几何与灰度解析链 DICOM 切片序列 Slice 001 IPP=(x,y,z) Slice 002 IPP=(x,y,z+Δ) Slice 003 IPP=(x,y,z+2Δ) PixelSpacing / IOP / Slope / Intercept 按 IPP 沿法向量排序,而非文件名 解析 3D 体数据 尺寸: 512 × 512 × 120 Spacing: 0.7 × 0.7 × 1.5 mm HU = 像素 × Slope + Intercept 空气 ≈ -1000 HU 水 ≈ 0 HU 骨 ≈ +1000 HU 重采样 NIfTI 体数据 (.nii.gz) 各向同性: 1.0 × 1.0 × 1.0 mm 仿射矩阵 sform (4×4) qform 备用 方向矩阵列向量 = 体素轴方向 i→左, j→后, k→头 (LPS) 负号 = 轴反向,需核对 方向矩阵与体素轴对应 i 轴 → 患者左 (L) j 轴 → 患者后 (P) k 轴 → 患者头 (S) 若 i 轴为负:左右翻转风险 若 k 轴为负:头脚颠倒风险 对称器官(肺、肾)最易受影响 窗宽窗位 (WW/WL) 映射 显示灰度 = f(HU, WW, WL) 肺窗: WW=1500, WL=-600 纵隔窗: WW=400, WL=40 骨窗: WW=2000, WL=400 窗宽窗位只影响可视化,不改变 HU 模型输入应使用 HU 或归一化值

四、窗宽窗位:灰度语义的显示控制

窗宽(Window Width, WW)和窗位(Window Level, WL)决定HU值如何映射到显示灰度。计算公式为:显示值 = (HU - (WL - WW/2)) / WW × 255,并截断到0~255。以肺窗WW=1500、WL=-600为例,映射区间为[-1350, 150],肺实质和气道细节清晰;纵隔窗WW=400、WL=40映射区间为[-160, 240],适合观察软组织与血管;骨窗WW=2000、WL=400则突出高密度骨结构。

需要特别强调:窗宽窗位是显示参数,不改变原始HU值。在训练检测或分类模型时,若直接使用窗变换后的8位图像,会丢失HU的绝对物理信息。更稳妥的做法是保留HU或做全局归一化,把窗变换仅用于可视化与人工标注。

五、元数据读取与工程检查

元数据读取应至少覆盖以下字段:患者与检查标识(PatientID、StudyInstanceUID、SeriesInstanceUID)、几何信息(PixelSpacing、SliceThickness、ImagePositionPatient、ImageOrientationPatient)、灰度信息(RescaleSlope、RescaleIntercept、WindowCenter、WindowWidth)以及采集参数(KVP、ConvolutionKernel)。这些字段既用于数据清洗,也用于排查“同一患者多次检查混入”“层间距不一致”“方向翻转”等问题。

一个可执行的检查流程如下:

  1. 读取序列全部DICOM文件,提取ImagePositionPatient和ImageOrientationPatient。
  2. 计算切片法向量,将所有切片沿法向量投影并排序,检查是否存在重复位置或缺失层。
  3. 用PixelSpacing和相邻层投影差计算体素间距,确认三轴间距是否一致。
  4. 用RescaleSlope和RescaleIntercept将像素值转为HU,统计HU直方图,确认空气峰约在-1000、水峰约在0附近。
  5. 构造仿射矩阵并写入NIfTI,用nibabel或SimpleITK回读,核对affine、shape和spacing。
  6. 用肺窗、纵隔窗、骨窗分别渲染一层,目视确认左右、头脚方向正确。
若HU直方图空气峰明显偏离-1000,优先检查RescaleIntercept是否被错误置零;若左右结构颠倒,优先检查方向矩阵第一列符号。

六、从格式解析到可训练数据

完成上述解析后,得到的应是一个形状为(D, H, W)、带有正确spacing和affine的浮点体数据。后续的3D检测或分类网络可以直接在该体数据上采样patch,或先重采样到统一间距再送入网络。格式解析阶段引入的几何错误往往不会在训练损失上立刻暴露,却会在推理阶段表现为左右混淆、层间错位或尺度失真,因此建议把本节的方向、间距、HU检查固化为数据入库前的标准步骤。

实际工程中,DICOM与NIfTI的转换不是一次性的,而是需要随数据批次持续执行。建议为每个序列保存一份解析日志,记录原始文件数、排序后层数、spacing、affine、HU范围以及方向检查结果。这样在模型效果异常时,可以快速回溯到数据几何层面,而不是盲目调整网络结构。