测量、DICOM SR/GSPS 与 QA:从屏幕标注走向标准对象
解释 DicomVision 中测量标注、DICOM SR、GSPS、MTF 和水模 QA 的关系与实现边界。
问题引入
测量标注看起来只是画线、画角度、画 ROI,但医学影像里真正重要的是这条线代表什么。屏幕上 120 像素的线,只有结合图像坐标、PixelSpacing 和视口变换,才能变成多少毫米。一个 ROI 的均值和标准差,也必须回到原始像素值域,而不是在屏幕截图上统计灰度。
DicomVision 早期的测量可以理解成本地 overlay。后来加入 DICOM SR 和 GSPS,是把“屏幕标注”往标准对象推进的一步。SR 更适合保存结构化测量结果,GSPS 更适合保存显示状态和图形叠加。二者都不是独立影像,通常需要和原始 DICOM 一起理解。
背景概念
DICOM SR 是 Structured Report。它保存的是结构化内容,例如某个测量项、数值、单位、引用的图像、测量方法等。SR 适合表达“结果是什么”。例如一条长度测量可以写成一项带单位的 NUM 内容,并引用原始图像。
GSPS 是 Grayscale Softcopy Presentation State。它保存的是灰度显示状态,例如引用哪些图像、窗宽窗位、显示区域、图形注释等。GSPS 更像是“应该怎么显示这些原始图像”。它不是把 overlay 烧进像素,而是让支持 GSPS 的 Viewer 在打开原始影像时叠加显示。
QA 是另一个方向。MTF 和水模 QA 不只是交互标注,而是从像素中提取质量指标。MTF 关注空间分辨率,水模 QA 关注均匀性、噪声、CT 值稳定性和区域统计。它们都依赖正确的像素值和物理尺度。
项目实现
测量交互在前端发生,用户拖拽生成线段、角度或 ROI。前端 overlay 负责及时反馈,后端负责计算和导出。计算距离时,要把图像坐标的差值乘以 spacing;计算角度时,要把两段向量归一化后使用点积;计算 ROI 时,要在像素数组上生成 mask,再统计均值、标准差、最小值、最大值等。
SR 导出时,项目使用 pydicom 构造新的 Dataset 和 Sequence,写入文件元信息、SOP Class、UID、内容序列和原始图像引用。GSPS 导出时,重点在 Presentation State、Referenced Series/Image、Graphic Annotation 等结构。两者都不能被当作普通 CT 序列打开,所以项目加载时需要识别 SR/GSPS,并提供适合的导入或展示逻辑。
QA 分析则更像独立的后端计算服务。MTF 通常需要从边缘或线扩散函数出发,得到频域响应;水模 QA 会在指定或自动识别的区域里统计 CT 值均匀性、噪声和偏差。这些计算不能基于压缩后的截图,而要基于 DICOM 解码后的源像素。
关键函数表
| 功能 | 相关函数或数据结构 | 实现重点 |
|---|---|---|
| 距离测量 | np.linalg.norm | 用物理坐标计算,不用屏幕像素 |
| 角度测量 | 向量点积、归一化 | 处理零长度向量和数值稳定 |
| ROI 统计 | NumPy mask、np.mean、np.std | 回到源像素或 HU 值域 |
| SR 导出 | pydicom.Dataset、Sequence、dcmwrite | 保存结构化测量结果和引用 |
| GSPS 导出 | Graphic Annotation、Referenced Image | 保存显示状态和图形叠加 |
| QA | scipy.ndimage、NumPy 统计 | 基于源像素做分析 |
自绘图表
<rect x="315" y="110" width="190" height="120" rx="16" fill="var(--surface)" stroke="var(--line)" />
<text x="410" y="150" text-anchor="middle" fill="currentColor" font-weight="800">图像坐标</text>
<text x="410" y="180" text-anchor="middle" fill="var(--muted)" font-size="14">pixel row/col</text>
<text x="410" y="205" text-anchor="middle" fill="var(--muted)" font-size="14">反向仿射变换</text>
<rect x="575" y="110" width="190" height="120" rx="16" fill="var(--surface)" stroke="var(--line)" />
<text x="670" y="150" text-anchor="middle" fill="currentColor" font-weight="800">物理坐标</text>
<text x="670" y="180" text-anchor="middle" fill="var(--muted)" font-size="14">mm</text>
<text x="670" y="205" text-anchor="middle" fill="var(--muted)" font-size="14">spacing / orientation</text>
<rect x="810" y="110" width="125" height="120" rx="16" fill="var(--surface)" stroke="var(--line)" />
<text x="872" y="150" text-anchor="middle" fill="currentColor" font-weight="800">结果</text>
<text x="872" y="180" text-anchor="middle" fill="var(--muted)" font-size="14">mm / degree</text>
<text x="872" y="205" text-anchor="middle" fill="var(--muted)" font-size="14">可导出</text>
<line x1="245" y1="170" x2="315" y2="170" stroke="var(--accent)" stroke-width="3" marker-end="url(#arrow-measure)" />
<line x1="505" y1="170" x2="575" y2="170" stroke="var(--accent)" stroke-width="3" marker-end="url(#arrow-measure)" />
<line x1="765" y1="170" x2="810" y2="170" stroke="var(--accent)" stroke-width="3" marker-end="url(#arrow-measure)" />
<text x="490" y="70" text-anchor="middle" fill="currentColor" font-size="20" font-weight="900">测量必须从屏幕回到物理空间</text>
<text x="490" y="295" text-anchor="middle" fill="var(--muted)" font-size="14">截图上的像素长度没有医学单位,只有结合 DICOM geometry 才有意义。</text>
| 对象 | 保存内容 | 是否独立影像 | 适合用途 |
|---|---|---|---|
| PNG | 当前视口截图 | 是,但失去 DICOM 语义 | 展示、汇报、快速分享 |
| DICOM Secondary Capture | 烧录后的影像像素 | 是 | 把当前显示结果作为新 DICOM 图像保存 |
| DICOM SR | 结构化测量和报告内容 | 否 | 保存测量结果、单位、引用关系 |
| DICOM GSPS | 显示状态和图形叠加 | 否 | 在支持的 Viewer 中复现 overlay |
小结
测量、SR、GSPS 和 QA 共同指向一个原则:影像 Viewer 不能只停留在“屏幕上看起来对”。距离、角度、ROI、报告和显示状态都需要回到 DICOM 的几何、像素和引用关系中。当前项目已经有这条路径的基础,但完整标准对象生态仍然需要持续补齐读取、展示、编辑和互操作验证。