【Python医学影像从超详细入门】1.医学影像与勾画文件查看(dicom nii nii.gz nrrd)
常见的医学影像格式有dicom nii nii.gz nrrd
建议将原始影像转换为nii.gz格式,便于处理且存储空间占用更小。
本文将展示使用python查看四种常用格式的医学影像的方法
(原始影像支持dicom nii nii.gz nrrd 勾画文件支持nii nii.gz)
影像查看其实也并非想象中那么简单,其中涉及格式转换与窗位窗宽的调整。
本次代码需要以下库:
SimpleITK
nibabel
cv2
numpy
首先您需要在控制台安装缺少的库(只需要安装提示缺少的库)
#SimpleITK:
pip install --user -i https://pypi.tuna.tsinghua.edu.cn/simple SimpleITK
#nibabel:
pip install --user -i https://pypi.tuna.tsinghua.edu.cn/simple nibabel
#cv2:
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple opencv-python
#numpy:
pip install numpy
安装完毕后即可执行本文中的代码。
代码段1 DICOM文件转换为NII NII.GZ NRRD格式
#代码段1 DICOM文件转换为NII NII.GZ NRRD格式
import SimpleITK as sitk
import nibabel as nib
import cv2
import numpy as np
import shutil
import os
#dicom即文件夹存储的dcm后缀文件转为nii或nii.gz或nrrd格式
#dicom文件夹目录 niipath:要保存的文件名
#您只需要修改niipath文件的后缀名为.nii .nii.gz .nrrd便可以直接实现三种格式的保存
def dcm2niigz(dcmpath, niipath):
reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(dcmpath)
reader.SetFileNames(dicom_names)
image2 = reader.Execute()
image_array = sitk.GetArrayFromImage(image2)
origin = image2.GetOrigin()
spacing = image2.GetSpacing()
direction = image2.GetDirection()
image3 = sitk.GetImageFromArray(image_array)
image3.SetSpacing(spacing)
image3.SetDirection(direction)
image3.SetOrigin(origin)
sitk.WriteImage(image3, niipath)
oripath = r'C:\Users\QDUMIAO\Desktop\dicom' #dicom文件夹
savepath1 = r'C:\Users\QDUMIAO\Desktop\ori.nii' #转换为nii
savepath2 = r'C:\Users\QDUMIAO\Desktop\ori.nii.gz' #转换为nii.gz
savepath3 = r'C:\Users\QDUMIAO\Desktop\ori.nii.nrrd' #转换为nrrd
dcm2niigz(oripath,savepath1)
dcm2niigz(oripath,savepath2)
dcm2niigz(oripath,savepath3)
dicom文件都应该存放在一个文件夹中
运行代码可以发现dicom文件已经成功被转换为了三种格式。
事实上,我们希望更多使用nii.gz格式
若我们希望实现nii nii.gz nrrd三种格式之间的转换,可以使用此函数:
代码段2 nii nii.gz nrrd格式互相转换
#代码段2 nii nii.gz nrrd格式互相转换
import SimpleITK as sitk
import nibabel as nib
import cv2
import numpy as np
import shutil
import os
#nii nii.gz nrrd格式之间互相转换
def nii2nii(oripath,savepath):
data = sitk.ReadImage(oripath)
img = sitk.GetArrayFromImage(data)
out = sitk.GetImageFromArray(img)
sitk.WriteImage(out,savepath)
接下来我们便可以使用以下函数将原始影像转换为jpg图像
代码段3 nii nii.gz nrrd原始影像转jpg
#代码段3 nii nii.gz nrrd原始影像转jpg
import SimpleITK as sitk
import nibabel as nib
import cv2
import numpy as np
import shutil
import os
#转换为jpg图像时,调整窗位窗宽
def window_transform(img, windowWidth, windowCenter):
minWindow = float(windowCenter) - 0.5*float(windowWidth)
img = (img - minWindow) / float(windowWidth)
img[img < 0] = 0
img[img > 1] = 1
img = (img * 255).astype('float32')
return img
#nii nii.gz nrrd的原始影像文件(非勾画)转换为jpg
#file_path应该是nii nii.gz nrrd文件 to_path应该是一个文件夹
def Niigz2jpg(file_path,to_path,cwckON,cwckcenter,cwckwidth):
n1 = nib.load(file_path)
n1 = n1.get_fdata()
if(cwckON):
n1 = window_transform(n1,cwckwidth,cwckcenter)
if(os.path.exists(to_path)):#若已存在文件夹
shutil.rmtree(to_path)#则删除文件夹
os.mkdir(to_path)#重新创建文件夹
for i in range(n1.shape[2]):
out_path = to_path + '\\' + str(i) + ".jpg"
nt=cv2.flip(np.rot90(n1[:,:,i],3),1)
nt = nt.astype('float32')
cv2.imwrite(out_path,nt)
勾画文件转换JPG与原始影像转换JPG略有不同,因为勾画文件为0/1,需要X255以可视化。
代码段4 勾画文件转JPG
#代码段4 勾画文件转JPG
import SimpleITK as sitk
import nibabel as nib
import cv2
import numpy as np
import shutil
import os
#nii
nii.gz nrrd勾画文件转jpg 需要像素值X255
def Nii2jpg_x255(file_path,to_path):
n1 = nib.load(file_path)
n1 = n1.get_fdata()
n1 = np.array(n1,dtype=np.uint8)
n1 = n1 * 255
if(os.path.exists(to_path)):
shutil.rmtree(to_path)
if(not os.path.exists(to_path)):
os.mkdir(to_path)
for i in range(n1.shape[2]):
out_path = to_path + '\\' + str(i) + ".jpg"
nt=cv2.flip(np.rot90(n1[:,:,i],3),1)
cv2.imwrite(out_path,nt)
接下来以DICOM原始影像 nii勾画文件为例,为您演示原始影像与勾画文件的转JPG过程。
完整代码:
import SimpleITK as sitk
import nibabel as nib
import cv2
import numpy as np
import shutil
import os
#dicom即文件夹存储的dcm后缀文件转为nii或nii.gz或nrrd格式
#dicom文件夹目录 niipath:要保存的文件名
def dcm2niigz(dcmpath, niipath):
reader = sitk.ImageSeriesReader()
dicom_names = reader.GetGDCMSeriesFileNames(dcmpath)
reader.SetFileNames(dicom_names)
image2 = reader.Execute()
image_array = sitk.GetArrayFromImage(image2)
origin = image2.GetOrigin()
spacing = image2.GetSpacing()
direction = image2.GetDirection()
image3 = sitk.GetImageFromArray(image_array)
image3.SetSpacing(spacing)
image3.SetDirection(direction)
image3.SetOrigin(origin)
sitk.WriteImage(image3, niipath)
#nii nii.gz nrrd格式之间互相转换
def nii2nii(oripath,savepath):
data = sitk.ReadImage(oripath)
img = sitk.GetArrayFromImage(data)
out = sitk.GetImageFromArray(img)
sitk.WriteImage(out,savepath)
#转换为jpg图像时,调整窗位窗宽
def window_transform(img, windowWidth, windowCenter):
minWindow = float(windowCenter) - 0.5*float(windowWidth)
img = (img - minWindow) / float(windowWidth)
img[img < 0] = 0
img[img > 1] = 1
img = (img * 255).astype('float32')
return img
#nii nii.gz nrrd的原始影像文件(非勾画)转换为jpg
#file_path应该是nii nii.gz nrrd文件 to_path应该是一个文件夹
def Niigz2jpg(file_path,to_path,cwckON,cwckcenter,cwckwidth):
n1 = nib.load(file_path)
n1 = n1.get_fdata()
if(cwckON):
n1 = window_transform(n1,cwckwidth,cwckcenter,False)
if(os.path.exists(to_path)):#若已存在文件夹
shutil.rmtree(to_path)#则删除文件夹
os.mkdir(to_path)#重新创建文件夹
for i in range(n1.shape[2]):
out_path = to_path + '\\' + str(i) + ".jpg"
nt=cv2.flip(np.rot90(n1[:,:,i],3),1)
nt = nt.astype('float32')
cv2.imwrite(out_path,nt)
#nii nii.gz nrrd勾画文件转jpg 需要像素值X255
def Nii2jpg_x255(file_path,to_path):
n1 = nib.load(file_path)
n1 = n1.get_fdata()
n1 = np.array(n1,dtype=np.uint8)
n1 = n1 * 255
if(os.path.exists(to_path)):
shutil.rmtree(to_path)
if(not os.path.exists(to_path)):
os.mkdir(to_path)
for i in range(n1.shape[2]):
out_path = to_path + '\\' + str(i) + ".jpg"
nt=cv2.flip(np.rot90(n1[:,:,i],3),1)
cv2.imwrite(out_path,nt)
oripath = r'C:\Users\QDUMIAO\Desktop\dicom' #原始影像dicom文件
maskpath = r'C:\Users\QDUMIAO\Desktop\mask.nii' #勾画文件
niigzpath = r'C:\Users\QDUMIAO\Desktop\ori.nii.gz' #先将dicom转换为nii.gz格式
orijpgpath = r'C:\Users\QDUMIAO\Desktop\orijpg' #存储原始影像JPG
maskjpgpath = r'C:\Users\QDUMIAO\Desktop\maskjpg' #存储勾画文件JPG
dcm2niigz(oripath,niigzpath) #先将原始影像dicom转换为nii.gz
#将原始影像nii.gz转换为jpg 启动窗位窗宽
Niigz2jpg(niigzpath,orijpgpath,cwckON=1,cwckcenter=200,cwckwidth=400)
Nii2jpg_x255(maskpath,maskjpgpath) #将勾画nii.gz转换为jpg
成功将dicom与mask都转换为了jpg
为了更好的查看mask在原始影像的位置,我们需要将mask覆盖到原始影像上。
#orijpgpath:原始影像的jpg图像所在文件夹
#maskjpgpath:勾画文件的jpg图像所在文件夹
#alpha:勾画覆盖强度
#savepath:文件保存目录
def ori_mask_2jpg(orijpgpath,maskjpgpath,alpha,savepath):
names1 = os.listdir(orijpgpath)
names1.sort(key=lambda x:int(x.split('.')[0]))
names2 = os.listdir(maskjpgpath)
names2.sort(key=lambda x:int(x.split('.')[0]))
if(os.path.exists(savepath)):
shutil.rmtree(savepath)
os.mkdir(savepath)
for i in range(len(names1)):
im1 = cv2.imread(orijpgpath + '\\' + names1[i])
im2 = cv2.imread(maskjpgpath + '\\' + names2[i])
im3 = np.concatenate([im1, cv2.addWeighted(im2, alpha, im1, 1,0,0)], axis=1)
cv2.imwrite(savepath+'\\'+names1[i],im3)
savepath = r'C:\Users\QDUMIAO\Desktop\jpg' #覆盖图像保存地址
alpha = 0.3 #覆盖强度
ori_mask_2jpg(orijpgpath,maskjpgpath,alpha,savepath)
执行完毕后将得到以下图像:左侧为原始影像,右侧为勾画覆盖影像。