1.原始的每个DCE序列中有多个dicom文件,经过插值裁剪后转成以一个3Dmatnii矩阵
2.现在的需求是把处理过的3Dnii矩阵还原成2Ddicom文件,并且保留原始dicom信息.
1.插值裁剪后的影像数据
每一个.nii.gz文件代表DCE-MRI中的一个序列
2.原始DCE-MRI影像数据中一个序列包含多个dcm文件
3.Python代码:把3Dnii文件还原成2Ddicom文件,并且保留原始dicom信息.
导入需要的包
import os
import SimpleITK as sitk
import numpy as np
import pydicom as dicom
定义翻转函数实现图像的180°旋转
def flip180(arr):#图片反转180°
new_arr =arr.copy()
new_arr = arr.reshape(arr.size)
new_arr = new_arr[::-1]
new_arr = new_arr.reshape(arr.shape)
return new_arr
定义给dicom的tag赋值的函数
def modify_dicom(ds,dcm):#把原始dicom的元数据写进新的dicom中,否则无法成为一个序列
#PatientInfo
ds.PatientID = dcm.PatientID
ds.PatientName = dcm.PatientName
ds.PatientBirthDate = dcm.PatientBirthDate
ds.PatientSex = dcm.PatientSex
ds.PatientAge = dcm.PatientAge
ds.PatientWeight = dcm.PatientWeight
try:
ds.MagneticFieldStrength = dcm.MagneticFieldStrength
ds.Manufacturer = dcm.Manufacturer
except TypeError:
print("Error:没有InstitutionName、Manufacturer、InstitutionName tag")
#studyInfo
ds.StudyDate =dcm.StudyDate
ds.StudyTime = dcm.StudyTime
ds.StudyDescription = dcm.StudyDescription
ds.StudyInstanceUID = dcm.StudyInstanceUID
ds.StudyID = ds.StudyID
# seriesInfo
ds.SeriesInstanceUID = dcm.SeriesInstanceUID
ds.SeriesDescription = dcm.SeriesDescription
ds.Modality = dcm.Modality
ds.SeriesNumber = dcm.SeriesNumber
#ds.InstanceNumber = instanceNumber #Instance Number
ds.SeriesDate = dcm.SeriesDate
ds.SeriesTime = dcm.SeriesTime
ds.SOPClassUID = dcm.SOPClassUID
return ds
定义给nii转dicom的核心函数
def nii2dicom(nii_img,save_dir,DCE_MR):
"""[将重采样后的nii图片转dicom保存]
Args:
nii_img ([]): 一个3维nii类型,shape=(W,H,切片数)
save_dir ([type]): 转成dicom序列文件保存路径
"""
itk_img = sitk.ReadImage(nii_img)
img_3Dndarray = sitk.GetArrayFromImage(itk_img)#得到图像矩阵
img_shape = img_3Dndarray.shape
print(img_shape,img_shape[0])#查看 3D 维度
img_num = img_3Dndarray.shape[0]
PixelSpacing = itk_img.GetMetaData('pixdim[1]')#pixdim[1] : 0.379464 pixdim[2] : 0.379464 pixel spacing
SliceThickness = itk_img.GetMetaData('pixdim[3]')#pixdim[3] : 1.2 层厚
BitsAllocated = itk_img.GetMetaData('bitpix')#16
Columns = itk_img.GetMetaData('dim[1]')#dim[1] : 896
Rows = itk_img.GetMetaData('dim[2]')
for i in range(img_num-13):
#从第13张slice开始,13张之前的均是不完整的切片
####.nii切片倒着读,并旋转180度,也要变为int16才行 img_num-i-1
out = flip180(img_3Dndarray[12+i,:,:]).astype('uint16')
itk_img_1 = sitk.GetImageFromArray(out)
InstanceNumber = ''
if (i+1) <10:
InstanceNumber = '0000'+str(i+1)
elif (i+1) <100:
InstanceNumber = '000'+str(i+1)
elif (i+1) <300:
InstanceNumber = '00'+str(i+1)
else:
print('Warning!!',InstanceNumber,"dicom数量大于300")
dicom_save_file_path = save_dir+'\\'+InstanceNumber+'.dcm'#to do i range
itk_img_1.SetMetaData('0028|0030',PixelSpacing)#0028,0030 修改 Pixel Spacing: 1.5625信息
itk_img_1.SetMetaData('0018|0050',SliceThickness)
itk_img_1.SetMetaData('0028|0100',str(16))#bitpix : 16 位数
itk_img_1.SetMetaData('0028|0011',Columns)#Columns
itk_img_1.SetMetaData('0028|0010',Rows)#Rows
itk_img_1.SetMetaData('0020|0013',str(i+1))#instanceNumber
sitk.WriteImage(itk_img_1,dicom_save_file_path)
######再读文件,修改dicom的tag信息使这些图片成为一个序列
read_dicom_path = DCE_MR+'\\'+'00010.dcm' #原始dcm文件的具体路径
dcm = dicom.read_file(read_dicom_path)
ds = dicom.read_file(dicom_save_file_path)
if i == 0:
seriesInstanceUID = ds.SeriesInstanceUID
studyInstanceUID = ds.StudyInstanceUID
frameUID = ds[0X0020, 0X0052].value
else:
ds.SeriesInstanceUID = seriesInstanceUID #修改Series Instance UID
ds.StudyInstanceUID = studyInstanceUID
ds[0X0020, 0X0052].value = frameUID
ds = modify_dicom(ds,dcm)
ds.InstanceNumber = i+1 ###必须加,形成连续变化的序列,不然,dicom软件读取切片会变乱
ds.save_as(dicom_save_file_path)
返回具体nii文件的路径
def get_NII_path(root_path,niidata_path,reliceniidata_path):
'''
返回具体nii文件的路径
'''
count_study = 0
for every_study in os.listdir(niidata_path):#遍历所有的病历号
count_study +=1
tmp_MR_path = os.path.join(root_path,every_study,'MR')#DWI ,T2等
_renii_path =os.path.join(reliceniidata_path,every_study)
if count_study <80:
continue
for every_MRI in os.listdir(tmp_MR_path):#每个病历号下面可能有多次MRI
tmp_MRI_path = os.path.join(tmp_MR_path,every_MRI)
tmp_DCEseries = tmp_MRI_path+"\DCE00000"
DCE_length = len(os.listdir(tmp_DCEseries))
print(tmp_DCEseries,"-->",DCE_length)
_rdicom_path = os.path.join(niidata_path,every_study,'ResliceMR',every_MRI)
for every_nii in os.listdir(_renii_path):
if DCE_length!=112 and "corDCE0000" in every_nii:
str1 = every_nii.replace(".nii.gz","")
str2 = str1.replace("cor","")
DCE_MR = os.path.join(tmp_MRI_path,str2)
every_niidata = os.path.join(_renii_path,every_nii)
print(every_niidata)
save_rDCE = os.path.join(_rdicom_path,str1)
if not os.path.exists(save_rDCE):
os.makedirs(save_rDCE)
print("create-->"+save_rDCE+"-->successfully!!")
else:
print(save_rDCE+" have exists!")
nii2dicom(every_niidata,save_rDCE,DCE_MR)
定义路径,调用函数执行
if __name__ =="__main__":
root_path = r"G:\DCE+T2+ADC"
niidata_path = r"G:\DCE90_NiiDATA"
reliceniidata_path =r"G:\DCE_ResliceNiiDATA"
get_NII_path(root_path,niidata_path,reliceniidata_path)
代码执行过程:
特别说明:本文为原创文章,参考或转发本文需注明本文链接,有问题请联系:nick.yu.jd@qq.com