Python 使用pydicom从轴向视图提取矢状面和冠状面切口

Python 使用pydicom从轴向视图提取矢状面和冠状面切口,python,dicom,pydicom,Python,Dicom,Pydicom,我正在尝试读取一系列默认显示轴向视图的.dcm文件。代码如下: import os import numpy as np import pydicom as dicom from matplotlib import pyplot as plt root_dir = 'mydcomDir' def sortDcm(): print('Given Path to the .dcm directory is: {}'.format(root_dir)) slice

我正在尝试读取一系列默认显示轴向视图的.dcm文件。代码如下:

import os
import numpy as np
import pydicom as dicom
from matplotlib import pyplot as plt

root_dir = 'mydcomDir'


def sortDcm():
        print('Given Path to the .dcm directory is: {}'.format(root_dir))
        slices = [dicom.read_file(root_dir + '/' + s) for s in os.listdir(root_dir)]
        slices.sort(key = lambda x: float(x.ImagePositionPatient[2]))
        pos1 = slices[int(len(slices)/2)].ImagePositionPatient[2]
        pos2 = slices[(int(len(slices)/2)) + 1].ImagePositionPatient[2]
        diff = pos2 - pos1
#        if diff > 0:
#            slices = np.flipud(slices)
        try:
            slice_thickness = np.abs(slices[0].ImagePositionPatient[2] - slices[1].ImagePositionPatient[2])
        except:
            slice_thickness = np.abs(slices[0].SliceLocation - slices[1].SliceLocation)

        for s in slices:
            s.SliceThickness = slice_thickness
#        print("from sorted dicom",len(slices))         
        return slices 


dcms = sortDcm()
ref_dicom = dcms[0]

d_array = np.zeros((ref_dicom.Columns,ref_dicom.Rows, len(dcms)), dtype=ref_dicom.pixel_array.dtype)

for dcm in dcms:
    d_array[:, :, dcms.index(dcm)] = dcm.pixel_array

#    fig = plt.figure(figsize=(12,12))
#    plt.subplot(1, 3, 1)
#    plt.title("Coronal")
#    plt.imshow(np.flipud(d_array[idx , :, :].T))
#    plt.subplot(1, 3, 2)
#    plt.title("Sagital")
#    plt.imshow(np.flipud(d_array[:, idy, :].T))
#    plt.subplot(1, 3, 3)
    plt.title("axial")
    plt.imshow(d_array[:, :, dcms.index(dcm)])
    plt.pause(0.001)
正如您从代码中看到的,我无法找出特定dcm文件的相关idx和idy。 所以我的问题是如何得到矢状切口和冠状切口,并根据轴向切口绘制它们

提前谢谢

编辑: 正如@Colonelfazakerley完美地回答的那样。我在下面的一行加上这个,只是为了说明我是如何使用它的

# fill 3D array with the images from the files
for i, s in enumerate(slices):
    img2d = s.pixel_array
    img3d[:,:,i] = img2d
#then to view sagittal and coronal slices for each of the axial slice
for i, s in enumerate(slices):
    img2d = s.pixel_array
    img3d[:,:,i] = img2d
    corId = corId-1
    sagId = sagId-1
#    plot 3 orthogonal slices
    a1 = plt.subplot(1,3,1)
    plt.title('Axial')
    plt.imshow(img3d[:,:,i],'gray')
    a1.set_aspect(ax_aspect)

    a2 = plt.subplot(1,3,2)
    plt.title('Sagittal')
    plt.imshow(np.flipud(img3d[:,sagId,:].T),'gray')
    a2.set_aspect(sag_aspect)

    a3 = plt.subplot(1,3,3)
    plt.imshow(np.flipud(img3d[corId,:,:].T),'gray')
    a3.set_aspect(cor_aspect)
    plt.title('Coronal')
    plt.show()
    plt.pause(0.001)  
