Pydicom

单张影像的读取

使用 pydicom.dcmread() 函数进行单张影像的读取,返回一个pydicom.dataset.FileDataset对象.

import os

import pydicom

# 调用本地的 dicom file

folder_path = r"D:\Files\Data\Materials"

file_name = "PA1_0001.dcm"

file_path = os.path.join(folder_path,file_name)

ds = pydicom.dcmread(file_path)

在一些特殊情况下,比如直接读取从医院拿到的数据(未经任何处理)时,可能会发生以下报错:

raise InvalidDicomError("File is missing DICOM File Meta Information "

pydicom.errors.InvalidDicomError: File is missing DICOM File Meta Information header or the 'DICM' prefix is missing from the header. Use force=True to force reading.

可以看到,由于缺失文件元信息头,无法直接读取,只能强行读取.这种情况可以直接根据提示,调整命令为:

ds = pydicom.dcmread(file_path,force=True)

但后续还会碰到:

AttributeError: 'Dataset' object has no attribute 'TransferSyntaxUID'

在网上检索后发现,可以通过设置TransferSyntaxUID来解决问题:

ds.file_meta.TransferSyntaxUID = pydicom.uid.ImplicitVRLittleEndian

这样就大功告成了(这里实际上就提前接触到了下面读取Dicom Tags的内容了)

一些简单处理

读取成功后,我们可以对 Dicom文件 进行一些简单的处理

读取并编辑Dicom Tags

可以通过两种方法来读取Tag的值

使用的Tag的Description

print(ds.PatientID,ds.StudyDate,ds.Modality)

使用 ds.get() 函数. 函数内参数采用的是Tag ID.几种简单的打开Dicom文件的软件(如RadiAnt DICOM Viewer)都可以直接看到.这里不再赘述.

ds.get(0x00100020) # 这里得到的是PatientID

读取到相应的Tag值后, 也可以将其他的值写入这些Tag.只要最后保存一下就可以了.

借助Numpy与PIL.Image

读取Dicom文件后,可以借助Numpy以及图像处理库(如PIL.Image)来进行简单的处理.

借助Numpy

import numpy as np

data = np.array(ds.pixel_array)

注意这里使用的是 np.array() 而不是 np.asarray(). 因为前者的更改并不会带来原pixel_array的改变.

在转化为ndarray后 可以直接进行简单的切割和连接,比如截取某一部分和将两张图像拼在一起等,之后再写入并保存下来即可.

借助PIL.Image

from PIL import Image

data_img = Image.fromarray(ds.pixel_array)

data_img_rotated = data_img.rotate(angle=45,resample=Image.BICUBIC,fillcolor=data_img.getpixel((0,0)))

这里展示的是旋转, 还有其他功能如resize等.

需要注意的是,从Numpy的ndarray转化为Image时,一般会发生变化:

print(data.dtype) # int16

data_rotated = np.array(data_img_rotated)

print(data_img) # int32

只需要指定参数就可以解决了

data_rotated = np.array(data_img_rotated,dtype = np.int16)

可视化

简单的可视化Pydicom没有直接的实现方法,我们可以通过上面借助Matplotlib以及Image模块来实现.但效果有限.

借助 Matplotlib (Pydicom官方文档中使用的方法)

from matplotlib import pyplot

pyplot.imshow(ds.pixel_array,cmap=pyplot.cm.bone)

pyplot.show()

效果如图所示:

但真实的图像是:

显然颜色是有区别的.导致这种差别的原因是pyplot函数使用的cm也就是"color map" 是简单的"bone" 并不能满足医学图像的要求.

借助Image模块

data_img.show()

一条指令即可,但是效果很差,如图所示:

综合来看,两种方法都不是很好.

单张影像的写入

经过上面对Tag值的修改, 对图像的切割, 旋转等操作.最后需要重新写入该Dicom文件.

ds.PixelData = data_rotated.tobytes()

ds.Rows,ds.Columns = data_rotated.shape

new_name = "dicom_rotated.dcm"

ds.save_as(os.path.join(folder_path,new_name))

SimpleITK

SimpleITK 是从基于C++的ITK迁移到Python的,所以很多方法的使用都跟C++很相似.

import SimpleITK as sitk

单张影像的读取

有两种方法:

sitk.ReadImage()

这种方法直接返回image对象,简单易懂.但是无法读取Tag的值.

img = sitk.ReadImage(file_path)

print(type(img)) #

sitk.ImageFileReader()

这种方法比较像C++的操作风格,需要先初始化一个对象,然后设置一些参数,最后返回image.相对更复杂,但可以操作的点比较多

file_reader = sitk.ImageFileReader()

file_reader.SetFileName(file_path) #这里只显示了必需的,还有很多可以设置的参数

data = file_reader.Execute()

# 使用这种方法读取Dicom的Tag Value

for key in file_reader.GetMetaDataKeys():

print(key,file_reader.GetMetaData(key))

以上两种方法返回的都是三维的对象,这与Pydicom有很大的不同.

data_np = sitk.GetArrayFromImage(data)

print(data_np.shape) # (1, 512, 512) = (Slice index, Rows, Columns)

序列读取

序列读取的方法与单张图像读取的第二种方法很相似.

(暂且只发现了一种方法读取序列,如果还有其他方法,请在评论区予以补充,感谢!)

series_reader = sitk.ImageSeriesReader()

fileNames = series_reader.GetGDCMSeriesFileNames(folder_name)

series_reader.SetFileNames(fileNames)

images = series_reader.Execute()

同样,返回的也是三维的对象.

一些简单操作

SimpleITK 包含很多图像处理如滤波的工具,这里简单介绍一个边缘检测工具和可视化工具

边缘检测

以Canny边缘检测算子为例,与读取单张图像类似,同样有两种方式:

sitk.CannyEdgeDetection()

由于滤波的对象必须是32位图像或者其他格式, 需要通过 sitk.Cast() 转换. 之后可以再转换回原格式.

data_32 = sitk.Cast(data,sitk.sitkFloat32)

data_edge_1 = sitk.CannyEdgeDetection(data_32,5,30,[5]*3,[0.8]*3)

sitk.CannyEdgeDetectionImageFilter()

这个操作相对麻烦一些

Canny = sitk.CannyEdgeDetectionImageFilter()

Canny.SetLowerThreshold(5)

Canny.SetUpperThreshold(30)

Canny.SetVariance([5]*3)

Canny.SetMaximumError([0.5]*3)

data_edge_2 = Canny.Execute(data_32)

可视化

可视化的方法非常简单 只需要一条指令:

sitk.Show()

但需要先安装工具ImageJ,否则无法使用.具体的安装链接,可以参考这篇博文:sitk.show()与imageJ结合使用常见的问题

同一张Dicom文件使用sitk.Show()得到的效果如下图:

除此之外,ImageJ还有一个Tool Bar 支持对图像的进一步处理:

可见,SimpleITK的可视化要比上面介绍的强大很多,不仅可以实现单张图像的可视化以及图像处理,还可以同时对整个序列的图像进行统一处理.

单张影像的写入

同样有两种方法

sitk.WriteImage()

new_name = "new_MR_2.dcm"

sitk.WriteImage(img,os.path.join(folder_name,new_name))

sitk.ImageFileWriter()

file_writer = sitk.ImageFileWriter()

file_writer.SetFileName(os.path.join(folder_name,new_name))

file_writer.SetImageIO(imageio="GDCMImageIO")

file_writer.Execute(img)

使用这两种方法进行写入的时候,会发现,即便什么也没有做,但得到的新Dicom文件要小于原始的Dicom文件.这是因为新的Dicom文件中没有Private Creator信息(属于Dicom Tag的内容).当然如果原始Dicom文件中本就没有这种信息,文件大小是保持相同的.

因为很多时候只是对图像进行处理,所以不再深究.

若有错误,还请指出,谢谢!

dcm文件读取 java_使用Python对Dicom文件进行读取与写入相关推荐

  1. 使用Python对Dicom文件进行读取与写入的实现(pydicom 和 SimpleITK)

    这篇文章主要介绍了使用Python对Dicom文件进行读取与写入的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 使用Pyd ...

  2. python入门文件读取与写入_使用Python对Dicom文件进行读取与写入的实现

    Pydicom 单张影像的读取 使用 pydicom.dcmread() 函数进行单张影像的读取,返回一个pydicom.dataset.FileDataset对象. import os import ...

  3. 基于Python的DICOM文件转换教程,使用pydicom将图片存为DICOM文件。

    基于Python的DICOM文件转换教程,使用pydicom将图片存为DICOM文件. DICOM是医学图像和信息的数字化标准,可用于将医学影像数据.诊断报告等信息在医疗领域进行传输.分享和分析.而常 ...

  4. python读取dicom序列_用原生Python解析DICOM文件

    如果你想了解DICOM格式,Oleg Pianykh的<医学数字成像与通信(DICOM):实用介绍与生存指南>(DICOM:A Practical Introduction and Sur ...

  5. python读取中文文件乱码-详解Python的json文件读取及中文乱码显示问题解决方法...

    Python的json文件读取及解决中文乱码显示问题 本文实例讲述了Python实现的json文件读取及中文乱码显示问题解决方法.分享给大家供大家参考,具体如下: city.json文件的内容如下: ...

  6. python多线程读取文件夹下的文件_是否可以使用python多线程从文件夹数读取文件数,并处理这些文件以获得组合结果?...

    我认为学习使用线程的最简单方法是在concurrent.futures模块中使用ThreadPoolExecutor类,因为它比通常的同步for循环多了几行.尤其是在Python3中,但这可以适用于P ...

  7. python中读取文件编码_[转载]python中使用文件的读取编码问题

    原文链接:https://www.cnblogs.com/qianboping/p/6524420.html 今天想写个程序合并文件的,以前一直觉得python的编码解码好烦,只要处理文件合并之类的都 ...

  8. win10安装GDCM以期用pydicom读取jpeg无损压缩过的DICOM文件

    可以通过查看DICOM以下Tag来判断DICOM文件是否压缩过 可以通过RadiAnt查看DICOM文件以下Tag来判断该DICOM文件是否被压缩过: 由上图可知,该DICOM做过JPEG无损压缩,为 ...

  9. python删除文件和linux删除文件区别_使用Python批量删除文件列表

    使用Python批量删除文件列表 环境: 已知要删除的文件列表,即确定哪些文件要删除. 代码如下: #!/usr/bin/env python #coding=utf-8 #目的:本程序主要为删除给定 ...

最新文章

  1. Scrum 学习笔记
  2. Linux下第一个java程序没有成功
  3. java 默认焦点_按钮活动焦点阴影默认问题
  4. radio被选中,但是重复点击后事件不触发
  5. java string类api_java基础—String类型常用api
  6. linux下检测硬盘,【转载】linux下硬盘监控诊断工具SmartTools
  7. 简单程序所需要的简单 asp.net通用数据库访问类
  8. linux 导出软件,如何将perf(Linux工具)的输出保存到文件中?
  9. 放肆的使用UIBezierPath和CAShapeLayer画各种图形
  10. 深度学习进行语音识别的方法 如何建立自己的语音识别系统
  11. Ubuntu 16.04 x64 常用软件
  12. 滚动条禁止_平南人用了几十年的这种小东西,将全面禁止生产!你家还有某?...
  13. 【Blender】UV贴图相关学习
  14. cocos 节点坐标和世界坐标转换 个人理解与应用
  15. 如何清除matlab工作区,matlab命令窗口中可用什么命令清除工作区中的变量
  16. 怎么把分开的pdf放在一起_两个合并到一起的pdf怎么拆分?
  17. 改变人类命运的造人计划
  18. 互联网大厂面试考点————JVM
  19. 蓝牙电话之HFP-通话
  20. web_dynpro_ALV:(包ZLYTEST2)(alv 的事件只需注意一个R_PARAM就哦了)

热门文章

  1. 移动端浏览器横屏、竖屏样式
  2. Linux字符设备驱动详解七(“插件“设备树实现RGB灯驱动)
  3. 离散数学计算机专业论文,离散数学
  4. 自学Java半年,能找到工作嘛?
  5. ubuntu桌面美化mac_Ubuntu系统美化之安装Mac主题菜鸟版[配图]
  6. 【Unix/Linux】文件系统介绍 入门
  7. 力软(.net)快速开发平台的主要功能特点
  8. 解决VirtualBox分辨率太小及VBoxGuestAdditions.iso下载地址
  9. DeepFaceLive AI实时换脸软件安装流程
  10. golang:时区设置