将图像方向转换为轴向、矢状或冠状平面

Translate Image Orientation into axial, sagittal, or coronal plane

我已经通读了这个问题 () 并做出了很多回答,但我似乎仍然无法弄清楚将图像方向标签中的数组连接成关于以下内容的明确声明的翻译图片是从哪个平面拍摄的。

我特别好奇的是,我如何获取一个数组 [0.5,0,-0.8660254,0,1,0] 并能够说它是矢状视图,就像 Roni 在这个博客中所说的那样 post:https://dicomiseasy.blogspot.com/2013/06/getting-oriented-using-image-plane.html 尤其是当矢状面切割应该这样定义时 - ['0', '1', '0', '0', '0', '-1'].

我不知道是否有可供 Python 用户进行此转换的现有插件,但如果有人可以帮助我了解该过程是如何完成的,我很乐意做一个。

如果只对图像的平面感兴趣,基本上需要图像z轴的方向。您可以通过对行和列图像方向向量(例如 ImageOrientationPatient 中给出的方向向量)进行叉积来获得此结果。在生成的矢量中,您可以将主方向定义为值的绝对最大值。 在您的示例中,您有:

>>> import numpy as np
>>> a = np.array([0.5,0,-0.8660254])
>>> b = np.array([0,1,0])
>>> np.cross(a, b)
array([ 0.8660254, -0.       ,  0.5      ])

这种情况下的主要方向是患者的 x 轴(次要方向是患者的 z 轴),意思是矢状视图,具有次要的横向方向(x -> 矢状,y -> 冠状,z -> transverse/axial).

因此,要确定主扫描方向,您可以这样做:

import numpy as np

ds = dcmread(filename)
image_ori = ds.ImageOrientationPatient
image_y = np.array([image_ori[0], image_ori[1], image_ori[2]])
image_x = np.array([image_ori[3], image_ori[4], image_ori[5]])
image_z = np.cross(image_x, image_y)
abs_image_z = abs(image_z)
main_index = list(abs_image_z).index(max(abs_image_z))
if main_index == 0:
    main_direction = "sagittal"
elif main_index == 1:
    main_direction = "coronal"
else:
    main_direction = "transverse"
print(main_direction)

MrBean 已经很好地回答了这个问题,但我想我会详细说明你的问题。

你说:'What I specifically am curious about is how I can take an array [0.5,0,-0.8660254,0,1,0] and be able to say it is a sagittal view'

矢状面、轴向面、冠状面视图,如果您想严格遵守,只有那些 沿着患者的轴线 。因此,正如您所指出的,只有那些在 IOP 向量中全为 1 或全为 0 的向量。


因此,对于上面的示例,您*不能说 [0.5,0,-0.8660254,0,1,0] 是矢状的,因为它的叉积并不严格符合任何单位向量。


但是每个人所做的,以及罗尼在他伟大的post中所说的,你可以说一个特定的方向是更多,或最接近轴位,或矢状位或冠状位,并称之为。

或者,您可以为每个单位视图设置一个公差,如果它在单位向量的公差范围内,则只称其为冠状面、轴向面或矢状面——否则就称其为未定义。 (你可以把这个公差想象成一个角度——所以,例如,如果它是一个单位向量的 10 度)。


所以 MrBean 上面的代码实际上就是这样做的 - 对于给定的输入 IOP,它正在寻找 最接近 单位向量的法线(注意对 max 的调用) :

main_index = list(abs_image_z).index(max(abs_image_z))


在我的代码中,我经常使用这个定义,所以我制定了自己的方法来计算它。请注意,与 MrBean 的代码一样,它也会找到 'closest' 方向,iop_rounded = [round(x) for x in iop]。这会将所有值四舍五入为 0 或 1,因此在一天结束时,相当于 MrBean 使用的值。

def get_orientation(dcm: DcmObj) -> str:
    """Get orientation of dicom object.

    Returns one of
        Transverse
        Coronal
        Sagittal
        NA  (if ImageOrientationPatient not available)
    """

    iop = getattr(dcm, 'ImageOrientationPatient', None)

    if iop is None:
        return 'NA'

    iop_rounded = [round(x) for x in iop]
    plane_cross = np.cross(iop_rounded[0:3], iop_rounded[3:6])
    plane = [abs(x) for x in plane_cross]

    if plane[0] == 1:
        return 'Sagittal'
    elif plane[1] == 1:
        return 'Coronal'
    elif plane[2] == 1:
        return 'Transverse'
    else:
        return 'NA'