超强攻略:TotalSegmentator NIfTI分割结果一键转BMP格式全流程

超强攻略:TotalSegmentator NIfTI分割结果一键转BMP格式全流程

【免费下载链接】TotalSegmentator Tool for robust segmentation of >100 important anatomical structures in CT images 【免费下载链接】TotalSegmentator 项目地址: https://gitcode.com/gh_mirrors/to/TotalSegmentator

你是否还在为医学影像分割结果的可视化而烦恼?当你使用TotalSegmentator获得精确的NIfTI格式分割结果后,却因无法快速生成临床可用的BMP格式图像而停滞不前?本文将系统解决这一痛点,通过7个实战步骤+3种进阶技巧,帮助你实现从NIfTI到BMP的高效转换,同时掌握质量优化与批量处理的核心方法。读完本文你将获得:医学影像格式转换的完整技术栈、TotalSegmentator高级可视化技巧、临床适用的图像后处理方案。

医学影像格式转换的技术背景

医学影像分割是放射科、肿瘤治疗等领域的关键技术环节,而格式转换则是连接自动分割与临床应用的桥梁。TotalSegmentator作为目前最先进的医学影像分割工具之一,能够在CT和MR图像中精准识别超过100种解剖结构(图1),但其默认输出的NIfTI格式(.nii.gz)在临床报告、教学演示等场景中存在可视化障碍。

NIfTI与BMP格式的核心差异

特性NIfTI格式BMP格式临床应用场景
数据类型3D体数据,含空间信息2D位图,像素阵列NIfTI用于定量分析,BMP用于定性展示
压缩方式支持gzip压缩无压缩/RIFF压缩科研存储用NIfTI,报告展示用BMP
元数据包含DICOM头信息、 affine矩阵仅包含基本图像尺寸、位深NIfTI保留空间定位,BMP侧重视觉呈现
软件兼容性ITK-SNAP、3D Slicer所有图像查看器、浏览器专业分析用NIfTI,跨平台分享用BMP

TotalSegmentator的可视化能力

TotalSegmentator内置的--preview参数已经提供了基础的3D渲染功能,通过fury库实现多结构叠加显示(图2)。该功能生成的preview.png文件包含所有分割结构的3D投影,但存在以下局限:

  • 仅输出PNG格式,不直接支持BMP
  • 默认视角固定,无法自定义解剖结构的显示角度
  • 不支持单结构单独导出,难以制作局部放大图

TotalSegmentator分割效果示例

环境准备与依赖安装

基础环境配置

确保你的系统已安装TotalSegmentator及其核心依赖:

pip install TotalSegmentator>=2.2.1
pip install nibabel>=4.0.0 matplotlib>=3.7.0 pillow>=10.0.0

对于3D渲染功能,需额外安装:

# Ubuntu/Debian
sudo apt-get install xvfb
# CentOS/RHEL
sudo yum install xorg-x11-server-Xvfb
# macOS
brew install XQuartz

验证安装完整性

创建验证脚本check_env.py

import nibabel as nib
import matplotlib.pyplot as plt
from PIL import Image
from totalsegmentator.python_api import totalsegmentator

print("Nibabel version:", nib.__version__)
print("Matplotlib version:", plt.__version__)
print("Pillow version:", Image.__version__)

# 测试TotalSegmentator可用性
try:
    print("TotalSegmentator task list:", list(totalsegmentator.class_map.keys())[:5])
    print("环境验证成功")
except Exception as e:
    print("环境验证失败:", str(e))

执行脚本验证所有依赖是否正常工作:

python check_env.py

方法一:使用内置Preview功能转换

TotalSegmentator的--preview参数能够自动生成3D渲染预览图,这是最简单的转换途径。

基础转换流程

  1. 运行分割并生成预览:
TotalSegmentator -i input_ct.nii.gz -o segmentations --preview
  1. 查看生成的PNG文件:
ls segmentations/preview.png
  1. 使用Python将PNG转换为BMP:
from PIL import Image

# 打开PNG文件并转换为BMP
with Image.open("segmentations/preview.png") as img:
    img.save("segmentations/preview.bmp", "BMP")

自定义预览参数

通过调整预览生成参数优化图像质量:

TotalSegmentator -i input_ct.nii.gz -o segmentations --preview --smoothing 30

