Python 处理医学影像学中的DICOM

DICOMDICOM(Digital Imaging and Communications in Medicine)即医学数字成像和通信,是医学图像和相关信息的国际标准(ISO 12052)。它定义了质量能满足临床需要的可用于数据交换的医学图像格式,可用于处理、存储、打印和传输医学影像信息。DICOM可以便捷地交换于两个满足DICOM格式协议的工作站之间。目前该协议标准不仅广泛应用于大型医院,而且已成为小型诊所和牙科诊所医生办公室的标准影像阅读格式。

这里写图片描述

DICOM被广泛应用于放射医疗、心血管成像以及放射诊疗诊断设备(X射线,CT,核磁共振,超声等),并且在眼科和牙科等其它医学领域得到越来越深入广泛的应用。在数以万计的在用医学成像设备中,DICOM是部署最为广泛的医疗信息标准之一。当前大约有百亿级符合DICOM标准的医学图像用于临床使用。

目前,越来越多的DICOM应用程序和分析软件被运用于临床医学,促使越来越多的编程语言开发出支持DICOM API的框架。今天就让我来介绍一下Python语言下支持的DICOM模块,以及如何完成基本DICOM信息分析和处理的编程方法。


Pydicom


Pydicom是一个处理DICOM文件的纯Python软件包。它可以通过非常容易的“Pythonic”的方式来提取和修改DICOM数据,修改后的数据还会借此生成新的DICOM文件。作为一个纯Python包,Pydicom可以在Python解释器下任何平台运行,除了必须预先安装Numpy模块外,几乎无需其它任何配置要求。其局限性之一是无法处理压缩像素图像(如JPEG),其次是无法处理分帧动画图像(如造影电影)。

这里写图片描述


SimpleITK


Insight Segmentation and Registration Toolkit (ITK)是一个开源、跨平台的框架,可以提供给开发者增强功能的图像分析和处理套件。其中最为著名的就是SimpleITK,是一个简化版的、构建于ITK最顶层的模块。SimpleITK旨在易化图像处理流程和方法。

这里写图片描述


PIL


Python Image Library (PIL) 是在Python环境下不可缺少的图像处理模块,支持多种格式,并提供强大的图形与图像处理功能,而且API却非常简单易用。


OpenCV


OpenCV的全称是:Open Source Computer Vision Library。OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

这里写图片描述


下面就让我以实际Python代码来演示如何编程处理心血管冠脉造影DICOM图像信息。

1. 导入主要框架:SimpleITK、pydicom、PIL、cv2和numpy

import SimpleITK as sitk
from PIL import Image
import pydicom
import numpy as np
import cv2

2. 应用SimpleITK框架来读取DICOM文件的矩阵信息。如果DICOM图像是三维螺旋CT图像,则帧参数则代表CT扫描层数;而如果是造影动态电影图像,则帧参数就是15帧/秒的电影图像帧数。

def loadFile(filename):ds = sitk.ReadImage(filename)img_array = sitk.GetArrayFromImage(ds)frame_num, width, height = img_array.shapereturn img_array, frame_num, width, height

3. 应用pydicom来提取患者信息。

def loadFileInformation(filename):information = {}ds = pydicom.read_file(filename)    information['PatientID'] = ds.PatientIDinformation['PatientName'] = ds.PatientNameinformation['PatientBirthDate'] = ds.PatientBirthDateinformation['PatientSex'] = ds.PatientSexinformation['StudyID'] = ds.StudyIDinformation['StudyDate'] = ds.StudyDateinformation['StudyTime'] = ds.StudyTimeinformation['InstitutionName'] = ds.InstitutionNameinformation['Manufacturer'] = ds.Manufacturerinformation['NumberOfFrames'] = ds.NumberOfFrames    return information

4. 应用PIL来检查图像是否被提取。

def showImage(img_array, frame_num = 0):img_bitmap = Image.fromarray(img_array[frame_num])return img_bitmap

5. 采用CLAHE (Contrast Limited Adaptive Histogram Equalization)技术来优化图像。

def limitedEqualize(img_array, limit = 4.0):img_array_list = []for img in img_array:clahe = cv2.createCLAHE(clipLimit = limit, tileGridSize = (8,8))img_array_list.append(clahe.apply(img))img_array_limited_equalized = np.array(img_array_list)return img_array_limited_equalized

这一步对于整个图像处理起到很重要的作用,可以根据不同的原始DICOM图像的窗位和窗宽来进行动态调整,以达到最佳的识别效果。

