【问题标题】:Extract sagittal and coronal cuts from axial view using pydicom使用 pydicom 从轴向视图中提取矢状和冠状切面
【发布时间】:2018-12-18 16:14:03
【问题描述】:

我正在尝试读取一系列默认显示轴向视图的 .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。 所以我的问题是,考虑到轴向切割,如何获得矢状和冠状切割并绘制它们?

提前致谢。

编辑: 正如@ColonelFazackerley 完美回答的那样。我在下面添加只是为了展示我是如何使用它的。

# 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)  

【问题讨论】:

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

标签: python dicom pydicom


【解决方案1】:
"""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()

针对来自此示例 3D CT 数据的系列 2 进行测试 http://www.pcir.org/researchers/54879843_20060101.html

编辑说明:接受作为 pydicom 项目的示例 https://github.com/pydicom/pydicom/blob/master/examples/image_processing/reslice.py

【讨论】:

  • 你能解释一下这个简单的地板分割是如何给我们每一个切口的吗?假设我们有 200 个切片,每个切片都是 256*256 的图像。阅读代码,我明白了:对于轴向切割,你只得到一片?对于矢状面,你得到所有切片,但每个切片只有一部分?日冕处也一样?
  • 我用地板除法给出一个整数来使用一个索引。我除以 2 从中间给出一个切片(如果你有奇数个切片 - 如果你有偶数个切片,则没有中间切片)。一个有用的应用可能是使用不同的选择切片的方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-21
  • 2020-07-02
  • 2020-06-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多