其中--smoothing参数控制3D模型的平滑度(默认20),值越大表面越光滑但细节越少。对于需要展示精细结构(如骨骼)的场景,建议使用10-15的较低值。

方法二:2D切片批量转换技术

对于需要将3D体数据转换为系列2D切片的场景(如逐层观察肿瘤变化),可采用Nibabel+Matplotlib方案。

单结构切片提取

以下脚本提取肝脏结构的轴向切片并保存为BMP:

import nibabel as nib
import numpy as np
import matplotlib.pyplot as plt
from pathlib import Path

# 创建输出目录
output_dir = Path("liver_slices")
output_dir.mkdir(exist_ok=True)

# 读取NIfTI文件
nifti_path = "segmentations/liver.nii.gz"
img = nib.load(nifti_path)
data = img.get_fdata()

# 获取体数据形状 (x, y, z)
x, y, z = data.shape

# 生成中间10层的切片
start_slice = z // 2 - 5
end_slice = z // 2 + 5

for i in range(start_slice, end_slice):
    # 获取第i层切片
    slice_data = data[:, :, i]
    
    # 创建图像
    plt.figure(figsize=(10, 10))
    plt.imshow(slice_data.T, cmap="gray", origin="lower")
    plt.axis("off")
    
    # 保存为BMP
    output_path = output_dir / f"liver_slice_{i:03d}.bmp"
    plt.savefig(output_path, bbox_inches="tight", pad_inches=0)
    plt.close()

print(f"已生成{end_slice - start_slice}个BMP切片到{output_dir}")

多结构对比切片

生成包含原始CT与多个结构掩码的复合切片:

import nibabel as nib
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.colors import LinearSegmentedColormap

# 读取CT图像和分割结果
ct_img = nib.load("input_ct.nii.gz")
ct_data = ct_img.get_fdata()
liver_img = nib.load("segmentations/liver.nii.gz")
liver_data = liver_img.get_fdata()
spleen_img = nib.load("segmentations/spleen.nii.gz")
spleen_data = spleen_img.get_fdata()

# 创建自定义颜色映射
liver_cmap = LinearSegmentedColormap.from_list("liver", [(0, 0, 0, 0), (0, 1, 0, 0.5)])
spleen_cmap = LinearSegmentedColormap.from_list("spleen", [(0, 0, 0, 0), (1, 0, 0, 0.5)])

# 生成中间切片
z = ct_data.shape[2] // 2
ct_slice = ct_data[:, :, z]
liver_slice = liver_data[:, :, z]
spleen_slice = spleen_data[:, :, z]

# 显示并保存
plt.figure(figsize=(12, 12))
plt.imshow(ct_slice.T, cmap="gray", origin="lower", vmin=-150, vmax=250)
plt.imshow(liver_slice.T, cmap=liver_cmap, origin="lower")
plt.imshow(spleen_slice.T, cmap=spleen_cmap, origin="lower")
plt.axis("off")
plt.savefig("ct_with_liver_spleen.bmp", bbox_inches="tight", pad_inches=0)

方法三:高级3D渲染与BMP导出

对于需要高质量3D渲染的场景,可使用fury库(TotalSegmentator预览功能的底层依赖)进行自定义渲染。

基础3D渲染脚本

import numpy as np
import nibabel as nib
from fury import window, actor, io
from totalsegmentator.vtk_utils import contour_from_roi_smooth

# 读取NIfTI文件
ct_img = nib.load("input_ct.nii.gz")
segmentation_img = nib.load("segmentations/liver.nii.gz")
data = segmentation_img.get_fdata()
affine = segmentation_img.affine

# 创建场景
scene = window.Scene()