用法:reslice.py 其中是指一组DICOM图像文件。 示例:python reslice.py“*.dcm”。需要引号来保护glob 从您的系统中删除,并将其留给脚本。”“” 导入pydicom 将numpy作为np导入 将matplotlib.pyplot作为plt导入 导入系统 导入glob #加载DICOM文件 文件=[] 打印('glob:{}'。格式(sys.argv[1])) 对于glob.glob(sys.argv[1],recursive=False)中的fname: 打印(“加载:{}”。格式(fname)) files.append(pydicom.read_文件(fname)) 打印(“文件计数:{}”。格式(len(文件))) #跳过没有切片位置的文件(如scout视图) 切片=[] skipcount=0 对于文件中的f: 如果hasattr(f,“切片位置”): 切片。追加(f) 其他: skipcount=skipcount+1 打印(“跳过,无切片位置:{}”。格式(skipcount)) #确保它们的顺序正确 切片=已排序(切片,键=lambda s:s.SliceLocation) #像素方面,假设所有切片都相同 ps=切片[0]。像素间距 ss=切片[0]。切片厚度 ax_aspect=ps[1]/ps[0] 垂向=ps[1]/ss cor_aspect=ss/ps[0] #创建三维阵列 img\u shape=list(切片[0]。像素数组。shape) img_shape.append(len(切片)) img3d=np.零(img_形) #用文件中的图像填充三维阵列 对于枚举中的i,s(片): img2d=s.pixel\u阵列 img3d[:,:,i]=img2d #绘制3个正交切片 a1=plt.子批次(2,2,1) plt.imshow(img3d[:,:,img_shape[2]//2]) a1.设置纵横比(最大纵横比) a2=plt.子批次(2,2,2) plt.imshow(img3d[:,img_形状[1]//2,:])) a2.设置纵横比(弧垂纵横比) a3=plt.子批次(2,2,3) plt.imshow(img3d[img_shape[0]//2,:,:].T) a3.设置相位(相位相位) plt.show() 根据本例3D CT数据中的系列2进行测试

编辑说明:作为pydicom项目的示例接受 用法:reslice.py 其中是指一组DICOM图像文件。 示例:python reslice.py“*.dcm”。需要引号来保护glob 从您的系统中删除,并将其留给脚本。”“” 导入pydicom 将numpy作为np导入 将matplotlib.pyplot作为plt导入 导入系统 导入glob #加载DICOM文件 文件=[] 打印('glob:{}'。格式(sys.argv[1])) 对于glob.glob(sys.argv[1],recursive=False)中的fname: 打印(“加载:{}”。格式(fname)) files.append(pydicom.read_文件(fname)) 打印(“文件计数:{}”。格式(len(文件))) #跳过没有切片位置的文件(如scout视图) 切片=[] skipcount=0 对于文件中的f: 如果hasattr(f,“切片位置”): 切片。追加(f) 其他: skipcount=skipcount+1 打印(“跳过,无切片位置:{}”。格式(skipcount)) #确保它们的顺序正确 切片=已排序(切片,键=lambda s:s.SliceLocation) #像素方面,假设所有切片都相同 ps=切片[0]。像素间距 ss=切片[0]。切片厚度 ax_aspect=ps[1]/ps[0] 垂向=ps[1]/ss cor_aspect=ss/ps[0] #创建三维阵列 img\u shape=list(切片[0]。像素数组。shape) img_shape.append(len(切片)) img3d=np.零(img_形) #用文件中的图像填充三维阵列 对于枚举中的i,s(片): img2d=s.pixel\u阵列 img3d[:,:,i]=img2d #绘制3个正交切片 a1=plt.子批次(2,2,1) plt.imshow(img3d[:,:,img_shape[2]//2]) a1.设置纵横比(最大纵横比) a2=plt.子批次(2,2,2) plt.imshow(img3d[:,img_形状[1]//2,:])) a2.设置纵横比(弧垂纵横比) a3=plt.子批次(2,2,3) plt.imshow(img3d[img_shape[0]//2,:,:].T) a3.设置相位(相位相位) plt.show() 根据本例3D CT数据中的系列2进行测试

