使用GDCMSeriesFileNames或路径列表读取的DICOM图像

时间:2018-06-12 09:45:57

标签: python dicom itk simpleitk

我正在使用SimpleITK来分析动态PET数据。我有一个148 * N图像的文件夹(N是我的动态PET的帧数),我想分开每个帧的图像。 首先,我为每个帧创建了一个带有相应图像的子文件夹。

>folder #Folder of dynamic data
   >subfolder1 #Subfolder with images of Frame 1
      >image1, image2, ..., image148
   >subfolder2 #Subfolder with images of Frame 2
      >image149 image 150, ..., image296

我正在阅读我的图片如下:

series_reader = sitk.ImageSeriesReader()
image = sitk.ReadImage(series_reader.GDCMSeriesFileNames(path_subfolder1))

创建所有这些子文件夹不是非常用户友好,所以我尝试将所有图像路径存储在列表中:

frame1 = [image1, ..., image148]
frame2 = [image149, ..., image296]
...
frame_list = [frame1, frame2, ..., frameN]

阅读这样的图像:

image = sitk.ReadImage(frame_list[0])

问题在于,当我查看位于相同坐标(x,y,z)中的体素的值时,我不会使用2种方法获得相同的值。 似乎用series_reader.GDCMSeriesFileNames() SimpleITK检索有关DICOM图像的一些信息,如Origin。

SimpleITK检索哪些信息以series_reader.GDCMSeriesFileNames()创建他需要具有完全相同图像的图像?或者是否有另一种方法可以使用路径列表来获得相同的图像?

P.S。 :在这篇文章中,所有以'image'命名的变量都是图像的路径,而不是SimpleITK Image对象。

编辑:在我的情况下,我的所有帧都有相同的序列号,因此我无法使用series_reader.GDCMSeriesFileNames(path_folder, series_ID)

4 个答案:

答案 0 :(得分:0)

据我所知,您有一个包含所有Dicom切片的文件夹,并且您希望将它们作为单个卷读取,以便您可以访问任何给定坐标的体素值。 请尝试通过以下代码片段阅读您的Dicom图片:

reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(path_subfolder1)
reader.SetFileNames(dicom_names)
image = reader.Execute()

现在,image是包含path_subfolder1中所有切片的3D卷,您可以访问体素值,间距,方向,原点等。

我希望这有帮助,如果不随意在下面发表评论。

答案 1 :(得分:0)

无需将系列拆分为单独的目录。您可以使用itk::simple::ImageSeriesReader::GetGDCMSeriesIDs方法获取目录中的seriesID列表。

您可以使用以下一个内容轻松地为seriesID创建一个map到文件列表的地图: series_dic = { series_id: reader.GetGDCMSeriesFileNames(path, series_id) for series_id in reader.GetGDCMSeriesIDs(path) }

通过使用GetGDCMSeriesFileNames方法,您应该获得所有文件是按其物理位置排序的正确顺序,而您手动方法则不是。

如果此自动方法不适用于您的特定扫描仪或采集过程,则必须手动加载DICOMS词典,通过series_id将它们分开,然后根据您采集的正确DICOM标记对它们进行正确排序。

答案 2 :(得分:0)

我找到的临时解决方案是以下解决方案:

1)使用sitk.ImageFileReader()创建包含每个切片作为图像对象的列表:

frame1 = [Image1, ..., Image148]
frame2 = [Image149, ..., Image296]
...
frame_list = [frame1, frame2, ..., frameN]

NB:在这里,我们处理sitk Image Object而不是像我的第一篇文章中所述的images path

2)修改DICOM标头中的每个图像seriesID:

count = 1
for frames in frame_list:
  for images in frames:
    newID = images.GetMetaData('0020|000e') + str(count)
    images.SetMetaData('0020|000e', newID)
  count += 1

3)使用writer = sitk.ImageFileWriter()writer.KeepOriginalImageUIDOn()将图像及其新的seriesID写入缓冲区文件夹中

4)使用@blowekamp方法将所有不同的系列ID及其相关的图像路径存储在字典中:

series_dic = { series_id: reader.GetGDCMSeriesFileNames(path, series_id) for series_id in reader.GetGDCMSeriesIDs(path) }

5)阅读该系列并将其存储在列表中:

for keys in series_dic:
  Img_list.append(sitk.ReadImage(series_dic[keys]))

6)最后,我使用shutil.rmtree(path, ignore_errors=True)

删除了缓冲区文件夹

这不是很优化,因为我必须写新图像然后删除它。如果您有更好的答案,请随时发表评论!

答案 3 :(得分:0)

GDCM可以处理简单的情况,例如一系列中的单个3D体积,但不准备处理时间序列。如果需要加载动态数据集,则需要使用更复杂的工具。

3D Slicer的DICOM导入器为整个文件夹结构建立索引,并确定可以从中加载的内容,包括具有无轴对齐,倾斜机架,可变切片间距的2D / 3D / 4D数据集;图像,细分,转换,结构化报告,RT计划/图像/结构集/剂量以及许多其他信息对象类型。然后,您可以将结果另存为nrrd,并使用SimpleITK对其进行进一步处理。

DCM2NIIX工具还可以将一些动态图像转换为nrrd或nifti。