注意:我安装了pydicom之后需要安装gdcm依赖,但我不能成功import gdcm,所以在下面的代码中都可能同时(混合)使用了pydicom和SimpleITK包读取的图像数据来做预处理。

可以成功import gdcm的同学请直接移步参考:https://www.kaggle.com/gzuidhof/full-preprocessing-tutorial

(一)简介与可视化

对于医学CT图像来说,每个人有若干张(切片).dcm类型的图像存入同一个文件夹中,分别是不同角度/部位的医学成像,可以用mango/小赛之类的看图软件看一下,也可以用matlab可视化:

clear all;
clc;
close all;
file_path='.\images\001\';
img_path_list=dir(strcat(file_path,'*.dcm'));%获取该文件夹中所有dcm格式的图像
img_num=length(img_path_list);%获取图像总数量
imagename=img_path_list(1).name;%图像名
imagemax=dicominfo(strcat(file_path,imagename));  %读取图像
imweigth=imagemax.Rows;     %DICOM水平像素数量
imhigh=imagemax.Columns;    %DICOM垂直像素数量
imagemax1=dicomread(strcat(file_path,imagename));  %读取图像
I=imagemax1;for j=2:img_num;  %逐一读取图像imagename=img_path_list(j).name;%图像名imagemax=dicomread(strcat(file_path,imagename));  %读取图像jI=imfuse(imagemax,I); %投影图像对应点取两幅图像合成值
end
I=rgb2gray(I);
m=max(max(I));
imshow(I,[]); %显示投影图像
imwrite(I,'001.png','png'); %保存投影图像

(二)读取

3D的CT不像2D图像可以直接读取 预处理 使用,可以借助python中的pydicom或者SimpleITK包来处理dicom。

SimpleITK

首先要将每个人的CT存储为一个大小为N*W*H的3D数组,其中N是这个人的.dcm切片图像数量,W*H是每张图的尺寸。

import SimpleITK as sitkdirectorypath = './images/001/'#
def get_img_array(directorypath):reader = sitk.ImageSeriesReader()reader.MetaDataDictionaryArrayUpdateOn()reader.LoadPrivateTagsOn()series_IDs = sitk.ImageSeriesReader.GetGDCMSeriesIDs(directorypath)series_ID = series_IDs[0]dicom_names = reader.GetGDCMSeriesFileNames(directorypath,series_ID)reader.SetFileNames(dicom_names)image3D = reader.Execute()imgArray = sitk.GetArrayFromImage(image3D)return image3D, imgArray 

如果想要获取某个切片slice_index的详细信息:

slice_index = 1 # for example
key = reader.GetMetaDataKeys(slice_index)
print(key)
for key in reader.GetMetaDataKeys(slice_index):value = reader.GetMetaData(slice_index,key)print("({0}) = = \"{1}\"".format(key, value))

pydicom

(1)如果使用pydicom读取目录中的多个文件(它们都是DICOM文件),不能直接:

dicom.read_dicomdir(CT_files_dir)

这样会报错:

PermissionError: [Errno 13] Permission denied:

参考:https://github.com/pydicom/pydicom/issues/322

dirname = '/some/path'
files = os.listdir(dirname)
ds_list = [dicom.read_file(os.path.join(dirname, filename)) for filename in files]

(2)如果缺失提示meta information,读取时使用“,force=True”:

ds_list = [dicom.read_file(os.path.join(dirname, filename), force=True) for filename in files]

(3)如果有的图像缺失部分meta info,则无法获取ImagePositionPatient。

此时可以注释掉第二行#slices.sort(key = lambda x: float(x.ImagePositionPatient[2])):

def load_scan(path):slices = [pydicom.read_file(path + '/' + s,force=True) for s in os.listdir(path)]#slices.sort(key = lambda x: float(x.ImagePositionPatient[2]))try:slice_thickness = np.abs(slices[0].ImagePositionPatient[2] - slices[1].ImagePositionPatient[2])except:slice_thickness = np.abs(slices[0].SliceLocation - slices[1].SliceLocation)for s in slices:s.SliceThickness = slice_thickness     return slices

(三)预处理

(1)将dcm图像的值转换为HU值

CT扫描的测量单位是亨斯菲尔德单位(HU),这是一种辐射密度的测量。CT扫描仪经过仔细校准,以准确地测量这一点。

HU(Hounsfiled Unit)值,反映了组织对X射线吸收程度。以水的吸收程度作为参考,即水的HU=0,衰减系数大于水的为正值,小于水的为负值。并以骨皮质和空气的HU值为上限和下限。

为了站在医生的角度看问题,所以必须将dcm图像的值转换为HU值。

