如何使用 Python 将 Nifti 文件转换为 Dicom 系列

1.摘要

创建将 nifti 文件转换为 dicom 系列的函数的概念很简单;所需要的只是从 nifti 文件中返回帧数据,将其划分为切片,然后将每个切片转换为一个 dicom

这种转换的灵感来自将 JPG 或 PNG 图像转换为 dicoms的函数。

2.步骤

  • 使用预先存在的 dicom 文件。
  • 安装需要的包。
  • nifti 文件中提取帧数据。
  • 准备要转换的数组。
  • 将一个 nifti 文件转换为 dicom 系列。
  • 将多个 nifti 文件转换为多个 dicom 系列。

2.1使用预先存在的 dicom 文件

如果我们尝试转换为 dicom,您可能想知道为什么我们需要 dicom 文件。答案可以在我们从 将 JPG 或 PNG 图像转换为 dicoms的博客上找到。因为当我们想要创建一个dicom文件时,我们不能仅仅将像素数据放入其中,dicom文件还包含除了像素值以外的其他更多的信息。如果没有另一个dicom文件的帮助,我们无法提供这些信息。因此,我们必须使用现有的dicom文件并修改其信息以匹配我们所拥有(需要)的内容。

2.2我们需要的包

与任何其他程序一样,我们需要一些包来完成此转换,因此在此项目中,您需要单独安装以下包。

  • nibabel: pip install nibabel
  • pydicom: pip install pydicom
  • numpy: pip install numpy
  • tqdm:pip install tqdm(这个只是打印转换的进度)

2.3从 nifti 文件中提取帧数据

首先,我们必须从 nifti 文件中提取帧数据(像素数组)以便对其进行转换。这个数组是一个矩阵,每一行都有一个切片。最终,我们将每个切片(行)转换为 dicom

为此,您可以使用 nibabel 库加载 nifti 文件,然后调用get_fdata函数,该函数将提取像素数组(它将是一个 numpy 数组)。

import nibabel

nifti_file = nibabel.load(nifti_dir)
nifti_array = nifti_file.get_fdata()

2.4准备要转换的数组

提取帧数据后,我们必须对其进行准备,以便将其转换为 dicom。我们必须首先将像素值转换为 16 位的无符号整数,然后再获取一个预先存在的 dicom 文件并填写一些参数来匹配我们的参数(宽度、高度……)。

def convertNsave(arr,file_dir, index=0):
    """
    `arr`: parameter will take a numpy array that represents only one slice.
    `file_dir`: parameter will take the path to save the slices
    `index`: parameter will represent the index of the slice, so this parameter will be used to put 
    the name of each slice while using a for loop to convert all the slices
    """
    
    dicom_file = pydicom.dcmread('images/dcmimage.dcm')
    arr = arr.astype('uint16')
    dicom_file.Rows = arr.shape[0]
    dicom_file.Columns = arr.shape[1]
    dicom_file.PhotometricInterpretation = "MONOCHROME2"
    dicom_file.SamplesPerPixel = 1
    dicom_file.BitsStored = 16
    dicom_file.BitsAllocated = 16
    dicom_file.HighBit = 15
    dicom_file.PixelRepresentation = 1
    dicom_file.PixelData = arr.tobytes()

就是这样,设置这些参数后,我们可以使用 pydicom 库中的 save 函数保存数组。

dicom_file.save_as(os.path.join(file_dir, f'slice{index}.dcm'))

注意:此函数只会转换一个切片,因此要转换单个 nifti 文件,我们必须通过所有切片传递此函数(在下一步中)。

2.5将一个 nifti 文件转换为 dicom 系列

正如我在上一段中提到的,函数convertNsave将只转换一个切片。

为此,我创建了函数nifti2dicom_1file,以便可以使用它直接转换一个 nifti 文件,在下一步中,我将向您展示如何对多个 nifti 文件进行转换。

这是nifti2dicom_1file转换一个文件的函数:

def nifti2dicom_1file(nifti_dir, out_dir):
    """
    This function is to convert only one nifti file into dicom series
    `nifti_dir`: the path to the one nifti file
    `out_dir`: the path to output
    """

    nifti_file = nibabel.load(nifti_dir)
    nifti_array = nifti_file.get_fdata()
    number_slices = nifti_array.shape[2]

    for slice_ in tqdm(range(number_slices)):
        convertNsave(nifti_array[:,:,slice_], out_dir, slice_)