编辑说明:作为pydicom项目的示例接受

对于大多数类型的DICOM图像,每个文件中都有一个轴向切片。如果你想要矢状面或冠状面,你必须加载所有切片,制作3D图像,然后在另一个平面重新切片。是的,你是正确的。我在每个文件中都有轴向切片。但正如你所说,我必须在另一个平面上重新切片才能得到冠状面或矢状面,我该怎么做?这是我的问题。重新切片轴向切片以获得其他平面视图的过程是什么??我找不到一个pydicom的解释示例。如果您能解释或提供重新选择的示例代码,那就太好了。堆叠和重新选择不是pydicom特有的。numpy会让它更快。我建议在那里查找示例。是的,我知道reslicing不是pydicom特有的。但我正在寻找python中的示例,不幸的是找不到一个正确解释的示例。你能提供一个吗?虽然我看过matlab的例子,但在python中找不到好的例子。对于大多数类型的DICOM图像,每个文件中都有一个轴向切片。如果你想要矢状面或冠状面,你必须加载所有切片,制作3D图像,然后在另一个平面重新切片。是的,你是正确的。我在每个文件中都有轴向切片。但正如你所说,我必须在另一个平面上重新切片才能得到冠状面或矢状面,我该怎么做?这是我的问题。重新切片轴向切片以获得其他平面视图的过程是什么??我找不到一个pydicom的解释示例。如果您能解释或提供重新选择的示例代码,那就太好了。堆叠和重新选择不是pydicom特有的。numpy会让它更快。我建议在那里查找示例。是的,我知道reslicing不是pydicom特有的。但我正在寻找python中的示例,不幸的是找不到一个正确解释的示例。你能提供一个吗?虽然我看过matlab的例子,但在python中找不到好的例子。
"""usage: reslice.py <glob>
where <glob> refers to a set of DICOM image files.

Example: python reslice.py "*.dcm". The quotes are needed to protect the glob
from your system and leave it for the script."""

import pydicom
import numpy as np
import matplotlib.pyplot as plt
import sys
import glob

# load the DICOM files
files=[]
print('glob: {}'.format(sys.argv[1]))
for fname in glob.glob(sys.argv[1], recursive=False):
    print("loading: {}".format(fname))
    files.append(pydicom.read_file(fname))

print("file count: {}".format(len(files)))

# skip files with no SliceLocation (eg scout views)
slices=[]
skipcount=0
for f in files:
    if hasattr(f, 'SliceLocation'):
        slices.append(f)
    else:
        skipcount = skipcount + 1

print("skipped, no SliceLocation: {}".format(skipcount))

# ensure they are in the correct order
slices = sorted(slices, key=lambda s: s.SliceLocation)

# pixel aspects, assuming all slices are the same
ps = slices[0].PixelSpacing
ss = slices[0].SliceThickness
ax_aspect = ps[1]/ps[0]
sag_aspect = ps[1]/ss
cor_aspect = ss/ps[0]

# create 3D array
img_shape = list(slices[0].pixel_array.shape)
img_shape.append(len(slices))
img3d=np.zeros(img_shape)

# fill 3D array with the images from the files
for i, s in enumerate(slices):
    img2d = s.pixel_array
    img3d[:,:,i] = img2d

# plot 3 orthogonal slices
a1 = plt.subplot(2,2,1)
plt.imshow(img3d[:,:,img_shape[2]//2])
a1.set_aspect(ax_aspect)

a2 = plt.subplot(2,2,2)
plt.imshow(img3d[:,img_shape[1]//2,:])
a2.set_aspect(sag_aspect)

a3 = plt.subplot(2,2,3)
plt.imshow(img3d[img_shape[0]//2,:,:].T)
a3.set_aspect(cor_aspect)

plt.show()