最后应用OpenCV的Python框架cv2把每帧图像组合在一起,生成通用视频格式。

def writeVideo(img_array):frame_num, width, height = img_array.shapefilename_output = filename.split('.')[0] + '.avi'    video = cv2.VideoWriter(filename_output, -1, 16, (width, height))    for img in img_array:video.write(img)video.release()

VTK加载DICOM数据


import vtk  
from vtk.util import numpy_support  
import numpy  PathDicom = "./dir_with_dicom_files/"  
reader = vtk.vtkDICOMImageReader()  
reader.SetDirectoryName(PathDicom)  
reader.Update()  # Load dimensions using `GetDataExtent`  
_extent = reader.GetDataExtent()  
ConstPixelDims = [_extent[1]-_extent[0]+1, _extent[3]-_extent[2]+1, _extent[5]-_extent[4]+1]  # Load spacing values  
ConstPixelSpacing = reader.GetPixelSpacing()  # Get the 'vtkImageData' object from the reader  
imageData = reader.GetOutput()  
# Get the 'vtkPointData' object from the 'vtkImageData' object  
pointData = imageData.GetPointData()  
# Ensure that only one array exists within the 'vtkPointData' object  
assert (pointData.GetNumberOfArrays()==1)  
# Get the `vtkArray` (or whatever derived type) which is needed for the `numpy_support.vtk_to_numpy` function  
arrayData = pointData.GetArray(0)  # Convert the `vtkArray` to a NumPy array  
ArrayDicom = numpy_support.vtk_to_numpy(arrayData)  
# Reshape the NumPy array to 3D using 'ConstPixelDims' as a 'shape'  
ArrayDicom = ArrayDicom.reshape(ConstPixelDims, order='F')  

PYDICOM加载DICOM数据:
可以在https://github.com/darcymason/pydicom的test里面看怎么用代码。


import dicom  
import os  
import numpy  PathDicom = "./dir_with_dicom_series/"  
lstFilesDCM = []  # create an empty list  
for dirName, subdirList, fileList in os.walk(PathDicom):  for filename in fileList:  if ".dcm" in filename.lower():  # check whether the file's DICOM  lstFilesDCM.append(os.path.join(dirName,filename))  # Get ref file  
RefDs = dicom.read_file(lstFilesDCM[0])  # Load dimensions based on the number of rows, columns, and slices (along the Z axis)  
ConstPixelDims = (int(RefDs.Rows), int(RefDs.Columns), len(lstFilesDCM))  # Load spacing values (in mm)  
ConstPixelSpacing = (float(RefDs.PixelSpacing[0]), float(RefDs.PixelSpacing[1]), float(RefDs.SliceThickness))  # The array is sized based on 'ConstPixelDims'  
ArrayDicom = numpy.zeros(ConstPixelDims, dtype=RefDs.pixel_array.dtype)  # loop through all the DICOM files  
for filenameDCM in lstFilesDCM:  # read the file  ds = dicom.read_file(filenameDCM)  # store the raw image data  ArrayDicom[:, :, lstFilesDCM.index(filenameDCM)] = ds.pixel_array  

转换VTK built-in types to SimpleITK/ITK built-ins and vice-versa


import vtk  
import SimpleITK  dctITKtoVTK = {SimpleITK.sitkInt8: vtk.VTK_TYPE_INT8,  SimpleITK.sitkInt16: vtk.VTK_TYPE_INT16,  SimpleITK.sitkInt32: vtk.VTK_TYPE_INT32,  SimpleITK.sitkInt64: vtk.VTK_TYPE_INT64,  SimpleITK.sitkUInt8: vtk.VTK_TYPE_UINT8,  SimpleITK.sitkUInt16: vtk.VTK_TYPE_UINT16,  SimpleITK.sitkUInt32: vtk.VTK_TYPE_UINT32,  SimpleITK.sitkUInt64: vtk.VTK_TYPE_UINT64,  SimpleITK.sitkFloat32: vtk.VTK_TYPE_FLOAT32,  SimpleITK.sitkFloat64: vtk.VTK_TYPE_FLOAT64}  
dctVTKtoITK = dict(zip(dctITKtoVTK.values(),   dctITKtoVTK.keys()))  def convertTypeITKtoVTK(typeITK):  if typeITK in dctITKtoVTK:  return dctITKtoVTK[typeITK]  else:  raise ValueError("Type not supported")  def convertTypeVTKtoITK(typeVTK):  if typeVTK in dctVTKtoITK:  return dctVTKtoITK[typeVTK]  else:  raise ValueError("Type not supported")  

