-
当前的需求是将原始DCM文件进行器官分割后,把得到的图像数据再保存为新的dcm文件,且新的dcm文件头要保留原始DCM的基本信息,以便进行后期分析。操作过程中主要有几个问题:
-
- 本来只用了pydicom库,发现它打不开有压缩的dcm文件,官网也说了只能借助其他工具打开(如gdcm),所以行不通(搞不懂这么好用的pydiocm怎么会有这种问题)
-
- 后来改用Simple ITK库,dcm文件倒是都能打开,但是保存为新的dcm时又出了问题:Simple ITK保存时会自动生成Series UID,而且0002开头的tag都不能修改,导致最后生成的dcm文件都不是一个序列,十分蛋疼
-
- 中间就差自己写代码解码dcm文件了,最后是结合pydicom和simpleitk,即用simpleitk读数据,pydicom处理tag并写入新的dcm,成功解决。
-
Pydicom
-
利用pydicom读写并修改图像数据
import pydicom dataset = pydicom.dcmread('.\001.dcm') #读取dicom文件 #val = dataset.data_element('Columns').value #根据TAG获得其值,可以读写所有tag pixeldata = dataset.pixel_array #获得图像数据的矩阵形式,只读 databyte = dataset.PixelData #获得图像的byte数据,可直接读写 datanew = pixeldata[0:400, 0:400] #截取原图像的一部分 dataset.Rows, dataset.Columns = datanew.shape #图像矩阵大小的另一种快速读写方法 newArray = np.ones([400, 400])+254 #新建一个对应大小的图像数据矩阵 data16 = np.int16(newArray) #必须转为int16 #dataset.pixel_array.data = data16 #第一种修改图像数据的方法,直接修改像素值 dataset.PixelData = data16.tobytes() #第二种修改图像数据的方法,修改byte值,建议用这种方式 dataset.save_as(r'.\002.dcm') #保存为新dcm文件
如果想把一个dcm的图像数据复制到另一个dcm中,需要考虑和pixeldata读写相关的一些tag,除了rows,columns,还有斜率/截距,高低位等,要提前修改。
- SimpleITK
- 官网及官方教程:https://simpleitk.readthedocs.io/en/master/index.html
SimpleITK是python对C++ITK的简化,可以看成是opencv的医学图像版本。 - 利用Simple ITK读写dcm数据
import SimpleITK as sitk
image = sitk.ReadImage('.\001.dcm') #读取dicom文件
image_array = sitk.GetArrayFromImage(image)
np_array = np.int16(image_array)
image_array = np.squeeze(np_array) #获得图像数据
im = sitk.GetImageFromArray(image_array) #用来读写Tag,相当于开始以imagearray构建一个新dcm
reader = sitk.ImageFileReader()
reader.SetFileName('.\002.dcm')
reader.LoadPrivateTagsOn()
reader.ReadImageInformation() #获得Tag信息
ImageType = reader.GetMetaData('0008|0008') #读取对应的Tag,0002开头的不能读写
im.EraseMetaData('0008|0008') #删除Tag,更改的话可以不写
im.SetMetaData('0008|0008', ImageType) #更改新dcm的Tag值
SOPClassUID = reader.GetMetaData('0008|0016')
im.SetMetaData('0008|0016',SOPClassUID)
SOPInstanceUID = reader.GetMetaData('0008|0018')
im.SetMetaData('0008|0018', SOPInstanceUID)
SeriesInstanceUID = reader.GetMetaData('0020|000e') #这个Tag改不了,保存时貌似会随机赋值
im.SetMetaData('0020|000e', SeriesInstanceUID)
sitk.WriteImage(im, '.\003.dcm') #保存为新dcm,不过不能组成序列
- 利用pydicom+Simple ITK读写有压缩分段的dcm
dcm = pydicom.dcmread('.\001.dcm') #选择一个普通的非压缩dcm文件作为转换模板
image = sitk.ReadImage('.\002.dcm')
image_array = sitk.GetArrayFromImage(image)
np_array = np.int16(image_array)
image_array = np.squeeze(np_array) #读取有压缩分段的dcm图像数据
dataset = pydicom.dcmread('.\002.dcm') #用来修改Tag,图像读写相关的tag都要改
dcm.data_element('PixelSpacing').value = dataset.data_element('PixelSpacing').value
dcm.data_element('RescaleIntercept').value = dataset.data_element('RescaleIntercept').value
dcm.data_element('RescaleSlope').value = dataset.data_element('RescaleSlope').value
dcm.PixelData = image_array.tobytes()
dcm.save_as('.\002.dcm') #保存文件