• TransFuse跑自己的数据集


     原始链接如下

    https://github.com/Rayicer/TransFusehttps://github.com/Rayicer/TransFuse这个复现不难,下面给下关键步骤

    1.数据准备

     一级目录,数据分为训练(train)、验证(val)、测试(test),如果数据少的话验证和测试一样也行,但是一定都要有,因为代码里有个地方写死了,当然,看完代码比较熟悉的话可以自己改掉。

    另外,所有文件夹的名字务必和我一样,这个代码里也写死了,熟悉的可以自己改。

     二级目录

    三级目录,注意这个是二分类,标签的值是0和255

     

     

     2.数据加载

    复现GitHub的关键其实就是数据加载部分,这个项目原本是读取了npy的,直接改成读图片就好了,下面是我改的util/dataloader.py,这里需要注意的是图片的大小,原始的数据大小是256*192,我这里把我512*512的图resize到了256*192,这个规定的大小要更改有点麻烦,得自己去模型文件里探索下,留给大家自己来吧。

    1. import os
    2. from PIL import Image
    3. import torch
    4. import torch.utils.data as data
    5. import torchvision.transforms as transforms
    6. import numpy as np
    7. import matplotlib.pyplot as plt
    8. import albumentations as A
    9. import cv2
    10. class SkinDataset(data.Dataset):
    11. """
    12. dataloader for skin lesion segmentation tasks
    13. """
    14. def __init__(self, image_root, gt_root):
    15. imgs_full_root = os.path.join(image_root, 'images')
    16. labs_full_root = os.path.join(gt_root, 'labels')
    17. image_names = os.listdir(imgs_full_root)
    18. label_names = os.listdir(labs_full_root)
    19. self.images = [os.path.join(imgs_full_root, im_name) for im_name in image_names]
    20. self.gts = [os.path.join(labs_full_root, lab_name) for lab_name in label_names]
    21. self.size = len(self.images)
    22. self.img_transform = transforms.Compose([
    23. transforms.ToTensor(),
    24. transforms.Normalize([0.485, 0.456, 0.406],
    25. [0.229, 0.224, 0.225])
    26. ])
    27. self.gt_transform = transforms.Compose([
    28. transforms.ToTensor()])
    29. self.transform = A.Compose(
    30. [
    31. A.ShiftScaleRotate(shift_limit=0.15, scale_limit=0.15, rotate_limit=25, p=0.5, border_mode=0),
    32. A.ColorJitter(),
    33. A.HorizontalFlip(),
    34. A.VerticalFlip()
    35. ]
    36. )
    37. def __getitem__(self, index):
    38. image_idx = self.images[index]
    39. image = cv2.imread(image_idx)
    40. image = cv2.resize(image, (256, 192))
    41. # image = image.transpose(2,1,0)
    42. gt_idx = self.gts[index]
    43. gt = cv2.imread(gt_idx, 0)
    44. gt = cv2.resize(gt, (256, 192))
    45. gt = gt / 255.0
    46. transformed = self.transform(image=image, mask=gt)
    47. image = self.img_transform(transformed['image'])
    48. # image = image / 255.0
    49. gt = self.gt_transform(transformed['mask'])
    50. return image, gt
    51. def __len__(self):
    52. return self.size
    53. def get_loader(image_root, gt_root, batchsize, shuffle=True, num_workers=4, pin_memory=True):
    54. dataset = SkinDataset(image_root, gt_root)
    55. data_loader = data.DataLoader(dataset=dataset,
    56. batch_size=batchsize,
    57. shuffle=shuffle,
    58. num_workers=num_workers,
    59. pin_memory=pin_memory)
    60. return data_loader
    61. class test_dataset:
    62. def __init__(self, image_root, gt_root):
    63. imgs_full_root = os.path.join(image_root, 'images')
    64. labs_full_root = os.path.join(gt_root, 'labels')
    65. image_names = os.listdir(imgs_full_root)
    66. label_names = os.listdir(labs_full_root)
    67. self.images = [os.path.join(imgs_full_root, im_name) for im_name in image_names]
    68. self.gts = [os.path.join(labs_full_root, lab_name) for lab_name in label_names]
    69. self.transform = transforms.Compose([
    70. transforms.ToTensor(),
    71. transforms.Normalize([0.485, 0.456, 0.406],
    72. [0.229, 0.224, 0.225])
    73. ])
    74. self.gt_transform = transforms.ToTensor()
    75. self.size = len(self.images)
    76. self.index = 0
    77. def load_data(self):
    78. image_idx = self.images[self.index]
    79. image = cv2.imread(image_idx)
    80. image = cv2.resize(image, (256, 192), interpolation=cv2.INTER_NEAREST)
    81. image = self.transform(image).unsqueeze(0)
    82. gt_idx = self.gts[self.index]
    83. gt = cv2.imread(gt_idx, 0)
    84. gt = cv2.resize(gt, (256, 192), interpolation=cv2.INTER_NEAREST)
    85. gt = gt/255.0
    86. self.index += 1
    87. return image, gt
    88. if __name__ == '__main__':
    89. path = 'data/'
    90. tt = SkinDataset(path+'data_train.npy', path+'mask_train.npy')
    91. for i in range(50):
    92. img, gt = tt.__getitem__(i)
    93. img = torch.transpose(img, 0, 1)
    94. img = torch.transpose(img, 1, 2)
    95. img = img.numpy()
    96. gt = gt.numpy()
    97. plt.imshow(img)
    98. plt.savefig('vis/'+str(i)+".jpg")
    99. plt.imshow(gt[0])
    100. plt.savefig('vis/'+str(i)+'_gt.jpg')

    3.训练

    train_isic.py主要改前面的参数部分,还有数据加载路径

    1. import torch
    2. from torch.autograd import Variable
    3. import argparse
    4. from datetime import datetime
    5. from lib.TransFuse import TransFuse_S
    6. from utils.dataloader import get_loader, test_dataset
    7. from utils.utils import AvgMeter
    8. import torch.nn.functional as F
    9. import numpy as np
    10. import matplotlib.pyplot as plt
    11. from test_isic import mean_dice_np, mean_iou_np
    12. import os
    13. def structure_loss(pred, mask):
    14. weit = 1 + 5*torch.abs(F.avg_pool2d(mask, kernel_size=31, stride=1, padding=15) - mask)
    15. wbce = F.binary_cross_entropy_with_logits(pred, mask, reduction='none')
    16. wbce = (weit*wbce).sum(dim=(2, 3)) / weit.sum(dim=(2, 3))
    17. pred = torch.sigmoid(pred)
    18. inter = ((pred * mask)*weit).sum(dim=(2, 3))
    19. union = ((pred + mask)*weit).sum(dim=(2, 3))
    20. wiou = 1 - (inter + 1)/(union - inter+1)
    21. return (wbce + wiou).mean()
    22. def train(train_loader, model, optimizer, epoch, best_loss):
    23. model.train()
    24. loss_record2, loss_record3, loss_record4 = AvgMeter(), AvgMeter(), AvgMeter()
    25. accum = 0
    26. for i, pack in enumerate(train_loader, start=1):
    27. # ---- data prepare ----
    28. images, gts = pack
    29. images = Variable(images).cuda()
    30. gts = Variable(gts).cuda()
    31. # ---- forward ----
    32. lateral_map_4, lateral_map_3, lateral_map_2 = model(images)
    33. # ---- loss function ----
    34. loss4 = structure_loss(lateral_map_4, gts)
    35. loss3 = structure_loss(lateral_map_3, gts)
    36. loss2 = structure_loss(lateral_map_2, gts)
    37. loss = 0.5 * loss2 + 0.3 * loss3 + 0.2 * loss4
    38. # ---- backward ----
    39. loss.backward()
    40. torch.nn.utils.clip_grad_norm_(model.parameters(), opt.grad_norm)
    41. optimizer.step()
    42. optimizer.zero_grad()
    43. # ---- recording loss ----
    44. loss_record2.update(loss2.data, opt.batchsize)
    45. loss_record3.update(loss3.data, opt.batchsize)
    46. loss_record4.update(loss4.data, opt.batchsize)
    47. # ---- train visualization ----
    48. if i % 20 == 0 or i == total_step:
    49. print('{} Epoch [{:03d}/{:03d}], Step [{:04d}/{:04d}], '
    50. '[lateral-2: {:.4f}, lateral-3: {:0.4f}, lateral-4: {:0.4f}]'.
    51. format(datetime.now(), epoch, opt.epoch, i, total_step,
    52. loss_record2.show(), loss_record3.show(), loss_record4.show()))
    53. print('lr: ', optimizer.param_groups[0]['lr'])
    54. save_path = 'snapshots/{}/'.format(opt.train_save)
    55. os.makedirs(save_path, exist_ok=True)
    56. if (epoch+1) % 1 == 0:
    57. meanloss = test(model, opt.test_path)
    58. if meanloss < best_loss:
    59. print('new best loss: ', meanloss)
    60. best_loss = meanloss
    61. torch.save(model.state_dict(), save_path + 'TransFuse-%d.pth' % epoch)
    62. print('[Saving Snapshot:]', save_path + 'TransFuse-%d.pth'% epoch)
    63. return best_loss
    64. def test(model, path):
    65. model.eval()
    66. mean_loss = []
    67. for s in ['val', 'test']:
    68. image_root = '{}/{}'.format(path, s)
    69. gt_root = '{}/{}'.format(path, s)
    70. test_loader = test_dataset(image_root, gt_root)
    71. dice_bank = []
    72. iou_bank = []
    73. loss_bank = []
    74. acc_bank = []
    75. for i in range(test_loader.size):
    76. image, gt = test_loader.load_data()
    77. image = image.cuda()
    78. with torch.no_grad():
    79. _, _, res = model(image)
    80. loss = structure_loss(res, torch.tensor(gt).unsqueeze(0).unsqueeze(0).cuda())
    81. res = res.sigmoid().data.cpu().numpy().squeeze()
    82. gt = 1*(gt>0.5)
    83. res = 1*(res > 0.5)
    84. dice = mean_dice_np(gt, res)
    85. iou = mean_iou_np(gt, res)
    86. acc = np.sum(res == gt) / (res.shape[0]*res.shape[1])
    87. loss_bank.append(loss.item())
    88. dice_bank.append(dice)
    89. iou_bank.append(iou)
    90. acc_bank.append(acc)
    91. print('{} Loss: {:.4f}, Dice: {:.4f}, IoU: {:.4f}, Acc: {:.4f}'.
    92. format(s, np.mean(loss_bank), np.mean(dice_bank), np.mean(iou_bank), np.mean(acc_bank)))
    93. mean_loss.append(np.mean(loss_bank))
    94. return mean_loss[0]
    95. if __name__ == '__main__':
    96. parser = argparse.ArgumentParser()
    97. parser.add_argument('--epoch', type=int, default=80, help='epoch number')
    98. parser.add_argument('--lr', type=float, default=7e-5, help='learning rate')
    99. parser.add_argument('--batchsize', type=int, default=8, help='training batch size')
    100. parser.add_argument('--grad_norm', type=float, default=2.0, help='gradient clipping norm')
    101. parser.add_argument('--train_path', type=str,
    102. default='./data/build512/', help='path to train dataset')
    103. parser.add_argument('--test_path', type=str,
    104. default='./data/build512/', help='path to test dataset')
    105. parser.add_argument('--train_save', type=str, default='TransFuse_S')
    106. parser.add_argument('--beta1', type=float, default=0.5, help='beta1 of adam optimizer')
    107. parser.add_argument('--beta2', type=float, default=0.999, help='beta2 of adam optimizer')
    108. opt = parser.parse_args()
    109. # ---- build models ----
    110. model = TransFuse_S(pretrained=True).cuda()
    111. params = model.parameters()
    112. optimizer = torch.optim.Adam(params, opt.lr, betas=(opt.beta1, opt.beta2))
    113. image_root = '{}/train'.format(opt.train_path)
    114. gt_root = '{}/train'.format(opt.train_path)
    115. train_loader = get_loader(image_root, gt_root, batchsize=opt.batchsize)
    116. total_step = len(train_loader)
    117. print("#"*20, "Start Training", "#"*20)
    118. best_loss = 1e5
    119. for epoch in range(1, opt.epoch + 1):
    120. best_loss = train(train_loader, model, optimizer, epoch, best_loss)

    4.预测验证

    test_isic.py预测也主要是改了路径,细节自己对比下吧

    1. import torch
    2. import torch.nn.functional as F
    3. import numpy as np
    4. import os, argparse
    5. from lib.TransFuse import TransFuse_S
    6. from utils.dataloader import test_dataset
    7. import imageio
    8. import cv2
    9. def mean_iou_np(y_true, y_pred, **kwargs):
    10. """
    11. compute mean iou for binary segmentation map via numpy
    12. """
    13. axes = (0, 1)
    14. intersection = np.sum(np.abs(y_pred * y_true), axis=axes)
    15. mask_sum = np.sum(np.abs(y_true), axis=axes) + np.sum(np.abs(y_pred), axis=axes)
    16. union = mask_sum - intersection
    17. smooth = .001
    18. iou = (intersection + smooth) / (union + smooth)
    19. return iou
    20. def mean_dice_np(y_true, y_pred, **kwargs):
    21. """
    22. compute mean dice for binary segmentation map via numpy
    23. """
    24. axes = (0, 1) # W,H axes of each image
    25. intersection = np.sum(np.abs(y_pred * y_true), axis=axes)
    26. mask_sum = np.sum(np.abs(y_true), axis=axes) + np.sum(np.abs(y_pred), axis=axes)
    27. smooth = .001
    28. dice = 2*(intersection + smooth)/(mask_sum + smooth)
    29. return dice
    30. if __name__ == '__main__':
    31. parser = argparse.ArgumentParser()
    32. parser.add_argument('--ckpt_path', type=str, default='snapshots/TransFuse_S/TransFuse-6.pth')
    33. parser.add_argument('--test_path', type=str,
    34. default='./data/build512', help='path to test dataset')
    35. parser.add_argument('--save_path', type=str, default='./predict', help='path to save inference segmentation')
    36. opt = parser.parse_args()
    37. model = TransFuse_S().cuda()
    38. model.load_state_dict(torch.load(opt.ckpt_path))
    39. model.cuda()
    40. model.eval()
    41. if opt.save_path is not None:
    42. os.makedirs(opt.save_path, exist_ok=True)
    43. print('evaluating model: ', opt.ckpt_path)
    44. image_root = '{}/test'.format(opt.test_path)
    45. gt_root = '{}/test'.format(opt.test_path)
    46. test_loader = test_dataset(image_root, gt_root)
    47. dice_bank = []
    48. iou_bank = []
    49. acc_bank = []
    50. for i in range(test_loader.size):
    51. image, gt = test_loader.load_data()
    52. # gt = 1*(gt>0.5)
    53. gt[gt > 0] = 1
    54. image = image.cuda()
    55. with torch.no_grad():
    56. _, _, res = model(image)
    57. res = res.sigmoid().data.cpu().numpy().squeeze()
    58. # res = 1*(res > 0.5)
    59. res[res > 0.5] = 1
    60. res[res <= 0.5] = 0
    61. dice = mean_dice_np(gt, res)
    62. iou = mean_iou_np(gt, res)
    63. acc = np.sum(res == gt) / (res.shape[0]*res.shape[1])
    64. acc_bank.append(acc)
    65. dice_bank.append(dice)
    66. iou_bank.append(iou)
    67. if opt.save_path is not None:
    68. res = 255 * res
    69. gt = 255 * gt
    70. cv2.imwrite(opt.save_path+'/'+str(i)+'_pred.jpg', res)
    71. cv2.imwrite(opt.save_path+'/'+str(i)+'_gt.jpg', gt)
    72. print('Dice: {:.4f}, IoU: {:.4f}, Acc: {:.4f}'.
    73. format(np.mean(dice_bank), np.mean(iou_bank), np.mean(acc_bank)))

    5.结果

     预测IOU大概在0.6左右,效果还需要自己调,这个项目里的学习率策略还可以加一下,还有数据增强

    积分下载:

    TransFuse复现-深度学习文档类资源-CSDN下载

  • 相关阅读:
    开源博客项目Blog .NET Core源码学习(16:App.Hosting项目结构分析-4)
    从C++CLI工程的依赖库引用问题看.Net加载程序集机制
    6G网络需求、架构及技术趋势
    rsync+inotify远程同步
    【PACS系统源码】与医院HIS系统双向数据交换,实现医学影像集成与影像后处理功能
    CentOS8安装部署DzzOffice协同办公平台
    【测试】最火的测试开发学习路线内容再次大更新,助力通关大厂测开
    并列句------六级
    json数据刨根究底
    C语言第五章第4节用do...while语句实现循环学习导案
  • 原文地址:https://blog.csdn.net/qq_20373723/article/details/126450108