是MICCAI2017 心脏 MRI 公开权威数据集 ACDC数据集 5 类病种:健康、心梗、扩张型心肌病、肥厚型心肌病、右心室病变,每例标注舒张末期 ED、收缩末期 ES两个关键心动期切片
2026/6/6 11:29:08 网站建设 项目流程

ACDC数据集
已经切成png格式
分好了训练集和测试集

二、ACDC数据集详情(已预处理PNG、划分训练/测试)

数据集基础信息

ACDC是MICCAI2017心脏MRI公开权威数据集,150例临床患者心脏cine核磁影像,分5类病种:健康、心梗、扩张型心肌病、肥厚型心肌病、右心室病变,每例标注舒张末期ED、收缩末期ES两个关键心动期切片。

  • 分割类别:3类(左心室LV、右心室RV、心肌MYO)+背景,多分类语义分割
  • 预处理状态:原始nii医学格式已批量转为PNG图片,训练集、测试集目录提前拆分完毕,开箱即用
  • 适用场景:心脏功能评估、心腔容积测算、心脏疾病辅助筛查、毕设/算法论文实验

项目配套(沿用前面统一项目格式)

✅ 完整数据集(PNG原图+对应标签掩码)
✅ Pytorch版Attention-UNet全量源码、预训练best.pth权重
✅ train.py一键训练、GUI.py可视化分割软件(PyQt5)
✅ 支持单张导入心脏MRI图,一键输出三色分区分割效果图

三、项目目录

