1

我正在使用 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) 中的体素值时,这两种方法无法获得相同的值。似乎使用series_reader.GDCMSeriesFileNames()SimpleITK 检索有关 DICOM 图像的一些信息,例如 Origin。

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

PS:在这篇文章中,所有以“图像”命名的变量都是图像的路径,而不是 SimpleITK 图像对象。

编辑:就我而言,我所有的框架都有相同的序列号,所以我不能使用series_reader.GDCMSeriesFileNames(path_folder, series_ID)

4

4 回答 4

1

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

您可以使用以下一行轻松创建 seriesID 到文件列表的映射: series_dic = { series_id: reader.GetGDCMSeriesFileNames(path, series_id) for series_id in reader.GetGDCMSeriesIDs(path) }

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

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

于 2018-06-12T19:01:59.110 回答
0

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

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

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

于 2020-12-06T06:43:43.813 回答
0

As far as I've understood your question, you have got a folder with all Dicom slices and you want to read them as a single volume so that you could access voxel values at any given coordinate. Try reading your Dicom images by this code snippet:

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

Now, image is your 3D volume containing all slices present in path_subfolder1 and you can access voxel values, spacing, directions, origin etc.

I hope this helps, if not feel free to comment down below.

于 2018-06-12T10:06:29.023 回答
0

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

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

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

注意:这里我们处理的是sitk Image Object,而不是我第一篇文章中的图像路径

2) 修改 DICOM 标头中的每个图像系列 ID:

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

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)

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

于 2018-06-19T14:38:37.220 回答