def get_pixels_hu(slices):image = np.stack([s.pixel_array for s in slices])# Convert to int16 (from sometimes int16), # should be possible as values should always be low enough (<32k)image = image.astype(np.int16)# Set outside-of-scan pixels to 0# The intercept is usually -1024, so air is approximately 0image[image == -2000] = 0# Convert to Hounsfield units (HU)for slice_number in range(len(slices)):intercept = slices[slice_number].RescaleInterceptslope = slices[slice_number].RescaleSlopeif slope != 1:image[slice_number] = slope * image[slice_number].astype(np.float64)image[slice_number] = image[slice_number].astype(np.int16)image[slice_number] += np.int16(intercept)return np.array(image, dtype=np.int16)

因为我安装之后无法成功import gdcm,所以采用迂回战术,即同时使用SimpleITK和pydicom读取的图像sitkarrayslices

def get_pixels_hu(sitkarray, slices):#sys.exit(0)print(np.array(slices).shape) #maybe different from 'num'[num,w,h] = sitkarray.shape#print(sitkarray[0])image = np.stack([sitkarray[i] for i in range(num)])# Convert to int16 (from sometimes int16), # should be possible as values should always be low enough (<32k)image = image.astype(np.int16)# Set outside-of-scan pixels to 0# The intercept is usually -1024, so air is approximately 0image[image == -2000] = 0# Convert to Hounsfield units (HU)for slice_number in range(num): #print(slices[slice_number].RescaleIntercept,slice_number)  intercept = slices[slice_number].RescaleInterceptslope = slices[slice_number].RescaleSlope if slope != 1:image[slice_number] = slope * image[slice_number].astype(np.float64)image[slice_number] = image[slice_number].astype(np.int16)    image[slice_number] += np.int16(intercept)return np.array(image, dtype=np.int16)

(2)重采样

扫描的像素间距如果是[2.5,0.5,0.5],这表示切片之间的距离为2.5毫米。对于不同的扫描,这项参数可能是不同的。

处理这一问题的一种常见方法是将整个数据集重新采样到一定的各向同性分辨率。

重采样到一个同构分辨率1mm *1mm *1mm,以消除扫描仪分辨率的差异:

def resample(sitk_img3D, image, scan, new_spacing=[1,1,1]):# Determine current pixel spacing#spacing = np.array(sitk_img3D.GetSpacing())spacing = np.array([scan[0].SliceThickness] + scan[0].PixelSpacing, dtype=np.float32) #print(spacing)#spacing = np.array([scan[0].SliceThickness] + scan[0].PixelSpacing, dtype=np.float32)resize_factor = spacing / new_spacingnew_real_shape = image.shape * resize_factornew_shape = np.round(new_real_shape)real_resize_factor = new_shape / image.shapenew_spacing = spacing / real_resize_factorimage = scipy.ndimage.interpolation.zoom(image, real_resize_factor, mode='nearest')return image, new_spacing

(3)归一化

两个优点:

1)加快了梯度下降求最优解的速度;

2)有可能提高精度。

MIN_BOUND = -1000.0
MAX_BOUND = 400.0def normalize(image):image = (image - MIN_BOUND) / (MAX_BOUND - MIN_BOUND)image[image>1] = 1.image[image<0] = 0.return image

(4)中心化(零均值化)

意义:数据中心化和标准化在回归分析中是取消由于量纲不同、自身变异或者数值相差较大所引起的误差。
原理:数据标准化:是指数值减去均值,再除以标准差;

数据中心化:是指变量减去它的均值。

目的:通过中心化和标准化处理,得到均值为0,标准差为1的服从标准正态分布的数据。

PIXEL_MEAN = 0.25 # To determine this mean you simply average all images in the whole dataset. If that sounds like a lot of work, we found this to be around 0.25 in the LUNA16 competition.
def zero_center(image):image = image - PIXEL_MEANreturn image

函数调用:

sitk_img3D, sitk_img = get_img_array(directorypath)
dicom_img = load_scan(directorypath)
img_pixels = get_pixels_hu(sitk_img, dicom_img)
pix_resampled, spacing = resample(sitk_img3D, img_pixels, dicom_img, [1,1,1])

参考:

https://www.cnblogs.com/jxblog/p/12010354.html

https://github.com/pydicom/pydicom/issues/322

https://www.jianshu.com/p/f98635abac65

https://www.kaggle.com/gzuidhof/full-preprocessing-tutorial

https://blog.csdn.net/weixin_37536336/article/details/109386431

https://blog.csdn.net/csdnxiekai/article/details/109448128