# 添加CT背景
ct_data = ct_img.get_fdata()
ct_actor = actor.slicer(ct_data, affine=ct_img.affine)
ct_actor.display(None, None, slice_number=ct_data.shape[2]//2)
scene.add(ct_actor)

# 添加3D分割结构
contour_actor = contour_from_roi_smooth(data, affine, smoothing=25)
scene.add(contour_actor)

# 设置视角
scene.set_camera(position=(1000, 0, 0), focal_point=(0, 0, 0), view_up=(0, 1, 0))
scene.reset_camera_tight()

# 保存为BMP
window.record(scene, out_path="3d_liver_rendering.bmp", size=(1024, 1024))

多结构3D渲染

同时渲染多个解剖结构并导出为BMP:

from fury import window, actor
import numpy as np
import nibabel as nib
from totalsegmentator.map_to_binary import class_map

# 加载多个结构
structures = {
    "liver": {"color": (0, 1, 0), "opacity": 0.6},
    "kidney_right": {"color": (0, 0, 1), "opacity": 0.6},
    "kidney_left": {"color": (0, 0, 1), "opacity": 0.6},
    "spleen": {"color": (1, 0, 0), "opacity": 0.6}
}

# 创建场景
scene = window.Scene()

# 添加所有结构
for name, props in structures.items():
    img = nib.load(f"segmentations/{name}.nii.gz")
    data = img.get_fdata()
    affine = img.affine
    
    # 创建3D轮廓
    actor = contour_from_roi_smooth(data, affine, smoothing=20)
    actor.GetProperty().SetColor(props["color"])
    actor.GetProperty().SetOpacity(props["opacity"])
    scene.add(actor)

# 设置相机和光照
scene.set_camera(position=(800, 800, 800), focal_point=(0, 0, 0), view_up=(0, 1, 0))
scene.add(actor.axes(scale=(100, 100, 100)))

# 保存为BMP
window.record(scene, out_path="abdominal_structures_3d.bmp", size=(1200, 1200))

批量转换与自动化处理

当需要处理大量病例时,自动化脚本能够显著提高效率。

批量转换脚本

import os
import re
from PIL import Image
from pathlib import Path

def batch_convert_previews(input_dir, output_dir):
    """
    批量将TotalSegmentator生成的PNG预览转换为BMP
    
    Args:
        input_dir: 包含多个病例文件夹的根目录
        output_dir: BMP输出目录
    """
    # 创建输出目录
    Path(output_dir).mkdir(exist_ok=True)
    
    # 遍历所有病例文件夹
    for case_dir in os.listdir(input_dir):
        case_path = os.path.join(input_dir, case_dir)
        if not os.path.isdir(case_path):
            continue
            
        # 查找preview.png
        preview_path = os.path.join(case_path, "preview.png")
        if os.path.exists(preview_path):
            # 转换为BMP
            output_path = os.path.join(output_dir, f"{case_dir}_preview.bmp")
            with Image.open(preview_path) as img:
                img.save(output_path, "BMP")
            print(f"转换完成: {case_dir}")

# 使用示例
batch_convert_previews("/path/to/cases", "/path/to/bmp_outputs")

集成到分割流程

创建完整的分割-转换流水线脚本segment_and_convert.sh

#!/bin/bash

# 检查输入参数
if [ $# -ne 1 ]; then
    echo "用法: $0 <input_nii.gz>"
    exit 1
fi

input=$1
case_name=$(basename "$input" .nii.gz)
output_dir="./segmentations_${case_name}"

# 创建输出目录
mkdir -p "$output_dir"

# 运行TotalSegmentator
TotalSegmentator -i "$input" -o "$output_dir" --preview

# 转换为BMP
python - <<END
from PIL import Image
import os

output_dir = "$output_dir"
if os.path.exists(os.path.join(output_dir, "preview.png")):
    with Image.open(os.path.join(output_dir, "preview.png")) as img:
        img.save(os.path.join(output_dir, f"${case_name}_preview.bmp"), "BMP")
    print("转换成功")
else:
    print("预览文件不存在")
END

echo "处理完成: $output_dir"

赋予执行权限并运行:

chmod +x segment_and_convert.sh
./segment_and_convert.sh input_ct.nii.gz

质量优化与常见问题解决

图像质量优化技巧

  1. 分辨率提升:通过调整渲染尺寸提高图像清晰度
# 在window.record中设置更高的size参数
window.record(scene, out_path="high_res.bmp", size=(2000, 2000))
  1. 对比度增强:使用PIL调整图像对比度
from PIL import Image, ImageEnhance

with Image.open("preview.png") as img:
    enhancer = ImageEnhance.Contrast(img)
    img_enhanced = enhancer.enhance(1.5)  # 增加50%对比度
    img_enhanced.save("preview_enhanced.bmp", "BMP")
  1. 抗锯齿处理:在3D渲染时启用抗锯齿
window.record(scene, out_path="anti_aliased.bmp", size=(1200, 1200), anti_aliasing=True)

常见问题解决方案

问题原因解决方案
转换后图像全黑窗宽窗位设置不当使用vmin=-150, vmax=250调整CT窗宽
3D渲染结构缺失平滑度过高降低--smoothing参数至15-20
转换速度慢图像尺寸过大使用--fast参数或降低输出分辨率
BMP文件体积过大未压缩且分辨率高适当降低分辨率或使用pngquant压缩后转换
中文路径错误Python路径编码问题使用Pathlib库或转换路径为纯ASCII

临床应用案例与最佳实践

肿瘤治疗规划应用

在放射治疗规划中,清晰的结构显示至关重要:

# 生成肿瘤与危及器官的3D对比图
import nibabel as nib
from fury import window, actor

# 加载数据
ct_img = nib.load("patient_ct.nii.gz")
tumor_img = nib.load("segmentations/liver_tumor.nii.gz")
liver_img = nib.load("segmentations/liver.nii.gz")

# 创建场景
scene = window.Scene()

# 添加肝脏(半透明绿色)
liver_actor = contour_from_roi_smooth(liver_img.get_fdata(), liver_img.affine, smoothing=20)
liver_actor.GetProperty().SetColor(0, 1, 0)
liver_actor.GetProperty().SetOpacity(0.4)
scene.add(liver_actor)

# 添加肿瘤(红色不透明)
tumor_actor = contour_from_roi_smooth(tumor_img.get_fdata(), tumor_img.affine, smoothing=10)
tumor_actor.GetProperty().SetColor(1, 0, 0)
tumor_actor.GetProperty().SetOpacity(1.0)
scene.add(tumor_actor)

# 设置视角并保存
scene.set_camera(position=(600, 400, 800), focal_point=(0, 0, 0))
window.record(scene, out_path="tumor_visualization.bmp", size=(1000, 1000))

教学演示中的应用

为医学教育创建解剖结构教学图:

# 生成带标注的骨骼系统图
import numpy as np
import nibabel as nib
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle

# 加载脊柱分割结果
spine_img = nib.load("segmentations/vertebrae_L3.nii.gz")
spine_data = spine_img.get_fdata()

# 获取中间切片
mid_slice = spine_data.shape[2] // 2
slice_data = spine_data[:, :, mid_slice].T

# 创建图像和标注
plt.figure(figsize=(10, 10))
plt.imshow(slice_data, cmap="gray", origin="lower")
plt.title("L3腰椎椎体 - 轴向视图", fontsize=16)

# 添加解剖标注
plt.text(50, 50, "椎弓根", color="red", fontsize=12)
plt.text(150, 100, "椎体", color="blue", fontsize=12)

# 添加比例尺
plt.gca().add_patch(Rectangle((20, 20), 50, 5, facecolor='white'))
plt.text(20, 15, "50mm", color="black", fontsize=10)

plt.axis("off")
plt.savefig("l3_vertebra_annotation.bmp", bbox_inches="tight")

总结与未来展望

本文系统介绍了三种将TotalSegmentator的NIfTI分割结果转换为BMP格式的方法,从简单的内置功能到复杂的自定义3D渲染,满足不同场景需求。通过基础转换、批量处理和质量优化等技巧,你可以轻松将医学影像分割结果转化为临床可用的可视化资料。

随着TotalSegmentator的不断发展,未来可能会直接支持BMP格式输出,进一步简化工作流程。同时,AI辅助的自动窗宽窗位调整、多模态融合可视化等技术也将提升医学影像可视化的质量和效率。

掌握这些转换技术不仅能提高你的工作效率,还能让精确的医学影像分割结果在临床沟通、学术交流和医学教育中发挥更大价值。立即尝试这些方法,将你的分割结果转化为更有影响力的可视化成果!

点赞+收藏+关注,不错过更多医学影像处理技巧!下期预告:基于TotalSegmentator的3D打印模型生成全流程。

【免费下载链接】TotalSegmentator Tool for robust segmentation of >100 important anatomical structures in CT images 【免费下载链接】TotalSegmentator 项目地址: https://gitcode.com/gh_mirrors/to/TotalSegmentator

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值