医学ct图像数据集
肝脏肿瘤数据集 约300张
说明:标签图中不含肝脏只含肿瘤
nii图像可视化工具
1
1
🩺 医学CT图像数据集:肝脏肿瘤分割(300张)+ NII可视化 + 详细训练代码
📊 一、数据集说明
✅ 数据集名称
肝脏肿瘤 CT 分割数据集(Liver Tumor Segmentation Dataset)
✅ 数据量
- 约 300 张 3D CT 扫描图像(.nii 格式)
- 每个病例包含多个切片(通常 100~200 层),总切片数 > 50,000
- 标注方式:仅标注肿瘤区域,不包含肝脏背景(即标签图中只有肿瘤)
✅ 图像格式
- 原始图像:
.nii或.nii.gz(NIfTI 格式,医学影像标准) - 标签图像:
.nii或.nii.gz,像素值为 1 表示肿瘤,0 表示非肿瘤
✅ 应用场景
- 肝癌早期诊断辅助系统
- 医学影像AI科研项目
- 医生培训与手术规划支持
- 3D肿瘤体积测量
🔍 示例图:左侧为交互式可视化工具界面,右侧为三维重建后显示的红色肿瘤区域(绿色点为关键点)
🧰 二、NIfTI 图像可视化工具推荐
✅ 工具1:ITK-SNAP(免费开源,功能强大)
- 下载地址:https://www.itksnap.org/pmwiki/pmwiki.php
- 支持
.nii文件加载 - 可进行3D 可视化、手动标注、ROI 提取
- 支持多模态融合(如CT+MRI)
✅ 工具2:3D Slicer(MIT开发,学术级)
- 下载地址:https://www.slicer.org/
- 支持
.nii、.dcm等多种格式 - 内置自动分割、3D重建、测量工具
- 可导出分割结果为
.nii或.vtk
✅ 工具3:Python 自定义可视化(使用SimpleITK+matplotlib)
# visualize_nii.pyimportSimpleITKassitkimportnumpyasnpimportmatplotlib.pyplotaspltdefload_nii(path):img=sitk.ReadImage(path)data=sitk.GetArrayFromImage(img)returndata,imgdefshow_slices(data,n=5):# 显示中间几层切片z=data.shape[0]//2foriinrange(n):idx=z-n//2+i plt.subplot(1,n,i+1)plt.imshow(data[idx],cmap='gray')plt.title(f'Slice{idx}')plt.axis('off')plt.tight_layout()plt.show()# 使用示例img_data,img=load_nii("liver_ct.nii")show_slices(img_data)🚀 三、基于 U-Net 的 3D 肿瘤分割模型训练代码(PyTorch)
✅ 使用3D U-Net架构处理 3D CT 数据
✅ 支持.nii格式读取与预处理
✅ 支持 GPU 加速
✅ 输出为 3D 分割掩膜(可直接用于临床分析)
📁 项目目录结构
liver_tumor_segmentation/ ├── data/ # 原始 .nii 文件 │ ├── images/ # CT 图像(.nii) │ └── labels/ # 肿瘤标签(.nii) ├── utils.py # 数据加载与预处理 ├── model.py # 3D U-Net 模型 ├── train.py # 训练脚本 └── predict.py # 推理脚本🔧 四、核心代码实现
1.utils.py—— 数据加载与预处理
# utils.pyimportosimportnumpyasnpimportSimpleITKassitkfromtorch.utils.dataimportDatasetimporttorchclassLiverTumorDataset(Dataset):def__init__(self,image_dir,label_dir,transform=None):self.image_dir=image_dir self.label_dir=label_dir self.transform=transform self.image_files=sorted([fforfinos.listdir(image_dir)iff.endswith('.nii')])def__len__(self):returnlen(self.image_files)def__getitem__(self,idx):img_path=os.path.join(self.image_dir,self.image_files[idx])lbl_path=os.path.join(self.label_dir,self.image_files[idx])# 假设命名一致# 读取图像img=sitk.ReadImage(img_path)img_array=sitk.GetArrayFromImage(img).astype(np.float32)# 读取标签lbl=sitk.ReadImage(lbl_path)lbl_array=sitk.GetArrayFromImage(lbl).astype(np.int64)# 归一化img_array=(img_array-img_array.mean())/img_array.std()# 转为 Tensorimg_tensor=torch.from_numpy(img_array).float().unsqueeze(0)# [C, D, H, W]lbl_tensor=torch.from_numpy(lbl_array).long()# [D, H, W]ifself.transform:img_tensor,lbl_tensor=self.transform(img_tensor,lbl_tensor)returnimg_tensor,lbl_tensor2.model.py—— 3D U-Net 模型
# model.pyimporttorchimporttorch.nnasnnimporttorch.nn.functionalasFclassDoubleConv(nn.Module):def__init__(self,in_channels,out_channels):super().__init__()self.conv=nn.Sequential(nn.Conv3d(in_channels,out_channels,kernel_size=3,padding=1),nn.BatchNorm3d(out_channels),nn.ReLU(inplace=True),nn.Conv3d(out_channels,out_channels,kernel_size=3,padding=1),nn.BatchNorm3d(out_channels),nn.ReLU(inplace=True))defforward(self,x):returnself.conv(x)classDownSample(nn.Module):def__init__(self,in_channels,out_channels):super().__init__()self.maxpool_conv=nn.Sequential(nn.MaxPool3d(2),DoubleConv(in_channels,out_channels))defforward(self,x):returnself.maxpool_conv(x)classUpSample(nn.Module):def__init__(self,in_channels,out_channels,trilinear=True):super().__init__()self.up=nn.Upsample(scale_factor=2,mode='trilinear',align_corners=True)iftrilinearelsenn.ConvTranspose3d(in_channels//2,in_channels//2,kernel_size=2,stride=2)self.conv=DoubleConv(in_channels,out_channels)defforward(self,x1,x2):x1=self.up(x1)diff_z=x2.size()[2]-x1.size()[2]diff_y=x2.size()[3]-x1.size()[3]diff_x=x2.size()[4]-x1.size()[4]x1=F.pad(x1,[diff_x//2,diff_x-diff_x//2,diff_y//2,diff_y-diff_y//2,diff_z//2,diff_z-diff_z//2])x=torch.cat([x2,x1],dim=1)returnself.conv(x)classUNet3D(nn.Module):def__init__(self,n_channels=1,n_classes=2):super().__init__()self.inc=DoubleConv(n_channels,64)self.down1=DownSample(64,128)self.down2=DownSample(128,256)self.down3=DownSample(256,512)self.down4=DownSample(512,512)self.up1=UpSample(1024,256)self.up2=UpSample(512,128)self.up3=UpSample(256,64)self.up4=UpSample(128,64)self.outc=nn.Conv3d(64,n_classes,kernel_size=1)defforward(self,x):x1=self.inc(x)x2=self.down1(x1)x3=self.down2(x2)x4=self.down3(x3)x5=self.down4(x4)x=self.up1(x5,x4)x=self.up2(x,x3)x=self.up3(x,x2)x=self.up4(x,x1)logits=self.outc(x)returnlogits3.train.py—— 训练脚本
# train.pyimporttorchfromtorch.utils.dataimportDataLoaderfromutilsimportLiverTumorDatasetfrommodelimportUNet3Dimportos device=torch.device("cuda"iftorch.cuda.is_available()else"cpu")# 参数设置batch_size=2epochs=100lr=1e-4# 数据集dataset=LiverTumorDataset("data/images","data/labels")loader=DataLoader(dataset,batch_size=batch_size,shuffle=True,num_workers=2)# 模型model=UNet3D(n_channels=1,n_classes=2).to(device)optimizer=torch.optim.Adam(model.parameters(),lr=lr)criterion=nn.BCEWithLogitsLoss()# 训练循环forepochinrange(epochs):model.train()total_loss=0forimgs,lblsinloader:imgs=imgs.to(device)lbls=lbls.to(device).float()optimizer.zero_grad()outputs=model(imgs)loss=criterion(outputs,lbls)loss.backward()optimizer.step()total_loss+=loss.item()print(f"Epoch [{epoch+1}/{epochs}] Loss:{total_loss/len(loader):.4f}")# 保存模型torch.save(model.state_dict(),"liver_tumor_unet.pth")print("✅ 模型已保存!")4.predict.py—— 推理脚本
# predict.pyimporttorchimportSimpleITKassitkfrommodelimportUNet3Dimportnumpyasnp device=torch.device("cuda"iftorch.cuda.is_available()else"cpu")# 加载模型model=UNet3D(n_channels=1,n_classes=2)model.load_state_dict(torch.load("liver_tumor_unet.pth"))model.eval()model.to(device)# 预测单个样本defpredict_single_case(img_path,output_path):img=sitk.ReadImage(img_path)img_array=sitk.GetArrayFromImage(img).astype(np.float32)img_array=(img_array-img_array.mean())/img_array.std()img_tensor=torch.from_numpy(img_array).float().unsqueeze(0).unsqueeze(0).to(device)# [1,1,D,H,W]withtorch.no_grad():pred=model(img_tensor)pred=torch.sigmoid(pred)pred=(pred>0.5).float().cpu().numpy()[0][0]# [D,H,W]# 保存预测结果pred_sitk=sitk.GetImageFromArray(pred.astype(np.uint8))pred_sitk.SetOrigin(img.GetOrigin())pred_sitk.SetSpacing(img.GetSpacing())pred_sitk.SetDirection(img.GetDirection())sitk.WriteImage(pred_sitk,output_path)print(f"✅ 预测完成,结果保存至{output_path}")# 使用示例predict_single_case("test_case.nii","prediction.nii")本方案基于3D U-Net + PyTorch实现了对肝脏肿瘤CT图像的高精度分割,适用于医学AI研究与临床辅助诊断。
数据集仅标注肿瘤区域,适合用于肿瘤检测、体积计算、治疗评估等任务。
结合ITK-SNAP或3D Slicer可进一步提升标注效率与可视化体验。