def train_transform(resize, normalize=None): if normalize == 'imagenet': trans_fucn = [ albu.VerticalFlip(p=0.5), albu.HorizontalFlip(p=0.5), # albu.ToFloat(max_value=255, p=1.0), albu.Normalize(p=1.0), ToTensorV2(p=1.0) ] elif normalize == 'global_norm': trans_fucn = [ albu.VerticalFlip(p=0.5), albu.HorizontalFlip(p=0.5), GlobalNormalize(p=1.0), # albu.ToFloat(max_value=255, p=1.0), ToTensorV2(p=1.0) ] else: trans_fucn = [ albu.VerticalFlip(p=0.5), albu.HorizontalFlip(p=0.5), albu.Normalize(mean=(0, 0, 0), std=(1, 1, 1)), # albu.ToFloat(max_value=255, p=1.0), ToTensorV2(p=1.0) ] return Compose(trans_fucn, p=1.0)
def get_transformv2(opt): transform_list = [] # Transforms in opt.preprocess if 'fixsize' in opt.preprocess: transform_list.append(tr.Resize(286, 286, interpolation=2, p=1)) if 'resize' in opt.preprocess: transform_list.append( tr.Resize(opt.load_size, opt.load_size, interpolation=2, p=1)) if 'crop' in opt.preprocess: transform_list.append(tr.RandomCrop(opt.crop_size, opt.crop_size, p=1)) # Transforms in colorspace if 'color' in opt.preprocess: transform_list.extend([ tr.RandomContrast(limit=0.2, p=0.5), tr.RandomBrightness(limit=0.2, p=0.5), tr.HueSaturationValue(hue_shift_limit=20, sat_shift_limit=30, val_shift_limit=20, p=0.5), # tr.ISONoise() ]) # Necessary transforms transform_list.extend([ tr.HorizontalFlip(p=0.5), tr.VerticalFlip(p=0.5), tr.Normalize(p=1.0), ToTensorV2(p=1) ]) return Compose(transform_list, additional_targets={'imageB': 'image'})
def flip_augment(image, mask): ''' flip an image vertically or horizontally. Args: image(nd.array) mask(nd.array) Returns: (flip_image, flip_mask) (tuple) : tuple of flipped image and mask. ''' if (random.randint(0, 1) == 0): flip_img = transforms.HorizontalFlip().apply(image) flip_mask = transforms.HorizontalFlip().apply_to_mask(mask) else: flip_img = transforms.VerticalFlip().apply(image) flip_mask = transforms.VerticalFlip().apply_to_mask(mask) return (flip_img, flip_mask)
def augmentation(in_path='./train/raw_images/', out_path='./train/aug_images/'): for filename in os.listdir(in_path): hf = transforms.HorizontalFlip(always_apply=True) vf = transforms.VerticalFlip(always_apply=True) tp = transforms.Transpose(always_apply=True) rt = transforms.Rotate(limit=80, always_apply=True) image = np.array(Image.open(in_path + filename)) hf_image = hf(image=image)['image'] vf_image = vf(image=image)['image'] tp_image = tp(image=image)['image'] rt_image = rt(image=image)['image'] count = 1 for img in [image, hf_image, vf_image, tp_image, rt_image]: if len(img.shape) == 2: img = Image.fromarray(img) img.convert(mode='RGB') else: img = Image.fromarray(img, mode='RGB') img.save(out_path + filename.replace('.jpg', '_' + str(count) + '.jpg')) count += 1
def __init__(self, im_paths=None, labels=None, phase=None, resize=False): """ Args: im_paths (numpy): image_data y (numpy): label data transform: pytorch transforms for transforms and tensor conversion """ self.im_paths = im_paths self.labels = labels self.resize = resize self.albumentations_transform = { 'train': Compose([ ab_transforms.HorizontalFlip(p=0.2), ab_transforms.VerticalFlip(p=0.2), ab_transforms.Rotate(limit=180, p=0.2), ab_transforms.HueSaturationValue(p=0.1), ab_transforms.RandomContrast(p=0.1), ab_transforms.GaussianBlur(blur_limit=3, p=0.2), ab_transforms.GaussNoise(p=0.05), ab_transforms.CLAHE(p=0.2), ab_transforms.Normalize(mean=[0.5944, 0.4343, 0.5652], std=[0.2593, 0.2293, 0.2377]), ToTensor() ]), 'val': Compose([ ab_transforms.Normalize(mean=[0.5944, 0.4343, 0.5652], std=[0.2593, 0.2293, 0.2377]), ToTensor() ]), } if phase == 'train': self.transform = self.albumentations_transform['train'] else: self.transform = self.albumentations_transform['val']
def main(): args = parse_args() if args.name is None: args.name = '%s_%s' % (args.arch, datetime.now().strftime('%m%d%H')) if not os.path.exists('models/%s' % args.name): os.makedirs('models/%s' % args.name) if args.resume: args = joblib.load('models/%s/args.pkl' % args.name) args.resume = True print('Config -----') for arg in vars(args): print('- %s: %s' % (arg, getattr(args, arg))) print('------------') with open('models/%s/args.txt' % args.name, 'w') as f: for arg in vars(args): print('- %s: %s' % (arg, getattr(args, arg)), file=f) joblib.dump(args, 'models/%s/args.pkl' % args.name) if args.seed is not None and not args.resume: print('set random seed') random.seed(args.seed) np.random.seed(args.seed) torch.manual_seed(args.seed) if args.loss == 'BCEWithLogitsLoss': criterion = BCEWithLogitsLoss().cuda() elif args.loss == 'WeightedBCEWithLogitsLoss': criterion = BCEWithLogitsLoss(weight=torch.Tensor([1., 1., 1., 1., 1., 2.]), smooth=args.label_smooth).cuda() elif args.loss == 'FocalLoss': criterion = FocalLoss().cuda() elif args.loss == 'WeightedFocalLoss': criterion = FocalLoss(weight=torch.Tensor([1., 1., 1., 1., 1., 2.])).cuda() else: raise NotImplementedError if args.pred_type == 'all': num_outputs = 6 elif args.pred_type == 'except_any': num_outputs = 5 else: raise NotImplementedError cudnn.benchmark = True # create model model = get_model(model_name=args.arch, num_outputs=num_outputs, freeze_bn=args.freeze_bn, dropout_p=args.dropout_p, pooling=args.pooling, lp_p=args.lp_p) model = model.cuda() train_transform = Compose([ transforms.Resize(args.img_size, args.img_size), transforms.HorizontalFlip() if args.hflip else NoOp(), transforms.VerticalFlip() if args.vflip else NoOp(), transforms.ShiftScaleRotate( shift_limit=args.shift_limit, scale_limit=args.scale_limit, rotate_limit=args.rotate_limit, border_mode=cv2.BORDER_CONSTANT, value=0, p=args.shift_scale_rotate_p ) if args.shift_scale_rotate else NoOp(), transforms.RandomContrast( limit=args.contrast_limit, p=args.contrast_p ) if args.contrast else NoOp(), RandomErase() if args.random_erase else NoOp(), transforms.CenterCrop(args.crop_size, args.crop_size) if args.center_crop else NoOp(), ForegroundCenterCrop(args.crop_size) if args.foreground_center_crop else NoOp(), transforms.RandomCrop(args.crop_size, args.crop_size) if args.random_crop else NoOp(), transforms.Normalize(mean=model.mean, std=model.std), ToTensor(), ]) if args.img_type: stage_1_train_dir = 'processed/stage_1_train_%s' %args.img_type else: stage_1_train_dir = 'processed/stage_1_train' df = pd.read_csv('inputs/stage_1_train.csv') img_paths = np.array([stage_1_train_dir + '/' + '_'.join(s.split('_')[:-1]) + '.png' for s in df['ID']][::6]) labels = np.array([df.loc[c::6, 'Label'].values for c in range(6)]).T.astype('float32') df = df[::6] df['img_path'] = img_paths for c in range(6): df['label_%d' %c] = labels[:, c] df['ID'] = df['ID'].apply(lambda s: '_'.join(s.split('_')[:-1])) meta_df = pd.read_csv('processed/stage_1_train_meta.csv') meta_df['ID'] = meta_df['SOPInstanceUID'] test_meta_df = pd.read_csv('processed/stage_1_test_meta.csv') df = pd.merge(df, meta_df, how='left') patient_ids = meta_df['PatientID'].unique() test_patient_ids = test_meta_df['PatientID'].unique() if args.remove_test_patient_ids: patient_ids = np.array([s for s in patient_ids if not s in test_patient_ids]) train_img_paths = np.hstack(df[['img_path', 'PatientID']].groupby(['PatientID'])['img_path'].apply(np.array).loc[patient_ids].to_list()).astype('str') train_labels = [] for c in range(6): train_labels.append(np.hstack(df[['label_%d' %c, 'PatientID']].groupby(['PatientID'])['label_%d' %c].apply(np.array).loc[patient_ids].to_list())) train_labels = np.array(train_labels).T if args.resume: checkpoint = torch.load('models/%s/checkpoint.pth.tar' % args.name) # train train_set = Dataset( train_img_paths, train_labels, transform=train_transform) train_loader = torch.utils.data.DataLoader( train_set, batch_size=args.batch_size, shuffle=True, num_workers=args.num_workers, # pin_memory=True, ) if args.optimizer == 'Adam': optimizer = optim.Adam( filter(lambda p: p.requires_grad, model.parameters()), lr=args.lr, weight_decay=args.weight_decay) elif args.optimizer == 'AdamW': optimizer = optim.AdamW( filter(lambda p: p.requires_grad, model.parameters()), lr=args.lr, weight_decay=args.weight_decay) elif args.optimizer == 'RAdam': optimizer = RAdam( filter(lambda p: p.requires_grad, model.parameters()), lr=args.lr, weight_decay=args.weight_decay) elif args.optimizer == 'SGD': optimizer = optim.SGD(filter(lambda p: p.requires_grad, model.parameters()), lr=args.lr, momentum=args.momentum, weight_decay=args.weight_decay, nesterov=args.nesterov) else: raise NotImplementedError if args.apex: amp.initialize(model, optimizer, opt_level='O1') if args.scheduler == 'CosineAnnealingLR': scheduler = lr_scheduler.CosineAnnealingLR( optimizer, T_max=args.epochs, eta_min=args.min_lr) elif args.scheduler == 'MultiStepLR': scheduler = lr_scheduler.MultiStepLR(optimizer, milestones=[int(e) for e in args.milestones.split(',')], gamma=args.gamma) else: raise NotImplementedError log = { 'epoch': [], 'loss': [], } start_epoch = 0 if args.resume: model.load_state_dict(checkpoint['state_dict']) optimizer.load_state_dict(checkpoint['optimizer']) scheduler.load_state_dict(checkpoint['scheduler']) start_epoch = checkpoint['epoch'] log = pd.read_csv('models/%s/log.csv' % args.name).to_dict(orient='list') for epoch in range(start_epoch, args.epochs): print('Epoch [%d/%d]' % (epoch + 1, args.epochs)) # train for one epoch train_loss = train(args, train_loader, model, criterion, optimizer, epoch) if args.scheduler == 'CosineAnnealingLR': scheduler.step() print('loss %.4f' % (train_loss)) log['epoch'].append(epoch) log['loss'].append(train_loss) pd.DataFrame(log).to_csv('models/%s/log.csv' % args.name, index=False) torch.save(model.state_dict(), 'models/%s/model.pth' % args.name) print("=> saved model") state = { 'epoch': epoch + 1, 'state_dict': model.state_dict(), 'optimizer': optimizer.state_dict(), 'scheduler': scheduler.state_dict(), } torch.save(state, 'models/%s/checkpoint.pth.tar' % args.name)
def augment(im, params=None): """ Perform data augmentation on some image using the albumentations package. Parameters ---------- im : Numpy array params : dict or None Contains the data augmentation parameters Mandatory keys: - h_flip ([0,1] float): probability of performing an horizontal left-right mirroring. - v_flip ([0,1] float): probability of performing an vertical up-down mirroring. - rot ([0,1] float): probability of performing a rotation to the image. - rot_lim (int): max degrees of rotation. - stretch ([0,1] float): probability of randomly stretching an image. - crop ([0,1] float): randomly take an image crop. - zoom ([0,1] float): random zoom applied to crop_size. --> Therefore the effective crop size at each iteration will be a random number between 1 and crop*(1-zoom). For example: * crop=1, zoom=0: no crop of the image * crop=1, zoom=0.1: random crop of random size between 100% image and 90% of the image * crop=0.9, zoom=0.1: random crop of random size between 90% image and 80% of the image * crop=0.9, zoom=0: random crop of always 90% of the image Image size refers to the size of the shortest side. - blur ([0,1] float): probability of randomly blurring an image. - pixel_noise ([0,1] float): probability of randomly adding pixel noise to an image. - pixel_sat ([0,1] float): probability of randomly using HueSaturationValue in the image. - cutout ([0,1] float): probability of using cutout in the image. Returns ------- Numpy array """ ## 1) Crop the image effective_zoom = np.random.rand() * params['zoom'] crop = params['crop'] - effective_zoom ly, lx, channels = im.shape crop_size = int(crop * min([ly, lx])) rand_x = np.random.randint(low=0, high=lx - crop_size + 1) rand_y = np.random.randint(low=0, high=ly - crop_size + 1) crop = transforms.Crop(x_min=rand_x, y_min=rand_y, x_max=rand_x + crop_size, y_max=rand_y + crop_size) im = crop(image=im)['image'] ## 2) Now add the transformations for augmenting the image pixels transform_list = [] # Add random stretching if params['stretch']: transform_list.append( imgaug_transforms.IAAPerspective(scale=0.1, p=params['stretch'])) # Add random rotation if params['rot']: transform_list.append( transforms.Rotate(limit=params['rot_lim'], p=params['rot'])) # Add horizontal flip if params['h_flip']: transform_list.append(transforms.HorizontalFlip(p=params['h_flip'])) # Add vertical flip if params['v_flip']: transform_list.append(transforms.VerticalFlip(p=params['v_flip'])) # Add some blur to the image if params['blur']: transform_list.append( albumentations.OneOf([ transforms.MotionBlur(blur_limit=7, p=1.), transforms.MedianBlur(blur_limit=7, p=1.), transforms.Blur(blur_limit=7, p=1.), ], p=params['blur'])) # Add pixel noise if params['pixel_noise']: transform_list.append( albumentations.OneOf( [ transforms.CLAHE(clip_limit=2, p=1.), imgaug_transforms.IAASharpen(p=1.), imgaug_transforms.IAAEmboss(p=1.), transforms.RandomBrightnessContrast(contrast_limit=0, p=1.), transforms.RandomBrightnessContrast(brightness_limit=0, p=1.), transforms.RGBShift(p=1.), transforms.RandomGamma(p=1.) #, # transforms.JpegCompression(), # transforms.ChannelShuffle(), # transforms.ToGray() ], p=params['pixel_noise'])) # Add pixel saturation if params['pixel_sat']: transform_list.append( transforms.HueSaturationValue(p=params['pixel_sat'])) # Remove randomly remove some regions from the image if params['cutout']: ly, lx, channels = im.shape scale_low, scale_high = 0.05, 0.25 # min and max size of the squares wrt the full image scale = np.random.uniform(scale_low, scale_high) transform_list.append( transforms.Cutout(num_holes=8, max_h_size=int(scale * ly), max_w_size=int(scale * lx), p=params['cutout'])) # Compose all image transformations and augment the image augmentation_fn = albumentations.Compose(transform_list) im = augmentation_fn(image=im)['image'] return im
def augment(im, params=None): """ Perform data augmentation on some image using the albumentations package. Parameters ---------- im : Numpy array params : dict or None Contains the data augmentation parameters Mandatory keys: - h_flip ([0,1] float): probability of performing an horizontal left-right mirroring. - v_flip ([0,1] float): probability of performing an vertical up-down mirroring. - rot ([0,1] float): probability of performing a rotation to the image. - rot_lim (int): max degrees of rotation. - stretch ([0,1] float): probability of randomly stretching an image. - expand ([True, False] bool): whether to pad the image to a square shape with background color canvas. - crop ([0,1] float): randomly take an image crop. - invert_col ([0, 1] float): randomly invert the colors of the image. p=1 -> invert colors (VPR) - zoom ([0,1] float): random zoom applied to crop_size. --> Therefore the effective crop size at each iteration will be a random number between 1 and crop*(1-zoom). For example: * crop=1, zoom=0: no crop of the image * crop=1, zoom=0.1: random crop of random size between 100% image and 90% of the image * crop=0.9, zoom=0.1: random crop of random size between 90% image and 80% of the image * crop=0.9, zoom=0: random crop of always 90% of the image Image size refers to the size of the shortest side. - blur ([0,1] float): probability of randomly blurring an image. - pixel_noise ([0,1] float): probability of randomly adding pixel noise to an image. - pixel_sat ([0,1] float): probability of randomly using HueSaturationValue in the image. - cutout ([0,1] float): probability of using cutout in the image. Returns ------- Numpy array """ ## 1) Expand the image by padding it with bg-color canvas if params["expand"]: desired_size = max(im.shape) # check bg if np.argmax(im.shape) > 0: bgcol = tuple(np.repeat(int(np.mean(im[[0, -1], :, :])), 3)) else: bgcol = tuple(np.repeat(int(np.mean(im[:, [0, -1], :])), 3)) im = Image.fromarray(im) old_size = im.size # old_size[0] is in (width, height) format ratio = float(desired_size) / max(old_size) new_size = tuple([int(x * ratio) for x in old_size]) im = im.resize(new_size, Image.ANTIALIAS) # create a new image and paste the resized on it new_im = Image.new("RGB", (desired_size, desired_size), color=bgcol) new_im.paste(im, ((desired_size - new_size[0]) // 2, (desired_size - new_size[1]) // 2)) im = np.array(new_im) ## 2) Crop the image if params["crop"] and params["crop"] != 1: effective_zoom = np.random.rand() * params['zoom'] crop = params['crop'] - effective_zoom ly, lx, channels = im.shape crop_size = int(crop * min([ly, lx])) rand_x = np.random.randint(low=0, high=lx - crop_size + 1) rand_y = np.random.randint(low=0, high=ly - crop_size + 1) crop = transforms.Crop(x_min=rand_x, y_min=rand_y, x_max=rand_x + crop_size, y_max=rand_y + crop_size) im = crop(image=im)['image'] if params["enhance"]: im = Image.fromarray(im) enhancer = ImageEnhance.Contrast(im) im = np.array(enhancer.enhance(params["enhance"])) ## 3) Now add the transformations for augmenting the image pixels transform_list = [] if params['invert_col']: transform_list.append(transforms.InvertImg(p=params['invert_col'])) # Add random stretching if params['stretch']: transform_list.append( imgaug_transforms.IAAPerspective(scale=0.1, p=params['stretch'])) # Add random rotation if params['rot']: transform_list.append( transforms.Rotate(limit=params['rot_lim'], p=params['rot'])) # Add horizontal flip if params['h_flip']: transform_list.append(transforms.HorizontalFlip(p=params['h_flip'])) # Add vertical flip if params['v_flip']: transform_list.append(transforms.VerticalFlip(p=params['v_flip'])) # Add some blur to the image if params['blur']: transform_list.append( albumentations.OneOf([ transforms.MotionBlur(blur_limit=7, p=1.), transforms.MedianBlur(blur_limit=7, p=1.), transforms.Blur(blur_limit=7, p=1.), ], p=params['blur'])) # Add pixel noise if params['pixel_noise']: transform_list.append( albumentations.OneOf( [ transforms.CLAHE(clip_limit=2, p=1.), imgaug_transforms.IAASharpen(p=1.), imgaug_transforms.IAAEmboss(p=1.), transforms.RandomBrightnessContrast(contrast_limit=0, p=1.), transforms.RandomBrightnessContrast(brightness_limit=0, p=1.), transforms.RGBShift(p=1.), transforms.RandomGamma(p=1.) #, # transforms.JpegCompression(), # transforms.ChannelShuffle(), # transforms.ToGray() ], p=params['pixel_noise'])) # Add pixel saturation if params['pixel_sat']: transform_list.append( transforms.HueSaturationValue(p=params['pixel_sat'])) # Remove randomly remove some regions from the image if params['cutout']: ly, lx, channels = im.shape scale_low, scale_high = 0.05, 0.25 # min and max size of the squares wrt the full image scale = np.random.uniform(scale_low, scale_high) transform_list.append( transforms.Cutout(num_holes=8, max_h_size=int(scale * ly), max_w_size=int(scale * lx), p=params['cutout'])) # Compose all image transformations and augment the image augmentation_fn = albumentations.Compose(transform_list) im = augmentation_fn(image=im)['image'] return im