def process_full_image(image_name, output, multi_run, dataset_folder, class_encodings, post_process): """ Helper function to save the output during testing Parameters ---------- meanIU.avg : float MeanIU of the model of the evaluated split multi_run : image_name: str name of the image that is saved output: numpy matrix of size [#C x H x W] output image at full size dataset_folder: str path to the dataset folder post_process : Boolean apply post-processing to the output of the network Returns ------- mean_iu : float mean iu of this image """ # Load GT with open(os.path.join(dataset_folder, "test", "gt", image_name), 'rb') as f: with Image.open(f) as img: gt = np.array(img) # Get predictions if post_process: # Load original image with open(os.path.join(dataset_folder, "test", "data", image_name[:-4] + ".JPG"), 'rb') as f: with Image.open(f) as img: original_image = np.array(img) # Apply CRF # prediction = crf(original_image, output) # output_encoded = output_to_class_encodings(prediction, class_encodings, perform_argmax=False) else: prediction = np.argmax(output, axis=0) output_encoded = output_to_class_encodings(output, class_encodings) # Get boundary pixels and adjust the gt_image for the border pixel -> set to background (1) boundary_mask = gt[:, :, 0].astype(np.uint8) == 128 # Get the ground truth mapping and filter their values for the boundary pixels target = np.argmax(gt_to_one_hot(gt, class_encodings).numpy(), axis=0) target[np.logical_and.reduce([boundary_mask, prediction != target, prediction == 0])] = 0 # NOTE: here 0 is 0x1 because it works on the index! # Compute and record the meanIU of the whole image _, _, mean_iu, _ = accuracy_segmentation(target, prediction, len(class_encodings)) scalar_label = 'output_{}'.format(image_name) if multi_run is None else 'output_{}_{}'.format(multi_run, image_name) _save_output_evaluation(class_encodings, output_encoded=output_encoded, gt_image=gt, tag=scalar_label, multi_run=multi_run) return mean_iu
def train_one_mini_batch(model, criterion, optimizer, input_var, target_var_argmax, loss_meter, meanIU_meter, num_classes): """ This routing train the model passed as parameter for one mini-batch Parameters ---------- num_classes: model : torch.nn.module The network model being used. criterion : torch.nn.loss The loss function used to compute the loss of the model. optimizer : torch.optim The optimizer used to perform the weight update. input_var : torch.autograd.Variable The input data for the mini-batch target_var_argmax : torch.autograd.Variable The target data (labels) for the mini-batch loss_meter : AverageMeter Tracker for the overall loss meanIU_meter : AverageMeter Tracker for the overall meanIU Returns ------- acc : float Accuracy for this mini-batch loss : float Loss for this mini-batch """ # Compute output output = model(input_var) # Compute and record the loss loss = criterion(output, target_var_argmax) try: loss_meter.update(loss.item(), len(input_var)) except AttributeError: loss_meter.update(loss.data[0], len(input_var)) output_argmax = np.array( [np.argmax(o, axis=0) for o in output.data.cpu().numpy()]) target_argmax = target_var_argmax.data.cpu().numpy() # Compute and record the accuracy _, _, mean_iu, _ = accuracy_segmentation(target_argmax, output_argmax, num_classes) meanIU_meter.update(mean_iu, input_var.size(0)) # Reset gradient optimizer.zero_grad() # Compute gradients loss.backward() # Perform a step by updating the weights optimizer.step() # return acc, loss return mean_iu, loss
def validate(val_loader, model, criterion, writer, epoch, class_encodings, no_cuda=False, log_interval=10, **kwargs): """ The evaluation routine Parameters ---------- val_loader : torch.utils.data.DataLoader The dataloader of the evaluation set model : torch.nn.module The network model being used criterion: torch.nn.loss The loss function used to compute the loss of the model writer : tensorboardX.writer.SummaryWriter The tensorboard writer object. Used to log values on file for the tensorboard visualization. epoch : int Number of the epoch (for logging purposes) class_encodings : List Contains the classes (range of ints) no_cuda : boolean Specifies whether the GPU should be used or not. A value of 'True' means the CPU will be used. log_interval : int Interval limiting the logging of mini-batches. Default value of 10. Returns ------- meanIU.avg : float MeanIU of the model of the evaluated split """ # 'Run' is injected in kwargs at runtime IFF it is a multi-run event multi_run = kwargs['run'] if 'run' in kwargs else None num_classes = len(class_encodings) # Instantiate the counters batch_time = AverageMeter() losses = AverageMeter() meanIU = AverageMeter() data_time = AverageMeter() # Switch to evaluate mode (turn off dropout & such ) model.eval() # Iterate over whole evaluation set end = time.time() pbar = tqdm(enumerate(val_loader), total=len(val_loader), unit='batch', ncols=150, leave=False) for batch_idx, (input, target) in pbar: # Measure data loading time data_time.update(time.time() - end) # Moving data to GPU if not no_cuda: input = input.cuda(non_blocking=True) target = target.cuda(non_blocking=True) # Compute output output = model(input) # Compute and record the loss loss = criterion(output, target) losses.update(loss.item(), input.size(0)) # Compute and record the accuracy _, _, mean_iu_batch, _ = accuracy_segmentation(target.cpu().numpy(), get_argmax(output), num_classes) meanIU.update(mean_iu_batch, input.size(0)) # Add loss and meanIU to Tensorboard scalar_label = 'val/mb_loss' if multi_run is None else 'val/mb_loss_{}'.format(multi_run) writer.add_scalar(scalar_label, loss.item(), epoch * len(val_loader) + batch_idx) scalar_label = 'val/mb_meanIU' if multi_run is None else 'val/mb_meanIU_{}'.format(multi_run) writer.add_scalar(scalar_label, mean_iu_batch, epoch * len(val_loader) + batch_idx) # Measure elapsed time batch_time.update(time.time() - end) end = time.time() if batch_idx % log_interval == 0: pbar.set_description('val epoch [{0}][{1}/{2}]\t'.format(epoch, batch_idx, len(val_loader))) pbar.set_postfix(Time='{batch_time.avg:.3f}\t'.format(batch_time=batch_time), Loss='{loss.avg:.4f}\t'.format(loss=losses), meanIU='{meanIU.avg:.3f}\t'.format(meanIU=meanIU), Data='{data_time.avg:.3f}\t'.format(data_time=data_time)) # Logging the epoch-wise meanIU scalar_label = 'val/meanIU' if multi_run is None else 'val/meanIU_{}'.format(multi_run) writer.add_scalar(scalar_label, meanIU.avg, epoch) logging.info(_prettyprint_logging_label("val") + ' epoch[{}]: ' 'MeanIU={meanIU.avg:.3f}\t' 'Loss={loss.avg:.4f}\t' 'Batch time={batch_time.avg:.3f} ({data_time.avg:.3f} to load data)' .format(epoch, batch_time=batch_time, data_time=data_time, loss=losses, meanIU=meanIU)) return meanIU.avg
def test(test_loader, model, criterion, writer, epoch, class_encodings, img_names_sizes_dict, dataset_folder, post_process, no_cuda=False, log_interval=10, **kwargs): """ The evaluation routine Parameters ---------- img_names_sizes_dict: dictionary {str: (int, int)} Key: gt image name (with extension), Value: image size test_loader : torch.utils.data.DataLoader The dataloader of the evaluation set model : torch.nn.module The network model being used criterion: torch.nn.loss The loss function used to compute the loss of the model writer : tensorboardX.writer.SummaryWriter The tensorboard writer object. Used to log values on file for the tensorboard visualization. epoch : int Number of the epoch (for logging purposes) class_encodings : List Contains the range of encoded classes img_names_sizes_dict # TODO dataset_folder : str # TODO post_process : Boolean apply post-processing to the output of the network no_cuda : boolean Specifies whether the GPU should be used or not. A value of 'True' means the CPU will be used. log_interval : int Interval limiting the logging of mini-batches. Default value of 10. Returns ------- meanIU.avg : float MeanIU of the model of the evaluated split """ # 'Run' is injected in kwargs at runtime IFF it is a multi-run event multi_run = kwargs['run'] if 'run' in kwargs else None num_classes = len(class_encodings) # Instantiate the counters batch_time = AverageMeter() losses = AverageMeter() meanIU = AverageMeter() data_time = AverageMeter() # Switch to evaluate mode (turn off dropout & such ) model.eval() # Iterate over whole evaluation set end = time.time() # Need to store the images currently being processes canvas = {} pbar = tqdm(enumerate(test_loader), total=len(test_loader), unit='batch', ncols=150, leave=False) for batch_idx, (input, target) in pbar: # Unpack input input, top_left_coordinates, test_img_names = input # Measure data loading time data_time.update(time.time() - end) # Moving data to GPU if not no_cuda: input = input.cuda(non_blocking=True) target = target.cuda(non_blocking=True) # Compute output output = model(input) # Compute and record the loss loss = criterion(output, target) losses.update(loss.item(), input.size(0)) # Compute and record the batch meanIU _, _, mean_iu_batch, _ = accuracy_segmentation(target.cpu().numpy(), get_argmax(output), num_classes) # Add loss and meanIU to Tensorboard scalar_label = 'test/mb_loss' if multi_run is None else 'test/mb_loss_{}'.format(multi_run) writer.add_scalar(scalar_label, loss.item(), epoch * len(test_loader) + batch_idx) scalar_label = 'test/mb_meanIU' if multi_run is None else 'test/mb_meanIU_{}'.format(multi_run) writer.add_scalar(scalar_label, mean_iu_batch, epoch * len(test_loader) + batch_idx) # Measure elapsed time batch_time.update(time.time() - end) end = time.time() if batch_idx % log_interval == 0: pbar.set_description('test epoch [{0}][{1}/{2}]\t'.format(epoch, batch_idx, len(test_loader))) pbar.set_postfix(Time='{batch_time.avg:.3f}\t'.format(batch_time=batch_time), Loss='{loss.avg:.4f}\t'.format(loss=losses), meanIU='{meanIU.avg:.3f}\t'.format(meanIU=meanIU), Data='{data_time.avg:.3f}\t'.format(data_time=data_time)) # Output needs to be patched together to form the complete output of the full image # patches are returned as a sliding window over the full image, overlapping sections are averaged for patch, x, y, img_name in zip(output.data.cpu().numpy(), top_left_coordinates[0].numpy(), top_left_coordinates[1].numpy(), test_img_names): # Is a new image? if not img_name in canvas: # Create a new image of the right size filled with NaNs canvas[img_name] = np.empty((num_classes, *img_names_sizes_dict[img_name])) canvas[img_name].fill(np.nan) # Add the patch to the image canvas[img_name] = merge_patches(patch, (x, y), canvas[img_name]) # Save the image when done if not np.isnan(np.sum(canvas[img_name])): # Save the final image mean_iu = process_full_image(img_name, canvas[img_name], multi_run, dataset_folder, class_encodings, post_process) # Update the meanIU meanIU.update(mean_iu, 1) # Remove the entry canvas.pop(img_name) logging.info("\nProcessed image {} with mean IU={}".format(img_name, mean_iu)) # Canvas MUST be empty or something was wrong with coverage of all images assert len(canvas) == 0 # Logging the epoch-wise meanIU scalar_label = 'test/mb_meanIU' if multi_run is None else 'test/mb_meanIU_{}'.format(multi_run) writer.add_scalar(scalar_label, meanIU.avg, epoch) logging.info(_prettyprint_logging_label("test") + ' epoch[{}]: ' 'MeanIU={meanIU.avg:.3f}\t' 'Loss={loss.avg:.4f}\t' 'Batch time={batch_time.avg:.3f} ({data_time.avg:.3f} to load data)' .format(epoch, batch_time=batch_time, data_time=data_time, loss=losses, meanIU=meanIU)) return meanIU.avg
def process_full_image(image_name, output, multi_run, dataset_folder, class_encodings, post_process): """ Helper function to save the output during testing Parameters ---------- meanIU.avg : float MeanIU of the model of the evaluated split multi_run : image_name: str name of the image that is saved output: numpy matrix of size [#C x H x W] output image at full size dataset_folder: str path to the dataset folder post_process : Boolean apply post-processing to the output of the network Returns ------- mean_iu : float mean iu of this image """ # Load GT with open(os.path.join(dataset_folder, "test", "gt", image_name), 'rb') as f: with Image.open(f) as img: gt = np.array(img) # Get predictions if post_process: # Load original image with open( os.path.join(dataset_folder, "test", "data", image_name[:-4] + ".JPG"), 'rb') as f: with Image.open(f) as img: original_image = np.array(img) # # Apply CRF # prediction = crf(original_image, output) # output_encoded = output_to_class_encodings(prediction, class_encodings, perform_argmax=False) else: prediction = np.argmax(output, axis=0) output_encoded = output_to_class_encodings(output, class_encodings) # Get the ground truth mapping target = np.argmax(gt_to_one_hot(gt, class_encodings).numpy(), axis=0) # Compute and record the meanIU of the whole image _, _, mean_iu, _ = accuracy_segmentation(target, prediction, len(class_encodings)) scalar_label = 'output_{}'.format( image_name) if multi_run is None else 'output_{}_{}'.format( multi_run, image_name) _save_output_evaluation(class_encodings, output_encoded=output_encoded, tag=scalar_label, multi_run=multi_run) return mean_iu