VTK-SimpleITK绘制数据


#!/usr/bin/python  import SimpleITK as sitk  
import vtk  
import numpy as np  from vtk.util.vtkConstants import *  def numpy2VTK(img,spacing=[1.0,1.0,1.0]):  # evolved from code from Stou S.,  # on http://www.siafoo.net/snippet/314  importer = vtk.vtkImageImport()  img_data = img.astype('uint8')  img_string = img_data.tostring() # type short  dim = img.shape  importer.CopyImportVoidPointer(img_string, len(img_string))  importer.SetDataScalarType(VTK_UNSIGNED_CHAR)  importer.SetNumberOfScalarComponents(1)  extent = importer.GetDataExtent()  importer.SetDataExtent(extent[0], extent[0] + dim[2] - 1,  extent[2], extent[2] + dim[1] - 1,  extent[4], extent[4] + dim[0] - 1)  importer.SetWholeExtent(extent[0], extent[0] + dim[2] - 1,  extent[2], extent[2] + dim[1] - 1,  extent[4], extent[4] + dim[0] - 1)  importer.SetDataSpacing( spacing[0], spacing[1], spacing[2])  importer.SetDataOrigin( 0,0,0 )  return importer  def volumeRender(img, tf=[],spacing=[1.0,1.0,1.0]):  importer = numpy2VTK(img,spacing)  # Transfer Functions  opacity_tf = vtk.vtkPiecewiseFunction()  color_tf = vtk.vtkColorTransferFunction()  if len(tf) == 0:  tf.append([img.min(),0,0,0,0])  tf.append([img.max(),1,1,1,1])  for p in tf:  color_tf.AddRGBPoint(p[0], p[1], p[2], p[3])  opacity_tf.AddPoint(p[0], p[4])  # working on the GPU  # volMapper = vtk.vtkGPUVolumeRayCastMapper()  # volMapper.SetInputConnection(importer.GetOutputPort())  # # The property describes how the data will look  # volProperty =  vtk.vtkVolumeProperty()  # volProperty.SetColor(color_tf)  # volProperty.SetScalarOpacity(opacity_tf)  # volProperty.ShadeOn()  # volProperty.SetInterpolationTypeToLinear()  # working on the CPU  volMapper = vtk.vtkVolumeRayCastMapper()  compositeFunction = vtk.vtkVolumeRayCastCompositeFunction()  compositeFunction.SetCompositeMethodToInterpolateFirst()  volMapper.SetVolumeRayCastFunction(compositeFunction)  volMapper.SetInputConnection(importer.GetOutputPort())  # The property describes how the data will look  volProperty =  vtk.vtkVolumeProperty()  volProperty.SetColor(color_tf)  volProperty.SetScalarOpacity(opacity_tf)  volProperty.ShadeOn()  volProperty.SetInterpolationTypeToLinear()  # Do the lines below speed things up?  # pix_diag = 5.0  # volMapper.SetSampleDistance(pix_diag / 5.0)      # volProperty.SetScalarOpacityUnitDistance(pix_diag)   vol = vtk.vtkVolume()  vol.SetMapper(volMapper)  vol.SetProperty(volProperty)  return [vol]  def vtk_basic( actors ):  """ Create a window, renderer, interactor, add the actors and start the thing Parameters ---------- actors :  list of vtkActors Returns ------- nothing """       # create a rendering window and renderer  ren = vtk.vtkRenderer()  renWin = vtk.vtkRenderWindow()  renWin.AddRenderer(ren)  renWin.SetSize(600,600)  # ren.SetBackground( 1, 1, 1)  # create a renderwindowinteractor  iren = vtk.vtkRenderWindowInteractor()  iren.SetRenderWindow(renWin)  for a in actors:  # assign actor to the renderer  ren.AddActor(a )  # render  renWin.Render()  # enable user interface interactor  iren.Initialize()  iren.Start()  #####  filename = 'toto.nii.gz'  img = sitk.ReadImage( filename ) # SimpleITK object  
data = sitk.GetArrayFromImage( img ) # numpy array  from scipy.stats.mstats import mquantiles  
q = mquantiles(data.flatten(),[0.7,0.98])  
q[0]=max(q[0],1)  
q[1] = max(q[1],1)  
tf=[[0,0,0,0,0],[q[0],0,0,0,0],[q[1],1,1,1,0.5],[data.max(),1,1,1,1]]  actor_list = volumeRender(data, tf=tf, spacing=img.GetSpacing())  vtk_basic(actor_list)  

