如何在DICOM中绘制侦察/参考线

6

我是dicom开发组的初学者。我需要在dicom图像上创建定位器图像线。是否有好的想法?有没有技术专家能提供帮助。


1
这里提到了几个来源:http://www.dclunie.com/medical-image-faq/html/part2.html,尽管没有C#,但一些Java和C ++可以为您提供一个起点。 - David Brabant
1
谢谢你提供的链接。我已经查看了,但仍然有疑问。我想在参考图像上绘制线条,因此我需要至少2个点,但是在计算后,我只得到了一个点。我无法理解这里的参数。我应该从哪里获取这些参数? - eurekha_ananth
1个回答

15
David Brabant已经指出了正确的方向(如果您想使用DICOM工作,一定要阅读并珍藏dclunie的医学图像FAQ)。让我们看看我是否可以详细阐述并使您更容易实现。
我假设您有一个从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建议的方法直接使用它们,因此现在让我们先说它们可以给您图像平面在空间中的方向。我将它们标记为A-F,以便公式更容易编写。

现在,在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方向的像素距离计算图像的宽度/高度(以毫米为单位),并适当地进行求和。 如果要实现通用情况,则需要一些三角学知识...或者也许不需要。 如果您还没有阅读过方向余弦的定义,现在可能是时候了。
我会试着给你指路。 例如,在处理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乘以这些值就可以得到它们在毫米中的位置,而z为0(既是像素也是毫米)。我说的是这些值:
(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的方法。干杯

1
非常欢迎您选择我的答案,感谢您的支持。正如我所说,关于矩阵 M2 的解释是准确的,但是这个矩阵本身没有经过测试。如果您在尝试后能够确认其有效性并留下评论,那就太好了… - Epikuros
1
如果我正确地理解 M2 应该将 2D 图像行、列(以像素为单位)坐标转换为全局坐标 3D 系统,则我认为正确的矩阵可在 http://dicom.nema.org/medical/dicom/2017b/output/chtml/part03/sect_C.7.6.2.html 的 C.7.6.2.1-1 方程式中找到。 - Aerik

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接