6

我是 dicom 开发组的初学者。我需要在 dicom image 上创建一个定位器图像行。那么,有没有什么好主意。任何极客。

4

1 回答 1

15

David Brabant 已经为您指明了正确的方向(如果您想使用 DICOM,您绝对应该阅读并珍惜dclunie 的医学图像常见问题解答)。让我们看看我是否可以详细说明它并使您更容易实现。

我假设您有一个工具/库来从 DICOM 文件(Offis 的 DCMTK?)中提取标签。为了举例说明,我将参考 CT 扫描(许多切片,即许多图像)和侦察图像,您希望在其上显示定位线。每个 DICOM 图像,包括您的 CT 切片和您的侦察,都包含有关它们在空间中位置的完整信息,在这两个标签中:

Group,Elem  VR Value                           Name of the tag   
---------------------------------------------------------------------
(0020,0032) DS [-249.51172\-417.51172\-821]  # ImagePositionPatient
                X0         Y0         Z0

(0020,0037) DS [1\0\0\0\1\0]                 # ImageOrientationPatient
                A B C D E F

ImagePositionPatient 具有以毫米为单位的第一个传输像素的全局坐标(要清楚的是左上角像素),表示为 (x,y,z)。我将它们标记为 X0、Y0、Z0。ImageOrientationPatient 包含两个向量,都是三个分量,指定图像的第一行像素和第一列像素的方向余弦。理解方向余弦并没有什么坏处(参见例如http://mathworld.wolfram.com/DirectionCosine.html),但是 dclunie 建议的方法直接与它们一起使用,所以现在让我们说它们为您提供空间中的方向图像平面。我将它们标记为 AF 以使公式更容易。

现在,在 dclunie 给出的代码中(我相信它的目的是 C,但它非常简单,它应该和 Java、C#、awk、Vala、Octave 等一样工作)约定如下:

scr_* = 指源图像,即CT切片

dst_* = 指目标图像,即侦察兵

*_pos_x, *_pos_y, *_pos_z = 上面的 X0, Y0, Z0

*_row_dircos_x, *_row_dircos_y, *_row_dircos_z = 上面的 A, B, C

*_col_dircos_x、*_col_dircos_y、*_col_dircos_z = 上面的 D、E、F

设置正确的值后,只需应用这些:

dst_nrm_dircos_x = dst_row_dircos_y * dst_col_dircos_z 
                   - dst_row_dircos_z * dst_col_dircos_y; 
dst_nrm_dircos_y = dst_row_dircos_z * dst_col_dircos_x 
                   - dst_row_dircos_x * dst_col_dircos_z; 
dst_nrm_dircos_z = dst_row_dircos_x * dst_col_dircos_y 
                   - dst_row_dircos_y * dst_col_dircos_x; 

src_pos_x -= dst_pos_x;
src_pos_y -= dst_pos_y;
src_pos_z -= dst_pos_z;

dst_pos_x = dst_row_dircos_x * src_pos_x
          + dst_row_dircos_y * src_pos_y
          + dst_row_dircos_z * src_pos_z;

dst_pos_y = dst_col_dircos_x * src_pos_x
          + dst_col_dircos_y * src_pos_y
          + dst_col_dircos_z * src_pos_z;

dst_pos_z = dst_nrm_dircos_x * src_pos_x
          + dst_nrm_dircos_y * src_pos_y
          + dst_nrm_dircos_z * src_pos_z;

或者,如果你有一些花哨的矩阵类,你可以构建这个矩阵并将它与你的点坐标相乘。

    [ dst_row_dircos_x  dst_row_dircos_y  dst_row_dircos_z  -dst_pos_x ] 
M = [ dst_col_dircos_x  dst_col_dircos_y  dst_col_dircos_z  -dst_pos_y ]
    [ dst_nrm_dircos_x  dst_nrm_dircos_y  dst_nrm_dircos_z  -dst_pos_z ]
    [ 0                 0                 0                 1          ]

那将是这样的:

Scout_Point(x,y,z,1) = M * CT_Point(x,y,z,1)

说了这么多,我们应该转换 CT 的哪些点以在侦察器上创建一条线?同样对于这个 dclunie 已经提出了一个通用的解决方案:

我的方法是投影作为源图像边界框的正方形(即连接切片的 TLHC、TRHC、BRHC 和 BLHC 的线)。

如果您投影 CT 切片的四个角点,您将有一条垂直于侦察线的 CT 切片线,以及一条不垂直切片的梯形。现在,如果您的 CT 切片与坐标轴对齐(即 ImageOrientationPatient = [1\0\0\0\1\0]),那么这四个点是微不足道的。您使用行/列数和沿 x/y 方向的像素距离计算图像的宽度/高度(以 mm 为单位),并适当地总结。如果你想实现通用案例,那么你需要一点三角函数......或者可能不需要。如果您还没有阅读方向余弦的定义,也许是时候阅读了。

我会努力让你走上正轨。例如,在 TRHC 上工作,您知道体素在图像平面中的位置:

# Pixel location of the TRHC
x_pixel = number_of_columns-1 # Counting from 0
y_pixel = 0
z_pixel = 0 # We're on a plane!

DICOM 中的像素距离值是指图像平面,因此您可以简单地将 x 和 y 乘以这些值,使其位置以 mm 为单位,而 z 为 0(像素和 mm)。我说的是这些价值观:

(0028,0011) US 512                       #   2, 1 Columns
(0028,0010) US 512                       #   2, 1 Rows
(0028,0030) DS [0.9765625\0.9765625]     #  20, 2 PixelSpacing

上面的矩阵 M 是从全局坐标到图像坐标的通用转换,具有可用的方向余弦。您现在需要的是在源图像(CT 切片)上执行逆向工作(图像到全局)的东西。我会让你去挖掘几何书籍以确定,但我认为它应该是这样的(旋转部分被转置,平移没有符号变化,当然我们使用 src_* 值):

     [src_row_dircos_x  src_col_dircos_x  src_nrm_dircos_x  src_pos_x ]
M2 = [src_row_dircos_y  src_col_dircos_y  src_nrm_dircos_y  src_pos_y ]
     [src_row_dircos_z  src_col_dircos_z  src_nrm_dircos_z  src_pos_z ]
     [0                 0                 0                 1         ]

将 CT 切片中的点(例如四个角)转换为毫米,然后应用 M2 使它们位于全局坐标中。然后您可以将它们提供给 dclunie 报告的程序。在使用它之前交叉检查我的数学,例如用于患者诊断!;-)

希望这有助于更好地理解 dclunie 的方法。干杯

于 2012-05-02T13:00:22.467 回答