• 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下载

  • 相关阅读:
    大学新生开学数码装备,2022年值得买的几款数码好物
    阿里P8大能倾力编撰的“Java 进阶面试手册”,助力跳槽外包毕业生秋招收获大厂offer
    区块链技术研究探讨
    【路径优化】基于A*算法的路径优化问题(Matlab代码实现)
    Ubuntu将图标放置于任务栏
    Compiling and Loading
    Redis为什么要使用SDS作为基本数据结构
    国内厨电行业数据分析
    2023NOIP A层联测19-多边形
    windows安装npm教程
  • 原文地址:https://blog.csdn.net/qq_20373723/article/details/126450108