Python处理DICOM(02)--DICOM转PNG

一、基础环境准备

使用pip install XXX命令安装pydicom,SimpleITK,NumPy,opencv-python,tqdm几个模块。

pydicom:pydicom is a pure python package for working with DICOM files. It was made for inspecting and modifying DICOM data in an easy "pythonic" way. The modifications can be written again to a new file.

SimpleITK:Provide an abstraction layer to ITK that enables developers and users to access the powerful features of the InsightToolkit in a more simplified manner.

NumPy:一个用python实现的科学计算,包括:1、一个强大的N维数组对象Array;2、比较成熟的(广播)函数库;3、用于整合C/C++和Fortran代码的工具包;4、实用的线性代数、傅里叶变换和随机数生成函数。numpy和稀疏矩阵运算包scipy配合使用更加方便。

opencv-python:The aim of this repository is to provide means to package each new OpenCV release for the most used Python versions and platforms.OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。 [1]  它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

tqdm:Tqdm 是 Python 进度条库,可以在 Python 长循环中添加一个进度提示信息。用户只需要封装任意的迭代器,是一个快速、扩展性强的进度条工具库。

二、正式编码

1.引入需要的库:

import os
import SimpleITK
import pydicom
import numpy as np
import cv2
from tqdm import tqdm

2.定义功能函数:

def is_dicom_file(filename):
    '''
    判断某文件是否是dicom格式的文件
    :param filename: dicom文件的路径
    :return:
    '''
    file_stream = open(filename, 'rb')
    file_stream.seek(128)
    data = file_stream.read(4)
    file_stream.close()
    if data == b'DICM':
        return True
    return False

def load_patient(src_dir):
    '''
    读取某文件夹内的所有dicom文件
    :param src_dir: diocm文件夹的路径
    :return: dicom list
    '''
    files = os.listdir(src_dir)
    slices = []
    for s in files:
        if is_dicom_file(src_dir + '/' + s):
            instance = pydicom.read_file(src_dir + '/' + s)
            slices.append(instance)
    slices.sort(key=lambda x: int(x.InstanceNumber))
    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

def get_pixels_hu_by_simpleitk(dicom_dir):
    '''
    读取某文件夹内的所有文件,并提取像素值(-4000,4000)
    :param dicom_dir: dicom文件夹路径
    :return: image array
    '''
    reader = SimpleITK.ImageSeriesReader()
    series_IDs = reader.GetGDCMSeriesIDs(dicom_dir)
    print(series_IDs)
    dicom_names = reader.GetGDCMSeriesFileNames(dicom_dir, series_IDs[1])
    reader.SetFileNames(dicom_names)
    image = reader.Execute()
    img_array = SimpleITK.GetArrayFromImage(image)
    img_array[img_array == -2000] = 0
    return img_array

def normalize_hu(image):
    '''
    将输入图像的像素值(-4000~4000)归一化到0~1之间
    :param image: 输入的图像数组
    :return: 归一化处理后的图像数组
    '''
    MIN_BOUND = -1000.0
    MAX_BOUND = 400.0
    image = (image - MIN_BOUND) / (MAX_BOUND - MIN_BOUND)
    image[image > 1] = 1.
    image[image < 0] = 0.
    return image

3.调用

if __name__ == '__main__':
    dicom_dir = './data/dicom_demo/'
    #读取dicom文件的元数据(dicom tags)
    slices = load_patient(dicom_dir)
    print('The number of dicom files:', len(slices))
    #提取dicom文件中的像素值
    image = get_pixels_hu_by_simpleitk(dicom_dir)
    #print(len(image))
    for i in tqdm(range(image.shape[0])):
        img_path = "./temp_dir/dicom_2_png/img/" + str(i).rjust(4, '0') + "_i.png"
        #将像素归一化到[0,1]区间
        org_img = normalize_hu(image[i])
        #保存图像数组问灰度图(.png)
        cv2.imwrite(img_path, org_img * 255)

你可能感兴趣的:(医疗信息化)