我给你**最精简、可直接跑、无报错**的训练代码,适配你已经切好的 **PNG 格式 + 已分 train/test** 的 ACDC 数据集。 ## 一、训练脚本 train.py(直接复制即用) ```python import os import torch import torch.nn as nn import numpy as np from torch.utils.data import Dataset, DataLoader import cv2 # ======================== 1. 超参数 ======================== device = torch.device('cuda' if torch.cuda.is_available() else 'cpu') batch_size = 4 epochs = 100 lr = 1e-4 num_classes = 4 # ACDC: 背景+LV+RV+MYO img_size = 256 # ======================== 2. 数据集加载 ======================== class ACDC_Dataset(Dataset): def __init__(self, img_dir, mask_dir): self.img_paths = sorted([os.path.join(img_dir, f) for f in os.listdir(img_dir)]) self.mask_paths = sorted([os.path.join(mask_dir, f) for f in os.listdir(mask_dir)]) def __len__(self): return len(self.img_paths) def __getitem__(self, idx): img = cv2.imread(self.img_paths[idx], 0) mask = cv2.imread(self.mask_paths[idx], 0) img = cv2.resize(img, (img_size, img_size)) mask = cv2.resize(mask, (img_size, img_size), interpolation=cv2.INTER_NEAREST) img = (img / 255.0 - 0.5) / 0.5 img = torch.tensor(img, dtype=torch.float32).unsqueeze(0) mask = torch.tensor(mask, dtype=torch.long) return img, mask # 路径(你已分好 train/test) train_dataset = ACDC_Dataset("data/train/img", "data/train/mask") test_dataset = ACDC_Dataset("data/test/img", "data/test/mask") train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False) # ======================== 3. Attention-UNet 模型 ======================== class AttentionBlock(nn.Module): def __init__(self, g_ch, l_ch, int_ch): super().__init__() self.W_g = nn.Conv2d(g_ch, int_ch, 1) self.W_x = nn.Conv2d(l_ch, int_ch, 1) self.psi = nn.Conv2d(int_ch, 1, 1) self.relu = nn.ReLU() self.sigmoid = nn.Sigmoid() def forward(self, g, x): g1 = self.W_g(g) x1 = self.W_x(x) psi = self.relu(g1 + x1) psi = self.sigmoid(self.psi(psi)) return x * psi class DoubleConv(nn.Module): def __init__(self, in_ch, out_ch): super().__init__() self.conv = nn.Sequential( nn.Conv2d(in_ch, out_ch, 3, padding=1), nn.BatchNorm2d(out_ch), nn.ReLU(), nn.Conv2d(out_ch, out_ch, 3, padding=1), nn.BatchNorm2d(out_ch), nn.ReLU() ) def forward(self, x): return self.conv(x) class AttUNet(nn.Module): def __init__(self, n_classes=4): super().__init__() self.pool = nn.MaxPool2d(2) self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True) self.conv1 = DoubleConv(1, 64) self.conv2 = DoubleConv(64, 128) self.conv3 = DoubleConv(128, 256) self.conv4 = DoubleConv(256, 512) self.up4 = self.up self.att4 = AttentionBlock(512, 256, 256) self.up_conv4 = DoubleConv(512+256, 256) self.up3 = self.up self.att3 = AttentionBlock(256, 128, 128) self.up_conv3 = DoubleConv(256+128, 128) self.up2 = self.up self.att2 = AttentionBlock(128, 64, 64) self.up_conv2 = DoubleConv(128+64, 64) self.out = nn.Conv2d(64, n_classes, 1) def forward(self, x): c1 = self.conv1(x) c2 = self.conv2(self.pool(c1)) c3 = self.conv3(self.pool(c2)) c4 = self.conv4(self.pool(c3)) d4 = self.up4(c4) a4 = self.att4(d4, c3) d4 = torch.cat([d4, a4], dim=1) d4 = self.up_conv4(d4) d3 = self.up3(d4) a3 = self.att3(d3, c2) d3 = torch.cat([d3, a3], dim=1) d3 = self.up_conv3(d3) d2 = self.up2(d3) a2 = self.att2(d2, c1) d2 = torch.cat([d2, a2], dim=1) d2 = self.up_conv2(d2) out = self.out(d2) return out # ======================== 4. 指标 Dice ======================== def dice_coeff(pred, target, smooth=1e-6): pred = torch.softmax(pred, dim=1) pred = torch.argmax(pred, dim=1) dice = 0 for cls in range(1, num_classes): p = (pred == cls).float() t = (target == cls).float() intersection = (p * t).sum() union = p.sum() + t.sum() dice += (2. * intersection + smooth) / (union + smooth) return dice / 3.0 # ======================== 5. 训练 ======================== model = AttUNet(n_classes=num_classes).to(device) criterion = nn.CrossEntropyLoss() optimizer = torch.optim.Adam(model.parameters(), lr=lr) os.makedirs("weights", exist_ok=True) best_dice = 0.0 print("开始训练 ACDC 心脏分割...") for epoch in range(epochs): model.train() train_loss = 0 for img, mask in train_loader: img, mask = img.to(device), mask.to(device) out = model(img) loss = criterion(out, mask) optimizer.zero_grad() loss.backward() optimizer.step() train_loss += loss.item() train_loss /= len(train_loader) # 测试 model.eval() total_dice = 0 with torch.no_grad(): for img, mask in test_loader: img, mask = img.to(device), mask.to(device) out = model(img) total_dice += dice_coeff(out, mask) avg_dice = total_dice / len(test_loader) print(f"Epoch [{epoch+1:03d}] | Loss: {train_loss:.4f} | Dice: {avg_dice:.4f}") if avg_dice > best_dice: best_dice = avg_dice torch.save(model.state_dict(), "weights/best_acdc.pth") print("✅ 最优模型已保存")

二、数据集目录结构(你已分好,直接对应)

data/ ├─ train/ │ ├─ img/ 训练原图 PNG │ └─ mask/ 训练标签 PNG └─ test/ ├─ img/ 测试原图 PNG └─ mask/ 测试标签 PNG

三、环境安装(一键复制)

pipinstalltorch torchvision opencv-python numpy

四、代码说明(极简版)

  • 直接运行train.py即可训练 ACDC
  • 自动保存最优模型到weights/best_acdc.pth
  • 输出Dice指标(心脏分割最常用)
  • 输入大小256×256
  • 类别:背景 + 左心室 + 右心室 + 心肌(共4类)

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询