使用pydicom和SimpleITK预处理dicom文件相关推荐

  1. pydicom和simpleitk读写dicom图像元信息

    一.pydicom 1.读取元信息 import pydicomimg_path = '.\001.dcm' dataset = pydicom.dcmread(img_path) # <cla ...

  2. pyDicom基本使用操作dicom文件

    dicom文件前面已经介绍,那么我们需要读和写文件信息,我发现python中有pydicom这个好用的库,可以帮助我们方便的操作,据说比java的会方便很多. pydicom的网站里面介绍的比较详细  ...

  3. dicom文件_图像识别 | 使用Python对医学Dicom文件的预处理(含代码)

    前沿 在处理医学图像时,常常会遇到以Dicom格式保存的医学图像,如CT.MRI等.Dicom文件是需要专门的软件或者通过编程,应用相应的库进行处理.为了能够更好地服务下游任务,例如分割或检测腹腔CT ...

  4. python dicom 器官分割_图像识别 | 使用Python对医学Dicom文件的预处理(含代码)

    前沿 在处理医学图像时,常常会遇到以Dicom格式保存的医学图像,如CT.MRI等.Dicom文件是需要专门的软件或者通过编程,应用相应的库进行处理.为了能够更好地服务下游任务,例如分割或检测腹腔CT ...

  5. DICOM文件读取及PNG格式图片展示

    import globimport pydicom import matplotlib.pyplot as plt import numpy as np import os import multip ...

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

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

  7. pydicom读取头文件_python读取dicom图像(SimpleITK和dicom包实现)_愿十四亿神州尽舜尧-CSDN博客_python读取dicom...

    1. 用SimpleITK读取dicom序列:import SimpleITK as sitkimport numpy as npimg_path='F:\\dataset\\pancreas\\Ou ...

  8. CT图像分割dicom文件与nii.gz文件预处理----窗宽(window width)和窗位(window level)的设置

    最近被CT图像的值弄得很烦,记录一下. CT分割也是个很热门的话题,病灶分割,器官分割等. CT图像大多是两种格式.dcm和nii.gz,当然也有别的,但这里我就不说别的,就说这两种常用的. .dcm ...

  9. 使用python(pydicom)读取Dicom文件并且转换成png

    这篇主要讲怎么处理dicom格式的医学影像文件,并且转换成png,这样利于我们对图像进行处理. pydicom 目前取代了17年前的dicom库,更加的便捷 导入需要的模块,如果没安装,都可以用pip ...

最新文章

  1. python 实现结构树模式显示目录下文件
  2. 开启注册丨EMNLP 2021论文预讲会,邀你一起共赏自然语言处理学术盛宴(日程全公开)...
  3. java青蛙青蛙跳井_公务员行测技巧:青蛙跳井问题
  4. 去除tab、空格、回车符等使用replace语句
  5. 牛客网_PAT乙级_1022挖掘机技术哪家强(20)【class vector sort排序、删除重复元素】
  6. J-Link该如何升级固件?
  7. 使用DBUtils实现增删改查
  8. docker制作容器(待更新)
  9. 常见python爬虫框架_python的爬虫框架有哪些
  10. 解读《西厢记》——基于人脑的句法分析
  11. 电脑上的记账本,添加无限个账户记录
  12. jQuery实现购物车计算价格统计功能
  13. Laplacian eigenmap 拉普拉斯特征映射
  14. mysql flush logs时出现ERROR 1105
  15. 杭州保俶塔实验机器人_资讯 | 智慧与挑战!2017年西湖区中小学生科技节智能机器人比赛成绩出炉啦...
  16. 个人收款码和个人经营收款码的区别,你知道吗
  17. 从阿尔法元到人工智能会取代你的工作吗?
  18. 网络协议 交换机基础
  19. 华秦科技通过注册:拟募资12.8亿 预计年营收超5亿
  20. ad怎么测量pcb尺寸_一招教你学会使用AD更改PCB板子尺寸!

热门文章

  1. gear s3刷android wear,教程:三星Gear S3/Gear S3 classic智能手表如何刷机?
  2. php tp3.2 添加表内容,数据创建 · ThinkPHP3.2.3完全开发手册 · 看云
  3. 在Linux系统实现PTP时钟同步,查看网卡信息后发现网卡不支持PTP软硬件时间戳
  4. 双语web阅读器+书城设计与实现
  5. JVM配置、监控、调优
  6. 【基础篇】各类语言的变量命名规则
  7. Python爬虫 自动爬取图片并保存
  8. windows phonegap android,phonegap windows 安装
  9. 士兵队列训练问题 (HDU - 1276)
  10. 邮箱开启授权码(配置邮件客户端)