本项目围绕腹部 CT 多器官分割任务,比较 MedSAM、MedSAM2 与 nnU-Net v2 等方法在 FLARE22 数据集上的表现,并在分割结果基础上搭建了一个面向医学影像教学的可视化系统。项目主线是 MedSAM 系列方法的直接迁移、任务内微调和三维传播扩展;nnU-Net v2 作为成熟的全自动三维分割基线参与对照。
除分割实验外,项目还探索了语言提示分割、LLaVA-Med 图像分析和 Web 端教学展示。教学系统将腹部 CT、器官分割 mask、二维高亮、三维重建和文字讲解组织在同一界面中,用于展示多器官分割结果向教学场景转化的一种实现方式。
本仓库主要包含四部分内容。
第一部分是腹部 CT 多器官分割实验。项目从 FLARE22 数据集中选取 50 例带标注腹部 CT,并将原始标签整理为 8 类目标器官,包括肝脏、脾脏、左右肾、胃、胆囊、胰腺和肾上腺。实验比较了 MedSAM zero-shot、MedSAM fine-tuned、MedSAM2 zero-shot 和 nnU-Net v2 四种路线。
第二部分是 MedSAM 相关改进与消融。仓库提供了 MedSAM 切片缓存、box 提示推理、mask decoder 微调、部分 ViT block 解冻微调、提示质量退化、训练样本数量变化以及多窗口、CLAHE、ROI 聚焦、2.5D 输入等预处理探索脚本。
第三部分是语言提示分割与 LLaVA-Med 图像分析。语言提示分割模块使用视觉语言模型生成器官边界框,再交给 MedSAM 或 MedSAM2 完成分割;LLaVA-Med 模块用于对医学图像切片进行辅助观察和文字描述。该部分用于教学与实验探索,不作为诊疗依据。
第四部分是可视化教学系统。Web 系统基于已有腹部 CT 与分割 mask,提供病例浏览、器官查询、最佳切片定位、二维高亮叠加、面积和体积统计、Three.js 三维器官展示以及自然语言讲解等功能。
.
├── README.md
├── requirements.txt
├── configs/
│ └── organs.yaml # 器官标签、数据划分、预处理、VLM 和 nnU-Net 配置
├── src/ # 数据准备、训练、推理、评测、可视化和消融脚本
├── tests/ # 预处理相关自测脚本
├── webapp/ # FastAPI + Vue + Three.js 可视化教学系统
├── third_party/ # MedSAM、MedSAM2、nnU-Net 等第三方源码
├── 3Ddisplay.gif # 三维展示效果
└── LLaVA-Med.gif # LLaVA-Med 图像分析效果
third_party/ 中只包含第三方项目源码,不包含模型权重。FLARE22、LiTS、模型权重、训练缓存和推理结果体积较大,建议在本地按需准备,不建议直接上传到 GitHub。
本项目不是包含数据和权重的完整运行包。完整运行需要自行准备数据集、模型权重和对应环境。
主要数据约定如下:
- FLARE22 主实验数据:
data/FLARE22Train.zip,解压后放在data/raw/FLARE22Train/。 - LiTS 数据:用于 LLaVA-Med 相关探索,默认放在
data/lits_raw/Task03_Liver/。 - MedSAM 权重:默认路径为
checkpoints/MedSAM/medsam_vit_b.pth。 - MedSAM2 权重:默认路径为
third_party/MedSAM2/checkpoints/MedSAM2_latest.pt。 - nnU-Net 训练与推理产物:默认写入
data/nnunet_*和results/nnunet_pred/。
由于 MedSAM、MedSAM2、nnU-Net 和 LLaVA-Med 的依赖存在差异,建议使用多个独立 conda 环境:
| 环境 | 主要用途 | 说明 |
|---|---|---|
| MedSAM / 评测环境 | 数据准备、MedSAM 训练推理、评测和出图 | Python 3.10,安装 requirements.txt 与 third_party/MedSAM |
| MedSAM2 环境 | MedSAM2 三维传播推理 | 按 third_party/MedSAM2 的说明安装 |
| LLaVA-Med 环境 | LLaVA-Med 图像分析 | 按 LLaVA-Med 官方环境和权重准备 |
| Web 后端环境 | 可视化教学系统 | 在 MedSAM / 评测环境基础上安装 webapp/requirements.txt |
公共依赖可先安装:
pip install -r requirements.txt
pip install -e third_party/MedSAM
pip install git+https://github.com/google-deepmind/surface-distance.git如果使用 DashScope / Qwen-VL 相关接口,需要设置环境变量:
export DASHSCOPE_API_KEY=sk-xxxxWindows PowerShell:
$env:DASHSCOPE_API_KEY="sk-xxxx"所有命令默认在仓库根目录下执行,配置文件默认为 configs/organs.yaml。
先完成数据解压、病例选择、标签整理和格式转换:
python src/00_extract_data.py --config configs/organs.yaml
python src/01_select_subjects.py --config configs/organs.yaml
python src/02_build_label_map.py --config configs/organs.yaml
python src/03_to_nnunet.py --config configs/organs.yaml
python src/04_prep_medsam_slices.py --config configs/organs.yaml --split train
python src/04_prep_medsam_slices.py --config configs/organs.yaml --split test这些步骤会把 FLARE22 原始 CT 整理为本项目使用的 8 类器官标签,同时生成 nnU-Net 格式数据和 MedSAM 逐切片缓存。
MedSAM 微调使用预训练 MedSAM 权重和切片缓存:
python src/05_train_medsam.py \
--config configs/organs.yaml \
--ckpt checkpoints/MedSAM/medsam_vit_b.pth \
--train-cache data/medsam_cache/train \
--epochs 50 \
--bs 8 \
--out checkpoints/medsam_ft.pthMedSAM 推理可以使用微调权重,也可以把 --ckpt 换成原始 MedSAM 权重作为 zero-shot 对照:
python src/06_infer_medsam.py \
--config configs/organs.yaml \
--ckpt checkpoints/medsam_ft.pth \
--prompt tight \
--out results/medsam_pred_tightMedSAM2 推理使用中间切片提示和三维传播:
python src/07_infer_medsam2.py \
--config configs/organs.yaml \
--ckpt third_party/MedSAM2/checkpoints/MedSAM2_latest.pt \
--out results/medsam2_prednnU-Net v2 通过官方 CLI 运行。设置好 nnUNet_raw、nnUNet_preprocessed 和 nnUNet_results 后,可按 3D full resolution 配置训练和预测:
nnUNetv2_plan_and_preprocess -d 501 --verify_dataset_integrity
nnUNetv2_train 501 3d_fullres 0 -tr nnUNetTrainer_250epochs
nnUNetv2_predict -i data/nnunet_raw/Dataset501_AbdOrgan/imagesTs \
-o results/nnunet_pred \
-d 501 \
-c 3d_fullres \
-f 0 \
-tr nnUNetTrainer_250epochs完成各模型推理后,用同一评测脚本计算 Dice、HD95 和 NSD,并生成后续报告图表:
python src/08_evaluate.py \
--config configs/organs.yaml \
--gt data/labels_mapped \
--preds "nnunet=results/nnunet_pred,medsam=results/medsam_pred_tight,medsam2=results/medsam2_pred" \
--mapping data/nnunet_raw/Dataset501_AbdOrgan/case_mapping.json \
--out results/metrics.csv
python src/10_make_figures.py如果需要查看失败案例,可使用:
python src/09_visualize_failures.py \
--config configs/organs.yaml \
--metrics results/metrics.csv \
--pred-dir results/medsam_pred_tight \
--model medsam \
--topk 5 \
--out results/figs| 任务 | 入口 |
|---|---|
| 数据解压与校验 | src/00_extract_data.py |
| 病例选择与训练 / 验证 / 测试划分 | src/01_select_subjects.py |
| FLARE22 标签重映射 | src/02_build_label_map.py |
| 转换为 nnU-Net 数据格式 | src/03_to_nnunet.py |
| 生成 MedSAM 切片缓存 | src/04_prep_medsam_slices.py |
| MedSAM mask decoder 微调 | src/05_train_medsam.py |
| MedSAM 轻量端到端适配 | src/05b_train_medsam_e2e.py |
| MedSAM 推理与提示质量消融 | src/06_infer_medsam.py |
| MedSAM2 三维传播推理 | src/07_infer_medsam2.py |
| 分割指标评测 | src/08_evaluate.py |
| 失败案例可视化 | src/09_visualize_failures.py |
| 结果图表生成 | src/10_make_figures.py |
| 推理耗时统计 | src/11_time_medsam.py |
| 语言提示分割 demo | src/12_demo_vlm_seg.py |
| VLM box 批量推理 | src/13_infer_vlm_prompt.py |
| VLM box 缓存生成 | src/14_make_vlm_cache.py |
| 语言驱动 MedSAM2 自动分割 | src/15_infer_vlm_auto.py |
| LiTS 图像导出与 ROI 准备 | src/20_seg_to_roi.py |
| LLaVA-Med 切片推理 | src/21_llava_med_infer.py |
预处理消融集中由 configs/organs.yaml 控制,主要字段包括 ct_windows 和 preproc_ablation。多窗口、CLAHE、ROI 聚焦和 2.5D 输入可以通过派生配置重跑 04 -> 05/05b -> 06 -> 08 的流程进行比较。
Web 系统位于 webapp/,后端使用 FastAPI,前端使用 Vue 和 Three.js。系统读取已有 CT 与分割 mask,提供器官高亮、切片浏览、面积体积统计、三维重建和教学讲解功能。
安装后端依赖:
pip install -r webapp/requirements.txt启动服务:
cd webapp
python -m uvicorn app:app --host 0.0.0.0 --port 8080浏览器访问:
http://127.0.0.1:8080
可选启用 LLaVA-Med worker,用于补充图像观察文本:
python webapp/llava_worker.py --port 8090
export LLAVA_URL=http://127.0.0.1:8090如果未设置 LLAVA_URL 或 DASHSCOPE_API_KEY,系统会跳过对应的大模型步骤,回退到内置讲解模板。
由于本次实验使用的 MedSAM 模型项目较为复杂,若采用分模块分工然后不同模块负责同学对接的话效率过低,因此本组成员分工基于每位同学的特点分工。本组的分工采用工程实现、实验评估、报告撰写、PPT 展示部分进行分工。
首先,由吴君正同学提出大作业主题,然后四位成员共同探讨实验实现方案。接着主要由曹智翔同学负责工程实现部分,负责三种模型的搭建。对于可视化风格工具部分,由吴君正首先初步进行 LLaVA-Med 部署与探索,接由曹智翔进行与分割模型的交互与可视化系统的具体实现。遇到具体问题时,主要由曹智翔和吴君正共同探讨实验解决方式。获取到对应实验脚本后,主要由吴君正同学提取关键信息并分析,最终制作报告初稿。
谢滢同学主要负责报告的部分撰写工作与 PPT 的详细制作。陈天赋同学主要完成 PPT 的汇报部分、PPT 初版的制作与实验报告内容的部分撰写。需要说明的是,以上的每一步每一位组员都有共同参与,所有组员皆清楚内容具体完成部分,上述的“主要”仅代表其中贡献最高者。