下面一个不错的软件:
https://github.com/bastula/dicompyler
还有一个python的库mudicom,https://github.com/neurosnap/mudicom


import mudicom  
mu = mudicom.load("mudicom/tests/dicoms/ex1.dcm")  # returns array of data elements as dicts  
mu.read()  # returns dict of errors and warnings for DICOM  
mu.validate()  # basic anonymization  
mu.anonymize()  
# save anonymization  
mu.save_as("dicom.dcm")  # creates image object  
img = mu.image # before v0.1.0 this was mu.image()  
# returns numpy array  
img.numpy # before v0.1.0 this was mu.numpy()  # using Pillow, saves DICOM image  
img.save_as_pil("ex1.jpg")  
# using matplotlib, saves DICOM image  
img.save_as_plt("ex1_2.jpg")  

本文转自:

http://mp.weixin.qq.com/s?__biz=MzAxOTk4NTIwMw==&mid=2247483968&idx=1&sn=2844930d81f3e1f45260338dae21d8ea&chksm=9c3fe41cab486d0aa9d03a6494865c0ffdbb0e878f4804227a73d2d403382432fe22e9c03b71&mpshare=1&scene=23&srcid=0122xHKRmyLclSvbojaS1ICX##

http://blog.csdn.net/langb2014/article/details/54667905#

http://www.jianshu.com/p/df64088e9b6b

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/246868.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DICOM的常用Tag分类和说明

本文转自:http://blog.csdn.net/inter_peng/article/details/46513847 1. 前言: 基于DICOM3.0标准的医学图像中,每一张图像中都携带着许多的信息,这些信息主要可以分为Patient, Study, Series和Image四类。每一个DICOM T…

基于CNN的性别、年龄识别及Demo实现

一、相关理论 本篇博文主要讲解2015年一篇paper《Age and Gender Classification using Convolutional Neural Networks》paper的创新点在哪里。难道是因为利用CNN做年龄和性别分类的paper很少吗?网上搜索了一下,性别预测,以前很多都是用SVM算…

Faster R-CNN的安装及测试(Python版本和Matlab版本)

rbg的Python版本 一、拉取源码 git clone --recursive https://github.com/rbgirshick/py-faster-rcnn.git 拉取完成后,在/home/cmwang/目录下增加了py-faster-rcnn文件夹【cmwang是我的ubuntu用户名】 二、安装依赖 sudo apt-get install python-opencvsudo pip…

Faste R-CNN的安装及测试

一、拉取源码 下载 fast-rcnn 因下载解压后 caffe-fast-rcnn是空文件夹,故需要单独下 caffe-fast-rcnn-bcd9b4eadc7d8fbc433aeefd564e82ec63aaf69c.zip unzip caffe-fast-rcnn-bcd9b4eadc7d8fbc433aeefd564e82ec63aaf69c.zip cp ./caffe-fast-rcnn-bcd9b4eadc7d8…

6 areas of artificial intelligence to watch closely 需要密切关注的六大人工智能/机器学习领域

近段时间,有许多关于人工智能公认定义的争论。有些人认为人工智能就是“认知计算”或是“机器智能”,而另一些人则把它与“机器学习”的概念混淆了。然而,人工智能并不是特指某种技术,它实际上是一个由多门学科组成的广阔领域&…

2016 亚洲共识指南:肺结节的评估

2016 年 2 月,亚洲肺部疾病和胸外科多学科专家小组在美国胸科医师学会(ACCP)制定的肺结节评估指南的基础上结合亚洲患者的自身特点制订了亚洲肺结节患者的评估指南。 亚洲肺结节的评估与 APCC 指南中所指出的重要注意事项大致相同。但该指南…

Ubuntu 15.04 安装TensorFlow(源码编译) 及测试梵高作画

介绍Google的TensorFlow机器学习开源库,在UbuntuKylin上的安装和和源码编译。 原始官方文档参见:http://www.tensorflow.org. 本电脑配置如下: 3.19.0-15-generic #15-Ubuntu x86_64 GNU/Linux NVIDIA Corporation GK110BGL [Tesla K40c] …

Ubuntu 15.04 安装 boost-python

1. 安装依赖库 sudo apt-get install python-dev sudo apt-get install mpi-default-dev #安装mpi库 sudo apt-get install libicu-dev #支持正则表达式的UNICODE字符集 sudo apt-get install …

python 常见问题汇总(待续)

