现如今针对医学核磁共振MR影像的研究越来越多,但由于各种原因,从各个医院收集原始患者核磁共振影像BMP文件的难度非常大。而患者的原始DICOM文件相较MR文件更易收集,所以我们提出使用Python实现DICOM批量转换为jpg、png图像。
1.安装库
pip install numpy
pip install cv2
pip install simpleitk
pip install os
2.定义一个DICOM转JPG的函数
该函数读取图像的像素值信息,并转换为数组形式,在归一化、转换至0-255像素值区间内之后重新转换为三通道的RGB图。
# 定义dicom to jpg转换函数
def dicom2jpg(img, low_window, high_window, save_path):
"""
:param img: dicom图像的像素值信息
:param low_window: dicom图像像素值的最低值
:param high_window: dicom图像像素值的最高值
:param save_path: 新生成的jpg图片的保存路径
:return:
"""
oldimg = np.array([low_window * 1., high_window * 1.]) # 将像素值转换为array
newimg = (img - oldimg[0]) / (oldimg[1] - oldimg[0]) # 将像素值归一化0-1
newimg = (newimg * 255).astype('uint8') # 再转换至0-255,且将编码方式由原来的unit16转换为unit8
# 将单通道转换成三通道
img_out = np.zeros([newimg.shape[0], newimg.shape[1], 3])
img_out[:, :, 0] = newimg
img_out[:, :, 1] = newimg
img_out[:, :, 2] = newimg
# 用cv2写入图像指令,保存jpg即可
cv2.imwrite(save_path, img_out, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
3.批量转换
我们假设目标影像文件是存放在三级文件夹中,当然二级文件夹和更多级的文件夹思路相同。
我们首先需要输入影像文件存储的文件夹。
input_root = r'C:\Users\ediso\Desktop\shizhuang\shizhuang'
并输入想要转入的目标文件夹。
output_root = r'C:\Users\ediso\Desktop\out'
接着便可以实现DICOM文件的批量转换了。
if __name__ == '__main__':
input_root = r'C:\Users\ediso\Desktop\shizhuang\shizhuang'
dir_list = os.listdir(input_root) # 打开文件夹中的图像的文件名,作为列表返回
output_root = r'C:\Users\ediso\Desktop\out'
if not os.path.exists(output_root):
os.makedirs(output_root)
# 开始遍历日期文件夹下的每个子文件夹
print('The 1th class dir ' + str(input_root) + ' have ' + str(len(dir_list)) + ' files' + '*' * 50)
for _dir in dir_list:
if _dir != 'VERSION':
dir_in1_path = os.path.join(input_root, _dir)
dir_out1_path = os.path.join(output_root, _dir)
if not os.path.exists(dir_out1_path):
os.makedirs(dir_out1_path)
dir_in2_path_list = os.listdir(dir_in1_path)
print('The 2th class dir '+str(_dir)+' have ' + str(len(dir_in2_path_list))+' files'+'*'*50)
# debug 使用
j = 1
for i in dir_in2_path_list:
if i != 'VERSION':
document = os.path.join(dir_in1_path, i)
# countname = str(count) # 将设置的变量数字1,转换为字符串,作为名称使用
countfullname = _dir + '-' +str(j) + '.jpg'
output_jpg_path = os.path.join(dir_out1_path, countfullname) # 设置保存每张图片的路径
j = j+1
image = sitk.ReadImage(document)
img_array = sitk.GetArrayFromImage(image)
img_array = np.squeeze(img_array, axis=0)
high = np.max(img_array) # 找到最大的
low = np.min(img_array)# 找到最小的
print(str(_dir)+'/'+str(i)+' have max and min pixel are:'+str(high)+' and '+str(low))
# 调用函数,开始转换
dicom2jpg(img_array, low, high, output_jpg_path)
# count += 1 # 为下一张图像的名称作准备,加1变成2
4.完整代码
在完整代码中,我们为了防止整个程序因为某些未知问题报错添加了一个防报错机制。
import numpy as np
import cv2
import os
import SimpleITK as sitk
# 定义dicom to jpg转换函数
def dicom2jpg(img, low_window, high_window, save_path):
"""
:param img: dicom图像的像素值信息
:param low_window: dicom图像像素值的最低值
:param high_window: dicom图像像素值的最高值
:param save_path: 新生成的jpg图片的保存路径
:return:
"""
oldimg = np.array([low_window * 1., high_window * 1.]) # 将像素值转换为array
newimg = (img - oldimg[0]) / (oldimg[1] - oldimg[0]) # 将像素值归一化0-1
newimg = (newimg * 255).astype('uint8') # 再转换至0-255,且将编码方式由原来的unit16转换为unit8
# 将单通道转换成三通道
img_out = np.zeros([newimg.shape[0], newimg.shape[1], 3])
img_out[:, :, 0] = newimg
img_out[:, :, 1] = newimg
img_out[:, :, 2] = newimg
# 用cv2写入图像指令,保存jpg即可
cv2.imwrite(save_path, img_out, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
if __name__ == '__main__':
input_root = r'D:\DeepLearning\cervical\BianqueNet+\input\dicom\1'
dir_list = os.listdir(input_root) # 打开文件夹中的图像的文件名,作为列表返回
output_root = r'D:\DeepLearning\cervical\BianqueNet+\input\dicom_out'
if not os.path.exists(output_root):
os.makedirs(output_root)
# 开始遍历日期文件夹下的每个子文件夹
print('The 1th class dir ' + str(input_root) + ' have ' + str(len(dir_list)) + ' files' + '*' * 50)
for _dir in dir_list:
try:
if _dir != 'VERSION' and _dir != '.DS_Store':
dir_in1_path = os.path.join(input_root, _dir)
dir_out1_path = os.path.join(output_root, _dir)
if not os.path.exists(dir_out1_path):
os.makedirs(dir_out1_path)
dir_in2_path_list = os.listdir(dir_in1_path)
print('The 2th class dir '+str(_dir)+' have ' + str(len(dir_in2_path_list))+' files'+'*'*50)
# debug 使用
j = 1
for i in dir_in2_path_list:
if i != 'VERSION'and i != '.DS_Store':
document = os.path.join(dir_in1_path, i)
# countname = str(count) # 将设置的变量数字1,转换为字符串,作为名称使用
countfullname = _dir + '-' +str(j) + '.jpg'
output_jpg_path = os.path.join(dir_out1_path, countfullname) # 设置保存每张图片的路径
j = j+1
image = sitk.ReadImage(document)
img_array = sitk.GetArrayFromImage(image)
img_array = np.squeeze(img_array, axis=0)
high = np.max(img_array) # 找到最大的
low = np.min(img_array)# 找到最小的
print(str(_dir)+'/'+str(i)+' have max and min pixel are:'+str(high)+' and '+str(low))
# 调用函数,开始转换
dicom2jpg(img_array, low, high, output_jpg_path)
except Exception as e:
print("---------------------------------------------------------the conversion of " + str(
document) + " is failed!")
pass
continue