如您所见,函数convertNsave是该函数的核心。我只是在这个函数中添加了一个循环来传递所有的切片(我知道这很容易,但我想让它准备好以便你可以直接使用它)

2.6将多个 nifti 文件转换为多个 dicom 系列

现在要转换多个 nifti 文件,我们将只使用该函数nifti2dicom_1file,但我们使用循环多次调用它。这是执行此操作的脚本:

def nifti2dicom_mfiles(nifti_dir, out_dir=''):
    """
    This function is to convert multiple nifti files into dicom files
    `nifti_dir`: You enter the global path to all of the nifti files here.
    `out_dir`: Put the path to where you want to save all the dicoms here.
    PS: Each nifti file's folders will be created automatically, so you do not need to create an empty folder for each patient.
    """

    files = os.listdir(nifti_dir)
    for fileName in files:
        in_path = os.path.join(nifti_dir, fileName)
        out_path = os.path.join(out_dir, fileName)
        os.mkdir(out_path)
        nifti2dicom_1file(in_path, out_path)

2.7完整代码

# coding=utf-8
# /usr/bin/env python
'''
Author:David Xu
Blog: https://blog.csdn.net/weixin_43229348
date: 2022/1/17 13:11
'''
import nibabel
import numpy as np
import pydicom
import os
from tqdm import tqdm


def convertNsave(arr, file_dir, index=0):
    """
    `arr`: parameter will take a numpy array that represents only one slice.
    `file_dir`: parameter will take the path to save the slices
    `index`: parameter will represent the index of the slice, so this parameter will be used to put
    the name of each slice while using a for loop to convert all the slices
    """

    dicom_file = pydicom.dcmread('images/dcmimage.dcm')
    arr = arr.astype('uint16')
    dicom_file.Rows = arr.shape[0]
    dicom_file.Columns = arr.shape[1]
    dicom_file.PhotometricInterpretation = "MONOCHROME2"
    dicom_file.SamplesPerPixel = 1
    dicom_file.BitsStored = 16
    dicom_file.BitsAllocated = 16
    dicom_file.HighBit = 15
    dicom_file.PixelRepresentation = 1
    dicom_file.PixelData = arr.tobytes()
    dicom_file.save_as(os.path.join(file_dir, f'slice{index}.dcm'))


def nifti2dicom_1file(nifti_dir, out_dir):
    """
    This function is to convert only one nifti file into dicom series

    `nifti_dir`: the path to the one nifti file
    `out_dir`: the path to output
    """

    nifti_file = nibabel.load(nifti_dir)
    nifti_array = nifti_file.get_fdata()
    number_slices = nifti_array.shape[2]

    for slice_ in tqdm(range(number_slices)):
        convertNsave(nifti_array[:, :, slice_], out_dir, slice_)


def nifti2dicom_mfiles(nifti_dir, out_dir=''):
    """
    This function is to convert multiple nifti files into dicom files

    `nifti_dir`: You enter the global path to all of the nifti files here.
    `out_dir`: Put the path to where you want to save all the dicoms here.

    PS: Each nifti file's folders will be created automatically, so you do not need to create an empty folder for each patient.
    """

    files = os.listdir(nifti_dir)
    for file in files:
        in_path = os.path.join(nifti_dir, file)
        out_path = os.path.join(out_dir, file)
        os.mkdir(out_path)
        nifti2dicom_1file(in_path, out_path)
if __name__ == '__main__':
    if 0:
        # 将单个nifti文件转为dicom序列
        input_image = "18mask.nii.gz"
        output_path = "dicom_output"
        os.makedirs(output_path, exist_ok=True)
        nifti2dicom_1file(input_image, output_path)
    if 1:
        # 将多个nifti文件转为多个dicom序列
        input_image_dir = "test_dir"
        output_path = "dicom_output"
        os.makedirs(output_path, exist_ok=True)
        nifti2dicom_mfiles(input_image_dir, output_path)


参考目录

https://pycad.co/nifti2dicom/

  • 1
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值