c# - 如何在 dicom 中绘制侦察线/引用线

标签 c# image-processing dicom medical

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

最佳答案

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 建议的方法直接与它们一起使用,所以现在我们只说它们为您提供图像平面的空间方向。我将它们标记为 A-F 以使公式更容易。

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

scr_* = refers to the soruce image, i.e. the CT slice

dst_* = refers to the destination image, i.e. the scout

*_pos_x, *_pos_y, *_pos_z = the X0, Y0, Z0 above

*_row_dircos_x, *_row_dircos_y, *_row_dircos_z = the A, B, C above

*_col_dircos_x, *_col_dircos_y, *_col_dircos_z = the D, E, F above

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

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(像素和毫米)。我说的是这些值(value)观:

(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 的方法。干杯

关于c# - 如何在 dicom 中绘制侦察线/引用线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10241062/

相关文章:

Python:处理图像并保存到文件流

algorithm - 检测位图中的三角形

c++ - 在 C++ 中从 YBR_FULL 转换为 RGB?

c# - 如何等到进程终止后再继续执行 - C#

c# - 如何强制调用 C# 派生方法

c# - 服务器错误 : The request was aborted: Could not create SSL/TLS secure channel

c# - 查询 XML 的 Entity Framework

image - 检查邻域中的像素值

applet - DICOM;进行多平面重建并在Web上显示

dicom - "Other Word"VR 对于 8 位 RGB 图像是否合法?