3. OCT数据读取与元数据解析
OCT设备输出的原始数据并不总是“一张图”那么简单。一次视网膜OCT体扫描通常包含数百张B-scan,每张B-scan又由上千个A-scan组成,而每个A-scan的像素值背后还绑定着物理尺度、扫描方向、患者信息和设备参数。如果只把文件当作普通图像读取,后续的分层测量、厚度定量和跨设备对比都会失去物理意义。因此,数据读取与元数据解析是OCT工程分析的第一道关键工序。
三种常见数据形态
临床上最常见的是DICOM格式。OCT的DICOM通常使用多帧增强型或旧式多帧封装,像素数据存放在Pixel Data中,而物理信息分散在多个标签里:(0028,0030) PixelSpacing给出像素间距,(0018,0088) SpacingBetweenSlices或私有标签给出B-scan间距,(0020,0032) ImagePositionPatient与(0020,0037) ImageOrientationPatient描述每帧的空间位置和方向。需要注意的是,OCT的轴向与横向像素间距往往不同,PixelSpacing通常只描述横向,轴向分辨率需从(0018,0050) SliceThickness或厂商私有标签中获取。
厂商私有格式则更复杂。不同设备厂商会使用自有容器,例如把体数据存为二进制流加一个文本头,头里记录扫描模式、A-scan数量、B-scan数量、参考臂位置、焦点位置等。这类格式没有统一标准,必须依赖厂商文档或逆向解析。公开数据集格式相对友好,常见的有PNG/TIFF图像序列加CSV元数据、HDF5、或MAT文件。它们通常已经完成脱敏,但像素间距、扫描密度等字段可能被简化或缺失,需要从数据集说明中补齐。
像素间距与扫描密度的解析
像素间距决定了“一个像素代表多少微米”。在DICOM中,横向像素间距通常来自PixelSpacing,它是一个二元组,分别对应行方向和列方向。对于OCT,行方向往往对应A-scan之间的横向距离,列方向对应深度方向。但不同厂商的约定可能相反,必须结合ImageOrientationPatient和实际扫描几何来确认。轴向像素间距有时直接等于SliceThickness,有时需要从RealWorldValueMapping或私有标签中读取。
扫描密度描述B-scan之间的物理间隔。在体扫描中,如果B-scan间距为120 μm,而横向像素间距为20 μm,那么相邻B-scan之间就跳过了6个A-scan的位置。这个参数直接影响三维重建的层间插值和厚度测量的采样充分性。解析时可以从SpacingBetweenSlices、SliceLocation序列或私有头中的“scan density”字段获取。如果缺失,可以用相邻帧的ImagePositionPatient差值计算。
方向信息的处理
方向信息决定了图像在解剖坐标系中的朝向。DICOM的ImageOrientationPatient给出两个三维方向余弦,分别表示图像行方向和列方向在患者坐标系中的指向。对于OCT,还需要关注扫描方向是水平、垂直还是环形。方向解析错误会导致左右眼混淆、上下颠倒或厚度测量方向偏差。建议在读取后统一转换为“横向为x、深度为z、B-scan序列为y”的右手坐标系,并记录转换矩阵,保证后续所有测量在同一参照系下进行。
患者信息脱敏
脱敏不是简单删除姓名。DICOM中与患者身份相关的标签包括PatientName、PatientID、PatientBirthDate、PatientSex、StudyDate、InstitutionName等。工程上通常采用“替换+偏移”策略:用哈希值或顺序编号替换患者ID,保留眼别和年龄区间用于分组分析,将日期整体偏移一个固定天数以保留时间间隔但隐藏真实日期。脱敏应在数据进入分析流水线之前完成,并保留一份脱敏映射表供必要时回溯,映射表本身需加密存储。
批量数据组织
当处理数百例OCT数据时,目录结构直接影响检索效率。推荐按“数据集/患者匿名ID/眼别/扫描日期偏移/扫描协议”分层,每个体数据保存为独立文件,同时生成一个索引文件记录关键元数据。索引文件可以用JSON或CSV,字段包括:匿名ID、眼别、像素间距、B-scan数量、每帧A-scan数量、扫描密度、方向矩阵、设备型号、文件路径和校验和。这样在批量分析时,只需读取索引即可完成筛选和分组,不必反复打开大体积数据文件。
一个可参考的索引字段示例
| 字段 | 示例值 | 来源/说明 |
|---|---|---|
| anon_id | P0007 | 脱敏后顺序编号 |
| eye | OD | 右眼,来自Laterality标签 |
| pixel_spacing_x_um | 11.7 | 横向像素间距,示例值 |
| pixel_spacing_z_um | 3.9 | 轴向像素间距,示例值 |
| bscan_count | 128 | B-scan帧数 |
| ascan_count | 512 | 每帧A-scan数 |
| bscan_spacing_um | 120.0 | B-scan间距,示例值 |
| orientation | [1,0,0,0,1,0] | 方向余弦,示例值 |
| device | VendorA ModelX | 设备型号 |
| file_path | data/P0007/OD/20240101/volume.dcm | 相对路径 |
| checksum | sha256:… | 文件完整性校验 |
完成上述解析后,OCT数据才真正具备“可测量”的属性。像素间距和扫描密度把图像像素映射到物理空间,方向信息保证解剖朝向一致,脱敏和批量组织则让数据可以安全、高效地进入后续的分层与定量分析流程。实际工程中,建议把解析层封装为独立模块,对DICOM、私有格式和公开数据集分别实现适配器,向上层输出统一的体数据对象和元数据字典,这样更换数据来源时只需替换适配器,而不影响测量算法。