1. No module named skimage pip install scikit-image --upgrade 2. No module named dicom sudo pip install pydicom 3. python name ‘os’ is not defined import os This will import the python’s module os, which apparently is used later in the code of your m…

如何将 ipynb 发布到 blog 中(html, markdown格式)

相关文章链接 如何向IPython Notebook中导入.py文件 如何将 ipynb 发布到 blog 中(html, markdown格式) Introducing IPython Notebook Beginner’s IPython Notebook Tutorial Example notebook showing how to do statistics in IPython Notebook next generation slide…

HP Z840 工作站配sSAS Raid 安装 Ubuntu 16.04 系统

惠普Z840工作站配SAS RAID安装win7系统加载驱动 安装ubuntu的最低版本版本要求是01.25,请更新到官方最新的02.31测试 1. BIOS系统更新 1. 准备好一个空的U盘,格式化成FAT32,在U盘上建立\Hewlett-Packard\BIOS\New 2. 下载链接http://ftp.hp…

Ubuntu SSH Algorithm negotiation failed

问题 解决方法 chmod 777 /etc/ssh/sshd_configgedit /etc/ssh/sshd_config添加如下 Ciphers aes128-cbc,aes192-cbc,aes256-cbc,aes128-ctr,aes192-ctr,aes256-ctr,3des-cbc,arcfour128,arcfour256,arcfour,blowfish-cbc,cast128-cbcMACs hmac-md5,hmac-sha1,umac-64openssh.…

不同matlab版本所支持的gcc g+版本

问题 关于 GCC 和 G 版本问题 Matlab 2014a gcc/g 4.7.x, Matlab 2016a gcc/g 4.9.x Matlab 2017a gcc/g 4.9.x Ubuntu 15.04 gcc/g 4.9.x, Ubuntu 16.04 gcc/g 5.4.x 原则上Matlab需要和Ubuntu版本一致,由于CUDA 8只支持16.04,而且需要GCC 5.4.x 进行编译&#…

Linux系统中添加硬盘,并挂载到已有的目录,比如/home/user

备份用户下数据 cd home ls newuser tar cvf newuser.tar newuser  #创建一个tar归档 rm -rf newuser mkdir newuser备注:newuser为home下的用户。 分区和挂载 #查看硬盘分区 fdisk -l#分区 fdisk /dev/sdbCommand (m for help):m#新建一个分区 Comman…

高性能Numpy/Scipy加速:使用Intel MKL和Intel Compilers或OpenBLAS(待续)

Numpy/Scipy加速:使用Intel MKL和Intel Compilers 1.获取Intel Parallel Studio XE Intel免费软件工具提供免费的软件包,其中包括完整的Intel编译器和计算库及其激活码,软件和激活码一一对应。注意需要使用教育邮箱注册,否则不予通过。 2.安装…

Linux 安装卸载软件及管理软件仓库

软件仓库 Linux的软件包都存放在一个地方,叫做软件仓库,repository。 因为Linux是在Windows之后诞生的(1991年前后),所以为了避免Windows的这个“弊端”,Linux选择创建一个集中存放软件的地方。 当然了&a…

Linux 终端配置

一般Linux中的配置文件大多以点开头,而且多以rc结尾。比如vim的配置文件 .vimrc,bash shell的配置文件.bashrc,等等。 像这样的配置文件,如果用ls -l命令是列不出来的,需要用ls -a来列出。 “rc”,它是“…

Caffe2 Compilation Error gflags.cc' is being linked both statically and dynamically into this execut

问题描述 python -c from caffe2.python import core 2>/dev/null && echo "Success" || echo "Failure" 出现这个问题 ERROR: something wrong with flag flagfile in file /home/bids/softwares/gflags-2.2.0/src/gflags.cc. One possibil…

值得关注的医疗 AI 公司(待续)

医疗成像 Clearview Diagnostics 是一家开发辅助医生诊断疾病的工具的 AI 软件公司。该公司最初的重点是乳腺癌。 Butterfly Network 是一家医疗成像技术公司,该公司创建了一个集成了深度学习技术的便携式医疗成像设备,帮助缺乏医疗机构或医生不够专业的…

caffe2 介绍

Caffe2的特性 Caffe2框架可以通过一台机器上的多个GPU或具有一个及多个GPU的多台机器来进行分布式训练。 也可以在iOS系统、Android系统和树莓派(Raspberry Pi)上训练和部署模型。只需要运行几行代码即可调用Caffe2中预先训练好的Model Zoo模型。Caffe2…