def __init__( self, model_path='../model/deepglobe_deeplabv3_weights-cityscapes_19-outputs/model.pth', dataset='deepglobe', output_channels=19, split='valid', net_type='deeplab', batch_size=1, shuffle=True): """ Initializes the tester by loading the model with the good parameters. :param model_path: Path to model weights :param dataset: dataset used amongst {'deepglobe', 'pascal', 'cityscapes'} :param output_channels: num of output channels of model :param split: split to be used amongst {'train', 'valid'} :param net_type: model type to be used amongst {'deeplab', 'unet'} :param batch_size: batch size when loading images (always 1 here) :param shuffle: when loading images from dataset """ print('[Tester] [Init] Initializing tester...') self.dataset = dataset self.model_path = model_path # Load model print('[Tester] [Init] Loading model ' + model_path + ' with ' + str(output_channels) + ' output channels...') self.device = torch.device( 'cuda:0' if torch.cuda.is_available() else 'cpu') self.model = SPPNet(output_channels=output_channels).to(self.device) param = torch.load(model_path) self.model.load_state_dict(param) del param # Create data loader depending on dataset, split and net type if dataset == 'pascal': self.valid_dataset = PascalVocDataset(split=split, net_type=net_type) elif dataset == 'cityscapes': self.valid_dataset = CityscapesDataset(split=split, net_type=net_type) elif dataset == 'deepglobe': self.valid_dataset = DeepGlobeDataset(split=split, net_type=net_type) else: raise NotImplementedError self.valid_loader = DataLoader(self.valid_dataset, batch_size=batch_size, shuffle=shuffle) print('[Tester] [Init] ...done!') print('[Tester] [Init] Tester created.')
def __init__( self, model_path='../model/deepglobe_deeplabv3_weights-cityscapes_19-outputs/model.pth', dataset='deepglobe', output_channels=19, split='valid', net_type='deeplab', batch_size=1, shuffle=True): print('[Score Calculator] Initializing calculator...') self.dataset = dataset self.model_path = model_path self.net_type = net_type self.fp16 = True # Load model print('[Score Calculator] Loading model ' + model_path + ' with ' + str(output_channels) + ' output channels...') self.device = torch.device( 'cuda:0' if torch.cuda.is_available() else 'cpu') self.model = SPPNet(output_channels=output_channels).to(self.device) param = torch.load(model_path) self.model.load_state_dict(param) del param # Create data loader depending on dataset, split and net type if dataset == 'pascal': self.valid_dataset = PascalVocDataset(split=split, net_type=net_type) self.classes = np.arange(1, 22) elif dataset == 'cityscapes': self.valid_dataset = CityscapesDataset(split=split, net_type=net_type) self.classes = np.arange(1, 20) elif dataset == 'deepglobe': self.valid_dataset = DeepGlobeDataset(split=split, net_type=net_type) self.classes = np.arange(1, 8) else: raise NotImplementedError self.valid_loader = DataLoader(self.valid_dataset, batch_size=batch_size, shuffle=shuffle) # fp16 if self.fp16: from utils.apex.apex.fp16_utils.fp16util import BN_convert_float self.model = BN_convert_float(self.model.half()) print('[Score Calculator] fp16 applied') print('[Score Calculator] ...done!') print('[Score Calculator] Calculator created.')
def load_model(output_channels=2, model_path='../model/sherbrooke_deeplabv3p_lgpu30-2/model.pth'): ''' Returns torch model with pretrained weights :param output_channels: :param model_path: :return: ''' model_path = Path(model_path) path, model_dir = os.path.split(model_path.parent) # separate path and filename device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') #work on GPU if available print(f'Device: {device}') if 'mnv2' in model_dir: model = SPPNet(enc_type='mobilenetv2', dec_type = 'maspp', output_channels = output_channels).to(device) else: model = SPPNet(output_channels=output_channels).to(device) if device == torch.device('cpu'): param = torch.load(model_path, map_location='cpu') # parameters saved in checkpoint via model_path else: param = torch.load(model_path) # parameters saved in checkpoint via model_path print(f'Parameters loaded from {model_path}') model.load_state_dict(param) #apply method load_state_dict to model? del param # why delete parameters? Reduce memory usage? return model
def load_model(out_channels=2, enc_type='efficientnet', dec_type='unet', pretrained=True, output_stride=8): # Network global net_type if 'unet' in dec_type: net_type = 'unet' if 'efficient' in enc_type: model = EfficientUnet(enc_type, out_channels=out_channels, concat_input=True, pretrained=pretrained)#, model_name=enc_type) else: model = EncoderDecoderNet(**net_config) else: net_type = 'deeplab' model = SPPNet(output_channels=out_channels, enc_type=enc_type, dec_type=dec_type, output_stride=output_stride) return model
import albumentations as albu import cv2 import datetime import sys import argparse parser = argparse.ArgumentParser(description='Freespace detection module') parser.add_argument("video_path", help = "video file tor run segmentation on" ) parser.add_argument("--bs", dest = "batch_size", default = 1, type = int, help="number of sample per batch") parser.add_argument("--dim", dest = "input_dim", help = "Input resolution of the network. Increase to increase accuracy. Decrease to increase speed", default = 256, type = int) parser.add_argument("--dev", dest = "device_id", help = "ID of graphic card device", default = '0') args = parser.parse_args() print("Loading network...") device = torch.device('cuda:'+args.device_id if torch.cuda.is_available() else 'cpu') model = SPPNet(output_channels=10, enc_type='xception65', dec_type='aspp').to(device) model_path = '../model/bdd100k_deeplabv3p_xception65_total/model_tmp.pth' print("Setting the parameters...") param = torch.load(model_path, map_location='cuda:1') model.load_state_dict(param) del param print("Setting hyper parameter...") batch_size = int(args.batch_size) dim = int(args.input_dim) resizer = albu.Compose([albu.Resize(height=dim, width=dim)]) print("Setting up the model in evalutation mode...") model.eval() print("Loading video...") videofile = args.video_path cap = cv2.VideoCapture(videofile)
import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import torch import torch.nn.functional as F from torch.utils.data import DataLoader from models.net import SPPNet from dataset.cityscapes import CityscapesDataset from utils.preprocess import minmax_normalize device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') model = SPPNet(output_channels=19).to(device) model_path = '../model/cityscapes_deeplab_v3_plus/model.pth' param = torch.load(model_path) model.load_state_dict(param) del param batch_size = 1 valid_dataset = CityscapesDataset(split='valid', preprocess='deeplab') valid_loader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=True) images_list = [] labels_list = [] preds_list = [] model.eval()
import matplotlib.pyplot as plt import torch import torch.nn.functional as F from torch.utils.data import DataLoader from models.net import SPPNet from dataset.cityscapes import CityscapesDataset from utils.preprocess import minmax_normalize import datetime from torchsummary import summary device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') #model = SPPNet(output_channels=19).to(device) model = SPPNet(output_channels=19, enc_type='mobilenetv2', dec_type='maspp').to(device) summary(model, (3, 128, 256)) #model_path = '../model/cityscapes_deeplab_v3_plus/model.pth' #model_path = '../model/cityscapes_mobilenetv2/model.pth' model_path = '../model/cityscapes_deeplabv3p_mobilenetv2/model_tmp.pth' param = torch.load(model_path) model.load_state_dict(param) del param batch_size = 1 valid_dataset = CityscapesDataset(split='valid', net_type='deeplab') valid_loader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=True) images_list = [] labels_list = []
def convert_xception65(ckpt_path, num_classes): def conv_converter(pt_layer, tf_layer_name, depthwise=False, bias=False): if depthwise: pt_layer.weight.data = torch.Tensor( reader.get_tensor( f'{tf_layer_name}/depthwise_weights').transpose( 2, 3, 0, 1)) else: pt_layer.weight.data = torch.Tensor( reader.get_tensor(f'{tf_layer_name}/weights').transpose( 3, 2, 0, 1)) if bias: pt_layer.bias.data = torch.Tensor( reader.get_tensor(f'{tf_layer_name}/biases')) def bn_converter(pt_layer, tf_layer_name): pt_layer.bias.data = torch.Tensor( reader.get_tensor(f'{tf_layer_name}/beta')) pt_layer.weight.data = torch.Tensor( reader.get_tensor(f'{tf_layer_name}/gamma')) pt_layer.running_mean.data = torch.Tensor( reader.get_tensor(f'{tf_layer_name}/moving_mean')) pt_layer.running_var.data = torch.Tensor( reader.get_tensor(f'{tf_layer_name}/moving_variance')) def sepconv_converter(pt_layer, tf_layer_name): conv_converter(pt_layer.depthwise, f'{tf_layer_name}_depthwise', True) bn_converter(pt_layer.bn_depth, f'{tf_layer_name}_depthwise/BatchNorm') conv_converter(pt_layer.pointwise, f'{tf_layer_name}_pointwise') bn_converter(pt_layer.bn_point, f'{tf_layer_name}_pointwise/BatchNorm') def block_converter(pt_block, tf_block_name): if pt_block.skip_connection_type == 'conv': conv_converter(pt_block.conv, f'{tf_block_name}/shortcut') bn_converter(pt_block.bn, f'{tf_block_name}/shortcut/BatchNorm') sepconv_converter(pt_block.sep_conv1.block, f'{tf_block_name}/separable_conv1') sepconv_converter(pt_block.sep_conv2.block, f'{tf_block_name}/separable_conv2') sepconv_converter(pt_block.sep_conv3.block, f'{tf_block_name}/separable_conv3') reader = tf.train.NewCheckpointReader(ckpt_path) model = SPPNet(num_classes, enc_type='xception65', dec_type='aspp', output_stride=8) # Xception ## Entry flow conv_converter(model.encoder.conv1, 'xception_65/entry_flow/conv1_1') bn_converter(model.encoder.bn1, 'xception_65/entry_flow/conv1_1/BatchNorm') conv_converter(model.encoder.conv2, 'xception_65/entry_flow/conv1_2') bn_converter(model.encoder.bn2, 'xception_65/entry_flow/conv1_2/BatchNorm') block_converter(model.encoder.block1, 'xception_65/entry_flow/block1/unit_1/xception_module') block_converter(model.encoder.block2, 'xception_65/entry_flow/block2/unit_1/xception_module') block_converter(model.encoder.block3, 'xception_65/entry_flow/block3/unit_1/xception_module') ## Middle flow block_converter(model.encoder.block4, 'xception_65/middle_flow/block1/unit_1/xception_module') block_converter(model.encoder.block5, 'xception_65/middle_flow/block1/unit_2/xception_module') block_converter(model.encoder.block6, 'xception_65/middle_flow/block1/unit_3/xception_module') block_converter(model.encoder.block7, 'xception_65/middle_flow/block1/unit_4/xception_module') block_converter(model.encoder.block8, 'xception_65/middle_flow/block1/unit_5/xception_module') block_converter(model.encoder.block9, 'xception_65/middle_flow/block1/unit_6/xception_module') block_converter(model.encoder.block10, 'xception_65/middle_flow/block1/unit_7/xception_module') block_converter(model.encoder.block11, 'xception_65/middle_flow/block1/unit_8/xception_module') block_converter(model.encoder.block12, 'xception_65/middle_flow/block1/unit_9/xception_module') block_converter(model.encoder.block13, 'xception_65/middle_flow/block1/unit_10/xception_module') block_converter(model.encoder.block14, 'xception_65/middle_flow/block1/unit_11/xception_module') block_converter(model.encoder.block15, 'xception_65/middle_flow/block1/unit_12/xception_module') block_converter(model.encoder.block16, 'xception_65/middle_flow/block1/unit_13/xception_module') block_converter(model.encoder.block17, 'xception_65/middle_flow/block1/unit_14/xception_module') block_converter(model.encoder.block18, 'xception_65/middle_flow/block1/unit_15/xception_module') block_converter(model.encoder.block19, 'xception_65/middle_flow/block1/unit_16/xception_module') ## Exit flow block_converter(model.encoder.block20, 'xception_65/exit_flow/block1/unit_1/xception_module') block_converter(model.encoder.block21, 'xception_65/exit_flow/block2/unit_1/xception_module') # ASPP conv_converter(model.spp.aspp0.conv, 'aspp0') bn_converter(model.spp.aspp0.bn, 'aspp0/BatchNorm') sepconv_converter(model.spp.aspp1.block, 'aspp1') sepconv_converter(model.spp.aspp2.block, 'aspp2') sepconv_converter(model.spp.aspp3.block, 'aspp3') conv_converter(model.spp.image_pooling.conv, 'image_pooling') bn_converter(model.spp.image_pooling.bn, 'image_pooling/BatchNorm') conv_converter(model.spp.conv, 'concat_projection') bn_converter(model.spp.bn, 'concat_projection/BatchNorm') # Decoder conv_converter(model.decoder.conv, 'decoder/feature_projection0') bn_converter(model.decoder.bn, 'decoder/feature_projection0/BatchNorm') sepconv_converter(model.decoder.sep1.block, 'decoder/decoder_conv0') sepconv_converter(model.decoder.sep2.block, 'decoder/decoder_conv1') # Logits conv_converter(model.logits, 'logits/semantic', bias=True) return model
import numpy as np import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt import torch import torch.nn.functional as F from torch.utils.data import DataLoader from models.net import SPPNet from dataset.cityscapes import CityscapesDataset from utils.preprocess import minmax_normalize device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') model = SPPNet(output_channels=19).to(device) model_path = '../model/cityscapes_deeplab_v3_plus/model.pth' param = torch.load(model_path) model.load_state_dict(param) del param batch_size = 1 valid_dataset = CityscapesDataset(split='valid', net_type='deeplab') valid_loader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=True) images_list = [] labels_list = [] preds_list = [] model.eval()
def convert_mobilenetv2(ckpt_path, num_classes): def conv_converter(pt_layer, tf_layer_name, depthwise=False, bias=False): if depthwise: pt_layer.weight.data = torch.Tensor( reader.get_tensor( f'{tf_layer_name}/depthwise_weights').transpose( 2, 3, 0, 1)) else: pt_layer.weight.data = torch.Tensor( reader.get_tensor(f'{tf_layer_name}/weights').transpose( 3, 2, 0, 1)) if bias: pt_layer.bias.data = torch.Tensor( reader.get_tensor(f'{tf_layer_name}/biases')) def bn_converter(pt_layer, tf_layer_name): pt_layer.bias.data = torch.Tensor( reader.get_tensor(f'{tf_layer_name}/beta')) pt_layer.weight.data = torch.Tensor( reader.get_tensor(f'{tf_layer_name}/gamma')) pt_layer.running_mean.data = torch.Tensor( reader.get_tensor(f'{tf_layer_name}/moving_mean')) pt_layer.running_var.data = torch.Tensor( reader.get_tensor(f'{tf_layer_name}/moving_variance')) def block_converter(pt_layer, tf_layer_name): if hasattr(pt_layer, 'expand'): conv_converter(pt_layer.expand.conv, f'{tf_layer_name}/expand') bn_converter(pt_layer.expand.bn, f'{tf_layer_name}/expand/BatchNorm') conv_converter(pt_layer.depthwise.conv, f'{tf_layer_name}/depthwise', depthwise=True) bn_converter(pt_layer.depthwise.bn, f'{tf_layer_name}/depthwise/BatchNorm') conv_converter(pt_layer.project.conv, f'{tf_layer_name}/project') bn_converter(pt_layer.project.bn, f'{tf_layer_name}/project/BatchNorm') reader = tf.train.NewCheckpointReader(ckpt_path) model = SPPNet(num_classes, enc_type='mobilenetv2', dec_type='maspp') # MobileNetV2 conv_converter(model.encoder.conv, 'MobilenetV2/Conv') bn_converter(model.encoder.bn, 'MobilenetV2/Conv/BatchNorm') block_converter(model.encoder.block0, 'MobilenetV2/expanded_conv') block_converter(model.encoder.block1, 'MobilenetV2/expanded_conv_1') block_converter(model.encoder.block2, 'MobilenetV2/expanded_conv_2') block_converter(model.encoder.block3, 'MobilenetV2/expanded_conv_3') block_converter(model.encoder.block4, 'MobilenetV2/expanded_conv_4') block_converter(model.encoder.block5, 'MobilenetV2/expanded_conv_5') block_converter(model.encoder.block6, 'MobilenetV2/expanded_conv_6') block_converter(model.encoder.block7, 'MobilenetV2/expanded_conv_7') block_converter(model.encoder.block8, 'MobilenetV2/expanded_conv_8') block_converter(model.encoder.block9, 'MobilenetV2/expanded_conv_9') block_converter(model.encoder.block10, 'MobilenetV2/expanded_conv_10') block_converter(model.encoder.block11, 'MobilenetV2/expanded_conv_11') block_converter(model.encoder.block12, 'MobilenetV2/expanded_conv_12') block_converter(model.encoder.block13, 'MobilenetV2/expanded_conv_13') block_converter(model.encoder.block14, 'MobilenetV2/expanded_conv_14') block_converter(model.encoder.block15, 'MobilenetV2/expanded_conv_15') block_converter(model.encoder.block16, 'MobilenetV2/expanded_conv_16') # SPP conv_converter(model.spp.aspp0.conv, 'aspp0') bn_converter(model.spp.aspp0.bn, 'aspp0/BatchNorm') conv_converter(model.spp.image_pooling.conv, 'image_pooling') bn_converter(model.spp.image_pooling.bn, 'image_pooling/BatchNorm') conv_converter(model.spp.conv, 'concat_projection') bn_converter(model.spp.bn, 'concat_projection/BatchNorm') # Logits conv_converter(model.logits, 'logits/semantic', bias=True) return model
def process(config_path): gc.collect() torch.cuda.empty_cache() config = yaml.load(open(config_path)) net_config = config['Net'] data_config = config['Data'] train_config = config['Train'] loss_config = config['Loss'] opt_config = config['Optimizer'] device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') t_max = opt_config['t_max'] # Collect training parameters max_epoch = train_config['max_epoch'] batch_size = train_config['batch_size'] fp16 = train_config['fp16'] resume = train_config['resume'] pretrained_path = train_config['pretrained_path'] freeze_enabled = train_config['freeze'] seed_enabled = train_config['seed'] ######################################### # Deterministic training if seed_enabled: seed = 100 torch.manual_seed(seed) torch.cuda.manual_seed_all(seed) np.random.seed(seed=seed) import random random.seed(a=100) ######################################### # Network if 'unet' in net_config['dec_type']: net_type = 'unet' model = EncoderDecoderNet(**net_config) else: net_type = 'deeplab' net_config['output_channels'] = 19 model = SPPNet(**net_config) dataset = data_config['dataset'] if dataset == 'deepglobe-dynamic': from dataset.deepglobe_dynamic import DeepGlobeDatasetDynamic as Dataset net_config['output_channels'] = 7 classes = np.arange(0, 7) else: raise NotImplementedError del data_config['dataset'] modelname = config_path.stem timestamp = datetime.timestamp(datetime.now()) print("timestamp =", datetime.fromtimestamp(timestamp)) output_dir = Path(os.path.join(ROOT_DIR, f'model/{modelname}_{datetime.fromtimestamp(timestamp)}') ) output_dir.mkdir(exist_ok=True) log_dir = Path(os.path.join(ROOT_DIR, f'logs/{modelname}_{datetime.fromtimestamp(timestamp)}') ) log_dir.mkdir(exist_ok=True) dataset_dir= '/home/sfoucher/DEV/pytorch-segmentation/data/deepglobe_as_pascalvoc/VOCdevkit/VOC2012' logger = debug_logger(log_dir) logger.debug(config) logger.info(f'Device: {device}') logger.info(f'Max Epoch: {max_epoch}') # Loss loss_fn = MultiClassCriterion(**loss_config).to(device) params = model.parameters() optimizer, scheduler = create_optimizer(params, **opt_config) # history if resume: with open(log_dir.joinpath('history.pkl'), 'rb') as f: history_dict = pickle.load(f) best_metrics = history_dict['best_metrics'] loss_history = history_dict['loss'] iou_history = history_dict['iou'] start_epoch = len(iou_history) for _ in range(start_epoch): scheduler.step() else: start_epoch = 0 best_metrics = 0 loss_history = [] iou_history = [] affine_augmenter = albu.Compose([albu.HorizontalFlip(p=.5),albu.VerticalFlip(p=.5) # Rotate(5, p=.5) ]) # image_augmenter = albu.Compose([albu.GaussNoise(p=.5), # albu.RandomBrightnessContrast(p=.5)]) image_augmenter = None # This has been put in the loop for the dynamic training """ # Dataset train_dataset = Dataset(affine_augmenter=affine_augmenter, image_augmenter=image_augmenter, net_type=net_type, **data_config) valid_dataset = Dataset(split='valid', net_type=net_type, **data_config) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4, pin_memory=True, drop_last=True) valid_loader = DataLoader(valid_dataset, batch_size=1, shuffle=False, num_workers=4, pin_memory=True) """ # Pretrained model if pretrained_path: logger.info(f'Resume from {pretrained_path}') param = torch.load(pretrained_path) model.load_state_dict(param) model.logits = torch.nn.Conv2d(256, net_config['output_channels'], 1) del param # To device model = model.to(device) ######################################### if freeze_enabled: # Code de Rémi # Freeze layers for param_index in range(int((len(optimizer.param_groups[0]['params']))*0.5)): optimizer.param_groups[0]['params'][param_index].requires_grad = False ######################################### params_to_update = model.parameters() print("Params to learn:") if freeze_enabled: params_to_update = [] for name,param in model.named_parameters(): if param.requires_grad == True: params_to_update.append(param) print("\t",name) optimizer, scheduler = create_optimizer(params_to_update, **opt_config) # fp16 if fp16: # I only took the necessary files because I don't need the C backend of apex, # which is broken and can't be installed # from apex import fp16_utils from utils.apex.apex.fp16_utils.fp16util import BN_convert_float from utils.apex.apex.fp16_utils.fp16_optimizer import FP16_Optimizer # model = fp16_utils.BN_convert_float(model.half()) model = BN_convert_float(model.half()) # optimizer = fp16_utils.FP16_Optimizer(optimizer, verbose=False, dynamic_loss_scale=True) optimizer = FP16_Optimizer(optimizer, verbose=False, dynamic_loss_scale=True) logger.info('Apply fp16') # Restore model if resume: model_path = output_dir.joinpath(f'model_tmp.pth') logger.info(f'Resume from {model_path}') param = torch.load(model_path) model.load_state_dict(param) del param opt_path = output_dir.joinpath(f'opt_tmp.pth') param = torch.load(opt_path) optimizer.load_state_dict(param) del param i_iter = 0 ma_loss= 0 ma_iou= 0 # Train for i_epoch in range(start_epoch, max_epoch): logger.info(f'Epoch: {i_epoch}') logger.info(f'Learning rate: {optimizer.param_groups[0]["lr"]}') train_losses = [] train_ious = [] model.train() # Initialize randomized but balanced datasets train_dataset = Dataset(base_dir = dataset_dir, affine_augmenter=affine_augmenter, image_augmenter=image_augmenter, net_type=net_type, **data_config) valid_dataset = Dataset(base_dir = dataset_dir, split='valid', net_type=net_type, **data_config) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4, pin_memory=True, drop_last=True) valid_loader = DataLoader(valid_dataset, batch_size=1, shuffle=False, num_workers=4, pin_memory=True) with tqdm(train_loader) as _tqdm: for i, batched in enumerate(_tqdm): images, labels = batched if fp16: images = images.half() images, labels = images.to(device), labels.to(device) optimizer.zero_grad() preds = model(images) if net_type == 'deeplab': preds = F.interpolate(preds, size=labels.shape[1:], mode='bilinear', align_corners=True) if fp16: loss = loss_fn(preds.float(), labels) else: loss = loss_fn(preds, labels) preds_np = preds.detach().cpu().numpy() labels_np = labels.detach().cpu().numpy() iou = compute_iou_batch(np.argmax(preds_np, axis=1), labels_np, classes) _tqdm.set_postfix(OrderedDict(seg_loss=f'{loss.item():.5f}', iou=f'{iou:.3f}')) train_losses.append(loss.item()) train_ious.append(iou) ma_loss= 0.01*loss.item() + 0.99 * ma_loss ma_iou= 0.01*iou + 0.99 * ma_iou plotter.plot('loss', 'train', 'iteration Loss', i_iter, loss.item()) plotter.plot('iou', 'train', 'iteration iou', i_iter, iou) plotter.plot('loss', 'ma_loss', 'iteration Loss', i_iter, ma_loss) plotter.plot('iou', 'ma_iou', 'iteration iou', i_iter, ma_iou) if fp16: optimizer.backward(loss) else: loss.backward() optimizer.step() i_iter += 1 scheduler.step() train_loss = np.mean(train_losses) train_iou = np.nanmean(train_ious) logger.info(f'train loss: {train_loss}') logger.info(f'train iou: {train_iou}') plotter.plot('loss-epoch', 'train', 'iteration Loss', i_epoch, train_loss) plotter.plot('iou-epoch', 'train', 'iteration iou', i_epoch, train_iou) torch.save(model.state_dict(), output_dir.joinpath('model_tmp.pth')) torch.save(optimizer.state_dict(), output_dir.joinpath('opt_tmp.pth')) valid_losses = [] valid_ious = [] model.eval() with torch.no_grad(): with tqdm(valid_loader) as _tqdm: for batched in _tqdm: images, labels = batched if fp16: images = images.half() images, labels = images.to(device), labels.to(device) preds = model.tta(images, net_type=net_type) if fp16: loss = loss_fn(preds.float(), labels) else: loss = loss_fn(preds, labels) preds_np = preds.detach().cpu().numpy() labels_np = labels.detach().cpu().numpy() # I changed a parameter in the compute_iou method to prevent it from yielding nans iou = compute_iou_batch(np.argmax(preds_np, axis=1), labels_np, classes) _tqdm.set_postfix(OrderedDict(seg_loss=f'{loss.item():.5f}', iou=f'{iou:.3f}')) valid_losses.append(loss.item()) valid_ious.append(iou) valid_loss = np.mean(valid_losses) valid_iou = np.mean(valid_ious) logger.info(f'valid seg loss: {valid_loss}') logger.info(f'valid iou: {valid_iou}') plotter.plot('loss-epoch', 'valid', 'iteration Loss', i_epoch, valid_loss) plotter.plot('iou-epoch', 'valid', 'iteration iou', i_epoch, valid_iou) if best_metrics < valid_iou: best_metrics = valid_iou logger.info('Best Model!') torch.save(model.state_dict(), output_dir.joinpath('model.pth')) torch.save(optimizer.state_dict(), output_dir.joinpath('opt.pth')) loss_history.append([train_loss, valid_loss]) iou_history.append([train_iou, valid_iou]) history_ploter(loss_history, log_dir.joinpath('loss.png')) history_ploter(iou_history, log_dir.joinpath('iou.png')) history_dict = {'loss': loss_history, 'iou': iou_history, 'best_metrics': best_metrics} with open(log_dir.joinpath('history.pkl'), 'wb') as f: pickle.dump(history_dict, f)
output_dir.mkdir(exist_ok=True, parents=True) log_dir = Path('../logs').joinpath(modelname) log_dir.mkdir(exist_ok=True, parents=True) logger = debug_logger(log_dir) logger.info(f'Device: {device}') logger.info(f'Max Epoch: {max_epoch}') del data_config['dataset'] train_dataset = Dataset(split='train', **data_config) valid_dataset = Dataset(split='valid', **data_config) train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=4, pin_memory=True) valid_loader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=False, num_workers=4, pin_memory=True) if 'unet' in net_config['dec_type']: model = EncoderDecoderNet(**net_config).to(device) else: model = SPPNet(**net_config).to(device) loss_fn = CrossEntropy2d(**loss_config).to(device) optimizer, scheduler = create_optimizer(model=model, **opt_config) train()
from models.net import SPPNet from dataset.cityscapes import CityscapesDataset from dataset.bdd100k import BDD100KDataset from dataset.avm import AVMDataset from utils.preprocess import minmax_normalize import datetime from torchsummary import summary import cv2 device = torch.device('cuda:2' if torch.cuda.is_available() else 'cpu') torch.cuda.set_device(device) #model = SPPNet(output_channels=19).to(device) model = SPPNet(output_channels=4, enc_type='xception65', dec_type='aspp').to(device) summary(model, (3, 128, 256)) #model_path = '../model/cityscapes_deeplab_v3_plus/model.pth' #model_path = '../model/cityscapes_mobilenetv2/model.pth' #model_path = '../model/cityscapes_deeplabv3p_mobilenetv2/model_tmp.pth' #model_path = '../model/bdd100k_deeplabv3p_mobilenetv2/model_tmp.pth' model_path = '../model/avm_deeplabv3p_xception65/model_tmp.pth' #model_path = '../model/cityscapes_deeplabv3p_double_epoch/model.pth' param = torch.load(model_path) model.load_state_dict(param) del param batch_size = 1 #valid_dataset = BDD100KDataset(split='valid', net_type='deeplab') valid_dataset = AVMDataset(split='valid', net_type='deeplab')
def eval_from_model(split, output_channels, model_path, postproc=False, vis=True, debug=True): model_path = Path(model_path) path, model_dir = os.path.split( model_path.parent) # separate path and filename device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') #work on GPU if available print(f'Device: {device}') if 'mnv2' in model_dir: model = SPPNet(enc_type='mobilenetv2', dec_type='maspp', output_channels=output_channels).to(device) defaults = True else: model = SPPNet(output_channels=output_channels).to(device) defaults = False if device == torch.device('cpu'): param = torch.load(model_path, map_location='cpu' ) # parameters saved in checkpoint via model_path else: param = torch.load( model_path) # parameters saved in checkpoint via model_path print(f'Parameters loaded from {model_path}') model.load_state_dict(param) #apply method load_state_dict to model? del param # delete parameters? Reduce memory usage? dataset = SherbrookeDataset( split=split, net_type='deeplab', defaults=defaults) #reach cityscapes dataset, validation split classes = np.arange(1, dataset.n_classes) img_paths = dataset.img_paths base_dir = dataset.base_dir split = dataset.split if len(img_paths) == 0: raise ValueError('Your dataset seems empty...') else: print(f'{len(img_paths)} images found in {base_dir}\\{split}') model.eval() #apply eval method on model. ? #print(f'Files containing \'{filetype}\' will be converted to \'{colortype}\' colormap and saved to:\n{output_folder}') valid_ious = [] count = 0 predicted_boxes = {} ground_truth_boxes = {} with torch.no_grad(): #dataloader is a 2 element list with images and labels as torch tensors print('Generating predictions...') with tqdm(range(len(dataset))) as _tqdm: for i in _tqdm: count += 1 image, label = dataset[i] img_path = dataset.img_paths[i] #filename = img_path.stem filename = img_path.name #if isinstance(image, tuple): #take only image in label is also returned by __getitem__ # image = image[0] image = image[ None] # mimick dataloader with 4th channel (batch channel) image = image.to(device) # next line reaches to tta.py --> net.py --> xception.py ... # output: predictions (segmentation maps) pred = model.tta(image, net_type='deeplab') # pred = model(image) # pred = F.interpolate(pred, size=label.shape, mode='bilinear', align_corners=True) # pred = pred.argmax(dim=1) pred = pred.detach().cpu().numpy() label = label.numpy() # take first pred of single item list of preds... pred = pred[0] pred = softmax_from_feat_map(pred) # take channel corresponding to softmax scores in class 1. Reduces array to 2D pred = pred[1, :, :] if pred.shape[1] / pred.shape[0] == 4: pred = topcrop(pred, reverse=True) label = topcrop(label, reverse=True) if debug: print( f'Prediction shape after evaluation: {pred.shape}\nLabel shape: {label.shape}' ) if defaults: # set all pixel in pred corresponding to an ignore_pixel in label to 0 pred[label == dataset.ignore_index] = 0 #perc = round(len(np.unique(pred)) *0.5) #find index at median #val_at_perc = np.unique(pred)[perc] val_at_perc = 0.0002 #print( # f'Value at median in prediction is: {val_at_perc}') pred_masked = np.where(pred >= val_at_perc, pred, np.nan) pred_binary = threshold( pred.copy(), value=val_at_perc ) # set values under 0.5 to 0, else to 1. result: binary array bbox_list, scores_list = contour_proc(pred_binary, pred_masked) #add key to predicted_boxes: {'filename': {'boxes':bbox_list, 'scores':scores_list}} predicted_boxes.update( {filename: { "boxes": bbox_list, "scores": scores_list }}) #pred = filter_by_activation(pred, percentile=90) #pred = threshold(pred) bbox_list_lbl, _ = contour_proc(label, label.copy()) #add key to predicted_boxes: {'filename': {'boxes':bbox_list, 'scores':scores_list}} ground_truth_boxes.update({filename: bbox_list_lbl}) if debug: print(f'Label unique values: {np.unique(label)}') _tqdm.set_postfix(OrderedDict(last_image=f'{filename}')) with open('predicted_boxes_GSV.json', 'w') as json_file: json.dump(predicted_boxes, json_file, sort_keys=True) with open('ground_truth_boxes_GSV.json', 'w') as json_file: json.dump(ground_truth_boxes, json_file, sort_keys=True)
class Tester: def __init__( self, model_path='../model/deepglobe_deeplabv3_weights-cityscapes_19-outputs/model.pth', dataset='deepglobe', output_channels=19, split='valid', net_type='deeplab', batch_size=1, shuffle=True): """ Initializes the tester by loading the model with the good parameters. :param model_path: Path to model weights :param dataset: dataset used amongst {'deepglobe', 'pascal', 'cityscapes'} :param output_channels: num of output channels of model :param split: split to be used amongst {'train', 'valid'} :param net_type: model type to be used amongst {'deeplab', 'unet'} :param batch_size: batch size when loading images (always 1 here) :param shuffle: when loading images from dataset """ model_path = '/home/sfoucher/DEV/pytorch-segmentation/model/my_pascal_unet_res18_scse/model.pth' dataset_dir = '/home/sfoucher/DEV/pytorch-segmentation/data/deepglobe_as_pascalvoc/VOCdevkit/VOC2012' output_channels = 8 net_type = 'unet' print('[Tester] [Init] Initializing tester...') self.dataset = dataset self.model_path = model_path # Load model print('[Tester] [Init] Loading model ' + model_path + ' with ' + str(output_channels) + ' output channels...') self.device = torch.device( 'cuda:0' if torch.cuda.is_available() else 'cpu') if net_type == 'unet': self.model = EncoderDecoderNet(output_channels=8, enc_type='resnet18', dec_type='unet_scse', num_filters=8) else: self.model = SPPNet(output_channels=output_channels).to( self.device) param = torch.load(model_path) self.model.load_state_dict(param) del param # Create data loader depending on dataset, split and net type if dataset == 'pascal': self.valid_dataset = PascalVocDataset(split=split, net_type=net_type) elif dataset == 'cityscapes': self.valid_dataset = CityscapesDataset(split=split, net_type=net_type) elif dataset == 'deepglobe': self.valid_dataset = DeepGlobeDataset(base_dir=dataset_dir, target_size=(64, 64), split=split, net_type=net_type) else: raise NotImplementedError self.valid_loader = DataLoader(self.valid_dataset, batch_size=batch_size, shuffle=shuffle) print('[Tester] [Init] ...done!') print('[Tester] [Init] Tester created.') def make_demo_image(self): """ Picks 4 images from dataset randomly and creates image with raw, inferred and label pictures. :return: null """ images_list = [] labels_list = [] preds_list = [] print('[Tester] [Demo] Gathering images and inferring...') self.model.eval() with torch.no_grad(): for batched in self.valid_loader: images, labels = batched images_np = images.numpy().transpose(0, 2, 3, 1) labels_np = labels.numpy() images, labels = images.to(self.device), labels.to(self.device) preds = self.model.tta(images, net_type='deeplab') preds = preds.argmax(dim=1) preds_np = preds.detach().cpu().numpy() images_list.append(images_np) labels_list.append(labels_np) preds_list.append(preds_np) if len(images_list) == 4: break print('[Tester] [Demo] Processing results...') images = np.concatenate(images_list) labels = np.concatenate(labels_list) preds = np.concatenate(preds_list) # Ignore index ignore_pixel = labels == 255 preds[ignore_pixel] = 0 labels[ignore_pixel] = 0 # Plot fig, axes = plt.subplots(4, 3, figsize=(12, 10)) plt.tight_layout() axes[0, 0].set_title('input image') axes[0, 1].set_title('prediction') axes[0, 2].set_title('ground truth') for ax, img, lbl, pred in zip(axes, images, labels, preds): ax[0].imshow( minmax_normalize(img, norm_range=(0, 1), orig_range=(-1, 1))) ax[1].imshow(pred) ax[2].imshow(lbl) ax[0].set_xticks([]) ax[0].set_yticks([]) ax[1].set_xticks([]) ax[1].set_yticks([]) ax[2].set_xticks([]) ax[2].set_yticks([]) plt.savefig('eval.png') plt.show() plt.close() def infer_image_by_path( self, image_path='/home/ubuntu/data/Segmentation/pytorch-segmentation/test1.jpg', output_name='single_test_output', display=False): """ Opens image from fs and passes it through the loaded network, then displays and saves the result. :param output_name: Output image name :param display: Display images in windows or not :param image_path: Path of input images :return: null """ if not self.dataset == 'deepglobe': print( '[ERROR] Inference script only available for the Deepglobe dataset.' ) exit(-1) print('[Tester] [Single test] Opening image ' + image_path + '...') # Open and prepare image input_img = Image.open(image_path) if display: input_img.show() custom_img = np.array(input_img) custom_img = minmax_normalize(custom_img, norm_range=(-1, 1)) custom_img = custom_img.transpose(2, 0, 1) custom_img = torch.FloatTensor([custom_img]) print('[Tester] [Single test] Inferring image...') self.model.eval().to(self.device) with torch.no_grad(): # Send to GPU, infer and collect custom_img = custom_img.to(self.device) #preds = self.model.tta(custom_img, net_type='deeplab') preds = self.model.tta(custom_img, net_type='unet') preds = preds.argmax(dim=1) preds_np = preds.detach().cpu().numpy() print('[Tester] [Single test] Processing result...') good_preds = preds_np[0] good_mask = Image.fromarray(good_preds.astype('uint8'), 'P') # Transform mask to set good indexes and palette good_mask = DeepGlobeDataset.index_to_palette(good_mask) if display: good_mask.show() good_mask.save(output_name + '_prediction.png') overlay = Tester.make_overlay(good_mask, input_img, 100) if display: overlay.show() overlay.save(output_name + '_overlay.png') print('[Tester] [Single test] Done.') def infer_image_by_name(self, image_name='255876', output_name='single_test_output', display=True): """ Opens image from fs and passes it through the loaded network, then displays and saves the result. :param output_name: Output image name :param display: Display images in windows or not :param image_path: Path of input images :return: null """ if not self.dataset == 'deepglobe': print( '[ERROR] Inference script only available for the Deepglobe dataset.' ) exit(-1) print('[Tester] [Single test] Opening image ' + image_name + '...') # Open and prepare image input_img = Image.open( '/home/ubuntu/data/Segmentation/pytorch-segmentation/data/deepglobe_as_pascalvoc/VOCdevkit/VOC2012/JPEGImages/' + image_name + '.jpg') label = Image.open( '/home/ubuntu/data/Segmentation/pytorch-segmentation/data/deepglobe_as_pascalvoc/VOCdevkit/VOC2012/SegmentationClass/' + image_name + '.png') label_raw = copy.deepcopy(label) overlay_ground_truth = Tester.make_overlay(label_raw, input_img, 100) label = label.convert('P', palette=Image.WEB) if display: input_img.show(title='Input raw image') label.show(title='Ground truth') overlay_ground_truth.show(title='Overlay_ground_truth') custom_img = np.array(input_img) custom_img = minmax_normalize(custom_img, norm_range=(-1, 1)) custom_img = custom_img.transpose(2, 0, 1) custom_img = torch.FloatTensor([custom_img]) print('[Tester] [Single test] Inferring image...') self.model.eval() with torch.no_grad(): # Send to GPU, infer and collect custom_img = custom_img.to(self.device) preds = self.model.tta(custom_img, net_type='deeplab') preds = preds.argmax(dim=1) preds_np = preds.detach().cpu().numpy() print('[Tester] [Single test] Processing result...') good_preds = preds_np[0] good_mask = Image.fromarray(good_preds.astype('uint8'), 'P') # Transform mask to set good indexes and palette good_mask = DeepGlobeDataset.index_to_palette(good_mask) overlay = Tester.make_overlay(good_mask, input_img, 100) if display: good_mask.show(title='Prediction') overlay.show(title='Overlay') good_mask.save(output_name + '_prediction.png') overlay.save(output_name + '_overlay.png') overlay_ground_truth.save(output_name + '_overlay_truth.png') print('[Tester] [Single test] Done.') @staticmethod def make_overlay(pred_in, img_in, transparency): """ Build PIL image from input img and mask overlay with given transparency. :param pred_in: mask input :param img_in: img input :param transparency: transparency wanted between 0..255 :return: PIL image result """ pred = copy.deepcopy(pred_in) img = copy.deepcopy(img_in) print('[Tester] [Overlay] Building overlay...') if transparency < 0 or transparency > 255: print('ERROR : Transparency should be in range 0..255.') exit(-1) # Make preds semi_transparent pred = pred.convert('RGBA') data = pred.getdata() # you'll get a list of tuples new_data = [] for a in data: a = a[:3] # you'll get your tuple shorten to RGB a = a + ( transparency, ) # change the 100 to any transparency number you like between (0,255) new_data.append(a) pred.putdata(new_data) # you'll get your new img ready # Paste translucid preds on input image img.paste(pred, (0, 0), pred) print('[Tester] [Overlay] Done.') return img
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') t_max = opt_config['t_max'] max_epoch = train_config['max_epoch'] batch_size = train_config['batch_size'] fp16 = train_config['fp16'] resume = train_config['resume'] pretrained_path = train_config['pretrained_path'] # Network if 'unet' in net_config['dec_type']: net_type = 'unet' model = EncoderDecoderNet(**net_config) else: net_type = 'deeplab' model = SPPNet(**net_config) dataset = data_config['dataset'] if dataset == 'pascal': from dataset.pascal_voc import PascalVocDataset as Dataset net_config['output_channels'] = 21 classes = np.arange(1, 21) elif dataset == 'cityscapes': from dataset.cityscapes import CityscapesDataset as Dataset net_config['output_channels'] = 19 classes = np.arange(1, 19) elif dataset == 'sherbrooke': from dataset.sherbrooke import SherbrookeDataset as Dataset net_config['output_channels'] = 2 classes = np.arange(1, 2) else:
import matplotlib.pyplot as plt import torch import torch.nn.functional as F from torch.utils.data import DataLoader from models.net import SPPNet from dataset.cityscapes import CityscapesDataset from utils.preprocess import minmax_normalize import datetime from torchsummary import summary device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') #model = SPPNet(output_channels=19).to(device) model = SPPNet(output_channels=19, enc_type='mobilenetv2', dec_type='maspp').to(device) summary(model, (3, 128, 256)) model_path = '../model/cityscapes_deeplab_v3_plus/model.pth' #model_path = '../model/cityscapes_mobilenetv2/model.pth' #model_path = '../model/cityscapes_deeplabv3p_mobilenetv2/model_tmp.pth' param = torch.load(model_path) model.load_state_dict(param) del param batch_size = 1 valid_dataset = CityscapesDataset(split='valid', net_type='deeplab') valid_loader = DataLoader(valid_dataset, batch_size=batch_size, shuffle=True) images_list = [] labels_list = []
def eval_from_model(split, output_channels, model_path, postproc=False, vis=True, debug=True, mean_AP=False): model_path = Path(model_path) path, model_dir = os.path.split( model_path.parent) # separate path and filename device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu') #work on GPU if available print(f'Device: {device}') if 'mnv2' in model_dir: model = SPPNet(enc_type='mobilenetv2', dec_type='maspp', output_channels=output_channels).to(device) defects = True else: model = SPPNet(output_channels=output_channels).to(device) defects = False if device == torch.device('cpu'): param = torch.load(model_path, map_location='cpu' ) # parameters saved in checkpoint via model_path else: param = torch.load( model_path) # parameters saved in checkpoint via model_path print(f'Parameters loaded from {model_path}') model.load_state_dict(param) #apply method load_state_dict to model? del param # delete parameters? Reduce memory usage? dataset = SherbrookeDataset( split=split, net_type='deeplab', defects=defects) #reach cityscapes dataset, validation split classes = np.arange(1, dataset.n_classes) img_paths = dataset.img_paths base_dir = dataset.base_dir split = dataset.split if len(img_paths) == 0: raise ValueError('Your dataset seems empty...') else: print(f'{len(img_paths)} images found in {base_dir}\\{split}') model.eval() #apply eval method on model. ? #print(f'Files containing \'{filetype}\' will be converted to \'{colortype}\' colormap and saved to:\n{output_folder}') valid_ious = [] count = 0 predicted_boxes = {} ground_truth_boxes = {} with torch.no_grad(): #dataloader is a 2 element list with images and labels as torch tensors print('Generating predictions...') with tqdm(range(len(dataset))) as _tqdm: for i in _tqdm: count += 1 if count % 1 == 10: print(f'Evaluation progress: {count}/{len(img_paths)}') image, label = dataset[i] img_path = dataset.img_paths[i] orig_image = np.array(Image.open(img_path)) filename = img_path.name #if isinstance(image, tuple): #take only image in label is also returned by __getitem__ # image = image[0] image = image[ None] # mimick dataloader with 4th channel (batch channel) image = image.to(device) # next line reaches to tta.py --> net.py --> xception.py ... # output: predictions (segmentation maps) pred = model.tta(image, net_type='deeplab') # pred = model(image) # pred = F.interpolate(pred, size=label.shape, mode='bilinear', align_corners=True) # take first pred of single item list of preds... pred = pred[0] softmax = torch.nn.Softmax(dim=1) pred = softmax(pred) #pred = softmax_from_feat_map(pred) pred = pred.detach().cpu().numpy() label = label.numpy() if pred.shape[1] / pred.shape[0] == 2: pred, label = dataset.postprocess(pred, label) if mean_AP and not postproc: raise Exception( 'postproc argument in eval_from_model function must be true if mean_AP is set to True' ) elif postproc: # take channel corresponding to softmax scores in channel 1 (class 1). Reduces array to 2D pred = pred[1, :, :] if dataset.defects: # set all pixel in pred corresponding to an ignore_pixel in label to 0 pred[label == dataset.ignore_index] = 0 if mean_AP: val_at_perc = 0.0002 # print( # f'Value at median in prediction is: {val_at_perc}') #create array copy and wreplace all values under threshold by nan values pred_masked = np.where(pred >= val_at_perc, pred, np.nan) #create copy of pred array and set all values above threshold to 1 and under to 0 pred_binary = threshold(pred.copy(), value=val_at_perc) # set values under 0.5 to 0, else to 1. result: binary array bbox_list, scores_list = contour_proc( pred_binary, pred_masked) # add key to predicted_boxes: {'filename': {'boxes':bbox_list, 'scores':scores_list}} predicted_boxes.update({ filename: { "boxes": bbox_list, "scores": scores_list } }) # pred = filter_by_activation(pred, percentile=90) # pred = threshold(pred) bbox_list_lbl, _ = contour_proc(label, label.copy()) # add key to predicted_boxes: {'filename': {'boxes':bbox_list, 'scores':scores_list}} ground_truth_boxes.update({filename: bbox_list_lbl}) pred_masked = np.where(pred >= val_at_perc, pred, np.nan) pred_binary = threshold( pred.copy(), value=val_at_perc ) # set values under 0.5 to 0, else to 1. result: binary array bbox_list, scores_list = contour_proc( pred_binary, pred_masked) #add key to predicted_boxes: {'filename': {'boxes':bbox_list, 'scores':scores_list}} predicted_boxes.update({ filename: { "boxes": bbox_list, "scores": scores_list } }) pred = filter_by_activation(pred, percentile=90) else: pred = np.argmax(pred, axis=0) if debug: print(f'Label unique values: {np.unique(label)}') # print(np.unique(pred)) if output_channels == 19: # create mask for values other than 0 (background) and 1(sidewalk) for i in range(2, 19): pred[ pred == i] = 0 # convert these classes to background value if dataset.split == 'val': # compute iou iou = compute_iou_batch(pred, label, classes) print(f'Iou for {filename}: {iou}') valid_ious.append(iou) if vis: output_dir = Path( f'../data/output/{model_dir}/{split}/{os.path.split(img_path.parent)[1]}' ) output_dir.mkdir(parents=True, exist_ok=True) folder = output_dir.joinpath('figures') folder.mkdir(parents=True, exist_ok=True) label[label == 255] = 0 conf_overlay = np.add(label, pred * 2) print(np.unique(conf_overlay)) confus_overlay = vis_segmentation(conf_overlay, img_path) confus_overlay.save( folder.joinpath(f'{filename}_overlay.jpg')) elif dataset.split == 'bootstrap': # convert 1 values to 8. For bootstrapping. pred = encode_mask(pred) pred_pil = Image.fromarray(pred.astype(np.uint8)) img_pil = Image.open(img_path) if pred_pil.size != img_pil.size: pred_pil = pred_pil.resize( (img_pil.size[0], img_pil.size[1]), Image.NEAREST) pred_pil.save( output_dir.joinpath(f'{filename}_gtFine_labelIds.png')) #save_colormap(pred[0], savename, output_dir, filetype, colortype=colortype) else: raise NotImplementedError _tqdm.set_postfix(OrderedDict(last_image=f'{filename}')) if mean_AP: with open('predicted_boxes_GSV.json', 'w') as json_file: json.dump(predicted_boxes, json_file, sort_keys=True) with open('ground_truth_boxes_GSV.json', 'w') as json_file: json.dump(ground_truth_boxes, json_file, sort_keys=True) if dataset.split == 'val': valid_iou = np.nanmean(valid_ious) print(f'mean valid iou: {valid_iou}') #print(f'Confusion matrix: \n{conf_mat}') with open('predicted_boxes_GSV.json', 'w') as json_file: json.dump(predicted_boxes, json_file) # , sort_keys=True) with open('ground_truth_boxes_GSV.json', 'w') as json_file: json.dump(ground_truth_boxes, json_file, sort_keys=True) if vis: print(f'Files were be saved to {output_dir.parent}')