在将dicom转nii的时候遇到了一个问题,就是医院给的dicom数据的每一个切片的命名是乱的,转成nii之后序列的z轴完全就是乱的,如下所示:
按切片顺序打印的图像,完全就是乱序的,在ITK中打开也可以看到图像z轴是乱的:
在网上找的dcm转nii的代码都是按照dcm命名来对dcm进行排序的,但是医院有时候给的数据命名不规范
解决方案:
用MicroDicom打开dicom图像,查看Dicom Tags,使用Instance number对切片进行排序,这个字段是存在dcm图像中的,而且按切片顺序保存的
def _get_instance_number(dicom_path):
img_reader = sitk.ImageFileReader()
img_reader.SetFileName(dicom_path)
img_reader.LoadPrivateTagsOn()
img_reader.ReadImageInformation()
number_str = img_reader.GetMetaData('0020|0013')#获取Instance number
return int(number_str)
def get_slice(dcm_path):
#用这个函数获得按照Instance number排序的切片路径
reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(dcm_path)#获得切片路径,这个是按切片命名排序的
r = []
for name in dicom_names:
r.append({"instance_number":_get_instance_number(name),"dcm_name":name})
r = pd.DataFrame(r)
r = r.sort_values("instance_number")#按照Instance number排序
r = tuple(r["dcm_name"])#获得按照Instance number排序的切片路径
return r
def dcm2nii(dcms_path):
# 1.构建dicom序列文件阅读器,并执行(即将dicom序列文件“打包整合”)
reader = sitk.ImageSeriesReader()
dicom_names = get_slice(dcms_path)
reader.SetFileNames(dicom_names)
# 2.将整合后的数据转为array,并获取dicom文件基本信息
image = reader.Execute()
image_array = sitk.GetArrayFromImage(image2) # z, y, x
origin = image2.GetOrigin() # x, y, z
# print(origin)
spacing = image2.GetSpacing() # x, y, z
# print(spacing)
direction = image2.GetDirection() # x, y, z
# print(direction)
# 3.将array转为img,并保存为.nii.gz
image3 = sitk.GetImageFromArray(image_array)#这些需要设置一下,不然z轴的空间信息可能会被压缩
image3.SetSpacing(spacing)
image3.SetDirection(direction)
image3.SetOrigin(origin)
sitk.WriteImage(image3, nii_path)
dcm_path = r"E:\xx\1647026\4_OAx T2 FLAIR"
nii_path = r"E:\xx\1647026\4_OAx T2 FLAIR.nii.gz"
dcm2nii(dcm_path,nii_path)
再用ITK打开,切片顺序就正常了。
按顺序打印也是对的了!
摸索了几天,终于搞定了!yes!