常用代码块

合并两个nii.gz

def merge_nii_gz(file1_path, file2_path, output_path):
    """
    将两个 .nii.gz 文件合并为一个,保持与原文件相同的尺寸,进行标签的并集操作,并保存为新的 .nii.gz 文件。

    :param file1_path: 第一个 .nii.gz 文件路径
    :param file2_path: 第二个 .nii.gz 文件路径
    :param output_path: 输出合并后的 .nii.gz 文件路径
    """
    # 加载第一个 .nii.gz 文件
    nii1 = nib.load(file1_path)
    data1 = nii1.get_fdata()

    # 加载第二个 .nii.gz 文件
    nii2 = nib.load(file2_path)
    data2 = nii2.get_fdata()

    # 检查两个文件的维度是否匹配
    if data1.shape != data2.shape:
        raise ValueError("两个 .nii.gz 文件的维度不一致,无法合并。")

    # 进行标签的并集操作 (按位逻辑或)
    merged_data = np.logical_or(data1, data2).astype(np.float32)

    # 使用第一个 NIfTI 文件的仿射矩阵和头信息
    merged_nii = nib.Nifti1Image(merged_data, nii1.affine, nii1.header)

    # 保存合并后的 NIfTI 图像为 .nii.gz 文件
    nib.save(merged_nii, output_path)
    print(f"标签并集后的 .nii.gz 文件已保存为 {output_path}")

Dicom转nii.gz

def dicom_to_nii_gz(dicom_dir, output_path):
    """
    使用 SimpleITK 将 DICOM 文件夹中的所有 DICOM 文件转换为 nii.gz 格式并保存,
    并保留原始 DICOM 的 spacing, direction 等信息。

    :param dicom_dir: 包含 DICOM 文件的文件夹路径
    :param output_path: 输出的 nii.gz 文件路径
    """
    # 读取 DICOM 文件夹中的 DICOM 图像
    reader = sitk.ImageSeriesReader()
    dicom_series = reader.GetGDCMSeriesFileNames(dicom_dir)
    reader.SetFileNames(dicom_series)

    # 读取 DICOM 切片并组合成 3D 图像
    image = reader.Execute()

    # 获取原始的 spacing 和 direction
    spacing = image.GetSpacing()
    direction = image.GetDirection()
    origin = image.GetOrigin()

    print(f"Spacing: {spacing}")
    print(f"Direction: {direction}")
    print(f"Origin: {origin}")

    # 保存为 NIfTI 格式,SimpleITK 会保留这些信息
    sitk.WriteImage(image, output_path)
    print(f"DICOM 文件已成功转换并保存为 {output_path}")

按比例缩小bbox

def shrink_bbox_in_mask(mask_path, output_path, shrink_percentage):
    """
    函数功能:缩小给定nii.gz掩码文件中的边界框(bbox)
    
    参数:
    mask_path (str): 输入nii.gz掩码文件的路径
    output_path (str): 保存修改后掩码文件的路径
    shrink_percentage (float): 缩小边界框的百分比,例如 0.1 表示缩小10%
    
    返回:
    无(将处理结果保存为新的nii.gz文件)
    """
    
    # 第1步: 加载nii.gz掩码文件
    img = nib.load(mask_path)
    mask_data = img.get_fdata()
    
    # 第2步: 获取掩码中非零区域的bounding box
    mask_nonzero = np.argwhere(mask_data > 0)
    min_coord = mask_nonzero.min(axis=0)  # 获取非零体素的最小坐标
    max_coord = mask_nonzero.max(axis=0)  # 获取非零体素的最大坐标
    
    # 第3步: 计算bbox的中心和尺寸
    center = (min_coord + max_coord) / 2  # bbox中心坐标
    bbox_size = max_coord - min_coord      # bbox的尺寸
    
    # 第4步: 根据给定的百分比缩小bbox
    shrink_factor = (1 - shrink_percentage)  # 缩小因子
    new_bbox_size = bbox_size * shrink_factor  # 缩小后的bbox尺寸
    new_min_coord = np.round(center - new_bbox_size / 2).astype(int)  # 新的最小坐标
    new_max_coord = np.round(center + new_bbox_size / 2).astype(int)  # 新的最大坐标
    
    # 确保新的bbox在原始mask的维度范围内
    new_min_coord = np.maximum(new_min_coord, 0)
    new_max_coord = np.minimum(new_max_coord, mask_data.shape)
    
    # 第5步: 创建包含缩小后的bbox的新掩码
    new_mask_data = np.zeros_like(mask_data)  # 初始化新的掩码
    new_mask_data[new_min_coord[0]:new_max_coord[0],
                  new_min_coord[1]:new_max_coord[1],
                  new_min_coord[2]:new_max_coord[2]] = mask_data[
                      new_min_coord[0]:new_max_coord[0],
                      new_min_coord[1]:new_max_coord[1],
                      new_min_coord[2]:new_max_coord[2]]  # 填充缩小后的bbox区域
    
    # 第6步: 将新的掩码保存为nii.gz文件
    new_img = nib.Nifti1Image(new_mask_data, img.affine)
    nib.save(new_img, output_path)
    
    print(f'缩小后的掩码已保存到 {output_path}')

3维前缀和

def prefix_sum_3d(arr):
    # 创建一个和原数组大小相同的数组来存储前缀和
    prefix_sum = np.zeros_like(arr)

    # 使用三重循环计算每个位置的前缀和
    for i in range(arr.shape[0]):
        for j in range(arr.shape[1]):
            for k in range(arr.shape[2]):
                # 计算前缀和
                prefix_sum[i, j, k] = arr[i, j, k]
                
                if i > 0:
                    prefix_sum[i, j, k] += prefix_sum[i - 1, j, k]
                if j > 0:
                    prefix_sum[i, j, k] += prefix_sum[i, j - 1, k]
                if k > 0:
                    prefix_sum[i, j, k] += prefix_sum[i, j, k - 1]
                if i > 0 and j > 0:
                    prefix_sum[i, j, k] -= prefix_sum[i - 1, j - 1, k]
                if i > 0 and k > 0:
                    prefix_sum[i, j, k] -= prefix_sum[i - 1, j, k - 1]
                if j > 0 and k > 0:
                    prefix_sum[i, j, k] -= prefix_sum[i, j - 1, k - 1]
                if i > 0 and j > 0 and k > 0:
                    prefix_sum[i, j, k] += prefix_sum[i - 1, j - 1, k - 1]

    return prefix_sum