From 655f370b560e5074d02fe0925c2ce29541a254a4 Mon Sep 17 00:00:00 2001 From: charsyme Date: Mon, 10 Jan 2022 20:34:04 +0200 Subject: [PATCH 001/374] v1.0 --- .../nms/seq2seq-nms/img_temp/frame_0000.jpg | Bin 0 -> 325104 bytes .../nms/seq2seq-nms/inference_demo.py | 21 + .../object_detection_2d/dependencies.ini | 2 +- .../nms/seq2seq_nms/Seq2SeqNMSLearner.py | 844 ++++++++++++++++++ .../nms/seq2seq_nms/__init__.py | 0 .../nms/seq2seq_nms/algorithm/dataset.py | 308 +++++++ .../nms/seq2seq_nms/algorithm/fmod.py | 200 +++++ .../seq2seq_nms/algorithm/seq2seq_model.py | 196 ++++ .../datasets/PETS/FMoD/pets_edgemap_b.pkl | Bin 0 -> 2739 bytes .../object_detection_2d/ssd/ssd_learner.py | 23 +- 10 files changed, 1583 insertions(+), 11 deletions(-) create mode 100644 projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg create mode 100755 projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py create mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/Seq2SeqNMSLearner.py create mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/__init__.py create mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py create mode 100755 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py create mode 100755 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py create mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/datasets/PETS/FMoD/pets_edgemap_b.pkl diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg b/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5efb4d9298de38969e29c3bc98f9c91a5ae99849 GIT binary patch literal 325104 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[HY(kgreK9)b{m#PV)|jDpgC!Gt%f@TdeGQD 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 U%g4RhvxWI+#1uvU5Hyeg!G{K+I0qzc>Z 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

_i{JzeO`lfapmsUFkz^iWRX}$R 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 I@7uTk*-tn)8~^|S literal 0 HcmV?d00001 diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py new file mode 100755 index 0000000000..e5e670889f --- /dev/null +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -0,0 +1,21 @@ +from opendr.perception.object_detection_2d.nms.seq2seq_nms.Seq2SeqNMSLearner import Seq2SeqNMSLearner +from opendr.engine.data import Image +from opendr.perception.object_detection_2d import SingleShotDetectorLearner +from opendr.perception.object_detection_2d import draw_bounding_boxes +from multiprocessing import Pool +import os +OPENDR_HOME = os.environ['OPENDR_HOME'] + +seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, experiment_name='pets_exp6', use_fmod=True, + fmod_init_path=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/datasets/PETS/FMoD/pets_edgemap_b.pkl') +seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/pets_exp6/checkpoints/checkpoint_epoch_7', verbose=True) +ssd = SingleShotDetectorLearner(device='cpu') +ssd.download(".", mode="pretrained") +ssd.load("./ssd_default_person", verbose=True) +img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg') +if not isinstance(img, Image): + img = Image(img) +boxes = ssd.infer(img, threshold=0) +seq2SeqNMSLearner.fMoD.extract_maps(img=img, augm=False) +boxes = seq2SeqNMSLearner.infer(classes=ssd.classes, dets=boxes, boxes_sorted=False, max_dt_boxes=1200, img_res=img.opencv().shape[::-1][1:]) +draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) diff --git a/src/opendr/perception/object_detection_2d/dependencies.ini b/src/opendr/perception/object_detection_2d/dependencies.ini index 54850d7303..cc6fdf0366 100644 --- a/src/opendr/perception/object_detection_2d/dependencies.ini +++ b/src/opendr/perception/object_detection_2d/dependencies.ini @@ -6,5 +6,5 @@ python=mxnet-cu102==1.8.0 gluoncv==0.11.0b20210908 tqdm==4.54.0 git+https://github.com/cidl-auth/cocoapi#subdirectory=PythonAPI - + gdown linux=libopenblas-dev diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/Seq2SeqNMSLearner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/Seq2SeqNMSLearner.py new file mode 100644 index 0000000000..5d72424551 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/Seq2SeqNMSLearner.py @@ -0,0 +1,844 @@ + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import torch +import torch.nn.functional as F +import pickle +import numpy as np +import torchvision +import os +from opendr.engine.learners import Learner +from opendr.engine.constants import OPENDR_SERVER_URL +from urllib.request import urlretrieve +import torch.nn as nn +from tensorboardX import SummaryWriter +import torch.optim as optim +from tqdm import tqdm +import collections +import json +from pycocotools.coco import COCO +from pycocotools.cocoeval import COCOeval +import sys +from opendr.engine.target import BoundingBox, BoundingBoxList +from opendr.engine.data import Image +from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet +from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.fmod import FMoD +from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.dataset import Dataset_NMS + + +class Seq2SeqNMSLearner(Learner): + def __init__(self, lr=0.0001, lr_schedule='', checkpoint_after_iter=1, checkpoint_load_iter=0, + experiment_name='default', temp_path='temp', device='cuda', use_fmod=True, + fmod_map_type='EDGEMAP_B', fmod_map_bin=True, dropout=0.02, fmod_roi_pooling_dim=160, + fmod_map_res_dim=800, fmod_pyramid_lvl=3, lq_dim=256, sq_dim=128, app_input_dim=None, + num_JPUs=4, pretrained_demo_model=None, log_after=500, iou_filtering=None, fmod_init_path=None): + super(Seq2SeqNMSLearner, self).__init__(lr=lr, batch_size=1, lr_schedule=lr_schedule, + checkpoint_after_iter=checkpoint_after_iter, + checkpoint_load_iter=checkpoint_load_iter, + temp_path=temp_path, device=device, backbone='default') + self.use_fmod = use_fmod + if self.use_fmod: + self.fmod_normalization = None + self.fmod_map_type = fmod_map_type + self.fmod_roi_pooling_dim = [fmod_roi_pooling_dim, fmod_roi_pooling_dim] + self.fmod_map_res_dim = fmod_map_res_dim + self.fmod_pyramid_lvl = fmod_pyramid_lvl + self.fmod_feats_dim = 0 + for i in range(0, self.fmod_pyramid_lvl): + self.fmod_feats_dim = self.fmod_feats_dim + 15 * (pow(4, i)) + self.fmod_map_bin = fmod_map_bin + self.app_input_dim = self.fmod_feats_dim + else: + if app_input_dim is None: + raise Exception("The dimension of the input appearance-based features is not provided...") + else: + self.app_input_dim = app_input_dim + self.geom_input_dim = 14 + self.lq_dim = lq_dim + self.sq_dim = sq_dim + self.dropout = dropout + self.num_JPUs = num_JPUs + self.parent_dir = temp_path + if not os.path.isdir(self.parent_dir): + os.mkdir(self.parent_dir) + self.experiment_name = experiment_name + if not os.path.isdir(os.path.join(self.parent_dir, self.experiment_name)): + os.mkdir(os.path.join(self.parent_dir, self.experiment_name)) + self.pretrained_demo_model = pretrained_demo_model + self.checkpoint_load_iter = checkpoint_load_iter + self.log_after = log_after + self.iou_filtering = iou_filtering + self.classes = None + self.class_ids = None + self.device = device + self.fMoD = None + if self.use_fmod: + self.fMoD = FMoD(roi_pooling_dim=self.fmod_roi_pooling_dim, pyramid_depth=self.fmod_pyramid_lvl, + resize_dim=self.fmod_map_res_dim, + map_type=self.fmod_map_type, map_bin=self.fmod_map_bin, device=self.device) + if fmod_init_path is not None: + fmod_mean_std = load_FMoD_init(fmod_init_path) + self.fMoD.set_mean_std(mean_values=fmod_mean_std['mean'], std_values=fmod_mean_std['std']) + + def fit(self, dataset, val_dataset=None, epochs=None, logging_path='', logging_flush_secs=30, silent=True, + verbose=True, nms_gt_iou=0.5, boxes_sorted=False, max_dt_boxes=400): + + datasets_folder = './datasets' + dataset_nms = Dataset_NMS(datasets_folder, dataset, split='train') + if self.classes is None: + self.classes = dataset_nms.classes + self.class_ids = dataset_nms.class_ids + + if logging_path != '' and logging_path is not None: + logging = True + file_writer = SummaryWriter(logging_path, flush_secs=logging_flush_secs) + else: + logging = False + file_writer = None + + if self.model is None: + self.init_model() + checkpoints_folder = os.path.join(self.parent_dir, self.experiment_name, 'checkpoints') + if self.checkpoint_after_iter != 0 and not os.path.exists(checkpoints_folder): + os.makedirs(checkpoints_folder) + + if self.pretrained_demo_model is not None: + self.download(mode="weights", verbose=verbose and not silent) + weights_path = None + if self.pretrained_demo_model == 'PETS': + weights_path = os.path.join(self.parent_dir, "seq2seq_pets.pth.tar") + self.checkpoint_load_iter = '?' + elif self.pretrained_demo_model == 'COCO': + weights_path = os.path.join(self.parent_dir, "seq2seq_coco.pth.tar") + self.checkpoint_load_iter = '?' + elif self.pretrained_demo_model == 'CrownHuman': + weights_path = os.path.join(self.parent_dir, "seq2seq_crowdhuman.pth.tar") + self.checkpoint_load_iter = '?' + self.load(path=weights_path, verbose=verbose) + elif self.checkpoint_load_iter != 0: + checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) + checkpoint_full_path = os.path.join(checkpoints_folder, checkpoint_name) + self.load(checkpoint_full_path) + + if not silent and verbose: + print("Model trainable parameters:", self.count_parameters()) + + self.model.train() + if self.device == 'cuda': + self.model = self.model.cuda() + + if epochs is None: + raise ValueError("Training epochs not specified") + elif epochs <= self.checkpoint_load_iter: + raise ValueError("Training epochs are less than those of the loaded model") + + if self.use_fmod: + fmod_mean_std = load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, + map_bin=self.fmod_map_bin, datasets_folder=datasets_folder) + self.fMoD.set_mean_std(mean_values=fmod_mean_std['mean'], std_values=fmod_mean_std['std']) + + start_epoch = 0 + drop_after_epoch = [4, 7] + + train_ids = np.arange(len(dataset_nms.src_data)) + total_loss_iter = 0 + total_loss_epoch = 0 + optimizer = optim.Adam(self.model.parameters(), lr=self.lr, betas=(0.9, 0.99), eps=1e-9) # HERE + scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=drop_after_epoch, gamma=0.1) + + if self.checkpoint_load_iter != 0: + checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) + checkpoint_full_path = os.path.join(checkpoints_folder, checkpoint_name) + self.load(checkpoint_full_path) + + num_iter = 0 + training_weights = compute_class_weights(pos_weights=[0.5, 0.1], max_dets=max_dt_boxes, dataset_nms=dataset_nms) + + for epoch in range(start_epoch, epochs): + pbar = None + if not silent: + pbarDesc = "Epoch #" + str(epoch) + " progress" + pbar = tqdm(desc=pbarDesc, total=len(train_ids)) + np.random.shuffle(train_ids) + for sample_id in train_ids: + image_fln = dataset_nms.src_data[sample_id]['filename'] + loss = 0 + for class_index in range(len(dataset_nms.classes)): + if len(dataset_nms.src_data[sample_id]['dt_boxes'][class_index]) > 0: + dt_boxes = torch.tensor( + dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 0:4]).float() + dt_scores = torch.tensor(dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 4]).float() + if not boxes_sorted: + dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) + dt_boxes = dt_boxes[dt_scores_ids] + else: + continue + gt_boxes = torch.tensor([]).float() + if len(dataset_nms.src_data[sample_id]['gt_boxes'][class_index]) > 0: + gt_boxes = torch.tensor(dataset_nms.src_data[sample_id]['gt_boxes'][class_index]).float() + image_path = os.path.join(datasets_folder, dataset, 'images', image_fln) + img_res = dataset_nms.src_data[sample_id]['resolution'][::-1] + + if self.device == "cuda": + dt_boxes = dt_boxes.cuda() + dt_scores = dt_scores.cuda() + gt_boxes = gt_boxes.cuda() + + val_ids = torch.logical_and((dt_boxes[:, 2] - dt_boxes[:, 0]) > 4, + (dt_boxes[:, 3] - dt_boxes[:, 1]) > 4) + dt_boxes = dt_boxes[val_ids, :] + dt_scores = dt_scores[val_ids] + + dt_boxes, dt_scores = drop_dets(dt_boxes, dt_scores) + if self.iou_filtering is not None and 1.0 > self.iou_filtering > 0: + dt_boxes, dt_scores = apply_torchNMS(boxes=dt_boxes, scores=dt_scores, + iou_thres=self.iou_filtering) + + dt_boxes = dt_boxes[:max_dt_boxes] + dt_scores = dt_scores[:max_dt_boxes] + fmod_feats = None + if self.use_fmod: + img = Image.open(image_path) + img = img.convert(format='channels_last', channel_order='bgr') + self.fMoD.extract_maps(img=img, augm=True) + fmod_feats = self.fMoD.extract_FMoD_feats(dt_boxes) + fmod_feats = torch.unsqueeze(fmod_feats, dim=1) + msk = compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) + q_geom_feats, k_geom_feats = compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, + resolution=img_res) + + optimizer.zero_grad() + preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, + fmod_feats=fmod_feats) + preds = torch.clamp(preds, 0.001, 1 - 0.001) + labels = matching_module(scores=preds, dt_boxes=dt_boxes, gt_boxes=gt_boxes, + iou_thres=nms_gt_iou) + + # weights = (2.92 * labels + 0.932 * (1 - labels)).cuda() + weights = (training_weights[class_index][1] * labels + training_weights[class_index][0] * ( + 1 - labels)).cuda() + + e = torch.distributions.uniform.Uniform(0.02, 0.0205).sample([labels.shape[0], 1]) + if self.device == 'cuda': + e = e.cuda() + labels = labels * (1 - e) + (1 - labels) * e + ce_loss = F.binary_cross_entropy(preds, labels, reduction="none") + loss = loss + (ce_loss * weights).sum() + total_loss_iter = total_loss_iter + loss + total_loss_epoch = total_loss_epoch + loss + loss.backward() + optimizer.step() + num_iter = num_iter + 1 + if self.log_after != 0 and num_iter % self.log_after == 0: + if logging: + file_writer.add_scalar(tag="cross entropy loss", + scalar_value=total_loss_iter / self.log_after, + global_step=num_iter) + if verbose: + print(''.join(['\nEpoch: {}', + ' Iter: {}, cross entropy loss: {}']).format(epoch, num_iter, + total_loss_iter / self.log_after)) + total_loss_iter = 0 + if not silent: + pbar.update(1) + if not silent: + pbar.close() + if verbose: + print(''.join(['Epoch: {}', + ' cross entropy loss: {}\n']).format(epoch, + total_loss_epoch / len(train_ids))) + if self.checkpoint_after_iter != 0 and epoch % self.checkpoint_after_iter == self.checkpoint_after_iter - 1: + snapshot_name = '{}/checkpoint_epoch_{}'.format(checkpoints_folder, epoch) + # Save checkpoint with full information for training state + self.save(path=snapshot_name, optimizer=optimizer, scheduler=scheduler, + current_epoch=epoch, max_dt_boxes=max_dt_boxes) + total_loss_epoch = 0 + scheduler.step() + if logging: + file_writer.close() + # if not silent and verbose: + # print("Model trainable parameters:", self.count_parameters()) + + def eval(self, dataset, verbose=True, split='test', boxes_sorted=False, max_dt_boxes=400, eval_folder=None): + + # Load dataset + datasets_folder = './datasets' + dataset_nms = Dataset_NMS(datasets_folder, dataset, split) + + if self.classes is None: + self.classes = dataset_nms.classes + self.class_ids = dataset_nms.class_ids + + annotations_filename = str.lower(dataset) + '_' + split + '.json' + + if eval_folder is None: + eval_folder = os.path.join(self.parent_dir, self.experiment_name, 'eval') + if not os.path.isdir(eval_folder): + os.mkdir(eval_folder) + output_file = os.path.join(eval_folder, 'detections.json') + + # Model initialization if needed + if self.model is None and self.checkpoint_load_iter != 0: + # No model loaded, initializing new + self.init_model() + checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) + checkpoint_folder = os.path.join(self.parent_dir, self.experiment_name, 'checkpoints') + checkpoint_full_path = os.path.join(checkpoint_folder, checkpoint_name) + self.load(path=checkpoint_full_path, verbose=verbose) + + elif self.model is None: + raise AttributeError("self.model is None. Please load a model or set checkpoint_load_iter.") + + if self.use_fmod and (self.fMoD.mean is None or self.fMoD.std is None): + fmod_mean_std = load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, + datasets_folder=datasets_folder) + self.fMoD.set_mean_std(mean_values=fmod_mean_std['mean'], std_values=fmod_mean_std['std']) + + self.model = self.model.eval() # Change model state to evaluation + if self.device == "cuda": + self.model = self.model.cuda() + + # Change model state to evaluation + self.model = self.model.eval() + if self.device == "cuda": + self.model = self.model.cuda() + + train_ids = np.arange(len(dataset_nms.src_data)) + nms_results = [] + pbar_eval = None + if verbose: + pbarDesc = "Evaluation progress" + pbar_eval = tqdm(desc=pbarDesc, total=len(train_ids)) + for sample_id in train_ids: + image_fln = dataset_nms.src_data[sample_id]['filename'] + + image_path = os.path.join(datasets_folder, dataset, 'images', image_fln) + img_res = dataset_nms.src_data[sample_id]['resolution'][::-1] + + for class_index in range(len(dataset_nms.classes)): + if len(dataset_nms.src_data[sample_id]['dt_boxes'][class_index]) > 0: + dt_boxes = torch.tensor(dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 0:4]).float() + dt_scores = torch.tensor(dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 4]).float() + if not boxes_sorted: + dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) + dt_boxes = dt_boxes[dt_scores_ids] + else: + continue + + if self.device == "cuda": + dt_boxes = dt_boxes.cuda() + dt_scores = dt_scores.cuda() + + val_ids = torch.logical_and((dt_boxes[:, 2] - dt_boxes[:, 0]) > 4, + (dt_boxes[:, 3] - dt_boxes[:, 1]) > 4) + dt_boxes = dt_boxes[val_ids, :] + dt_scores = dt_scores[val_ids] + + if self.iou_filtering is not None and 1.0 > self.iou_filtering > 0: + dt_boxes, dt_scores = apply_torchNMS(boxes=dt_boxes, scores=dt_scores, iou_thres=self.iou_filtering) + + dt_boxes = dt_boxes[:max_dt_boxes] + dt_scores = dt_scores[:max_dt_boxes] + fmod_feats = None + if self.use_fmod: + img = Image.open(image_path) + img = img.convert(format='channels_last', channel_order='bgr') + self.fMoD.extract_maps(img, augm=False) + fmod_feats = self.fMoD.extract_FMoD_feats(dt_boxes) + fmod_feats = torch.unsqueeze(fmod_feats, dim=1) + msk = compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) + q_geom_feats, k_geom_feats = compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, + resolution=img_res) + with torch.no_grad(): + preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, + fmod_feats=fmod_feats).cpu().detach().numpy() + bboxes = dt_boxes.cpu().numpy().astype('float64') + for j in range(len(preds)): + nms_results.append({ + 'image_id': dataset_nms.src_data[sample_id]['id'], + 'bbox': [bboxes[j][0], bboxes[j][1], bboxes[j][2] - bboxes[j][0], bboxes[j][3] - bboxes[j][1]], + 'category_id': dataset_nms.class_ids[dataset_nms.classes[class_index]], + 'score': np.float64(preds[j]) + }) + pbar_eval.update(1) + pbar_eval.close() + if verbose: + print('Writing results json to {}'.format(output_file)) + with open(output_file, 'w') as fid: + json.dump(nms_results, fid, indent=2) + eval_result = run_coco_eval(gt_file_path=os.path.join(dataset_nms.path, 'annotations', annotations_filename), + dt_file_path=output_file, only_classes=[1], + verbose=verbose, max_dets=[max_dt_boxes]) + for i in range(len(eval_result)): + print('Evaluation results (num_dets={})'.format(str(eval_result[i][1]))) + print(eval_result[i][0][0][1]) + print(eval_result[i][0][1][1]) + print(eval_result[i][0][2][1]) + print(eval_result[i][0][3][1]) + print('\n') + + def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoch=None, max_dt_boxes=800): + """ + Method for saving the current model in the path provided + :param path: path for the model to be saved + :type path: str + :param verbose: whether to print a success message or not, defaults to False + :type verbose: bool, optional + :param optimizer: the optimizer used for training + :type optimizer: Optimizer PyTorch object + :param scheduler: the scheduler used for training + :type scheduler: Scheduler PyTorch object + :param current_epoch: the current epoch id + :type current_epoch: int + """ + path = path.split('.')[0] + custom_dict = {'state_dict': self.model.state_dict(), 'optimizer': optimizer.state_dict(), + 'scheduler': scheduler.state_dict(), 'current_epoch': current_epoch} + torch.save(custom_dict, path + '.pth') + + metadata = {"model_paths": [os.path.basename(path) + '.pth'], "framework": "pytorch", "has_data": False, + "inference_params": {}, "optimized": False, "optimizer_info": {}, "backbone": {}, + "format": "pth", "classes": self.classes, "use_fmod": self.use_fmod, + "lq_dim": self.lq_dim, "sq_dim": self.sq_dim, "num_JPUs": self.num_JPUs, + "geom_input_dim": self.geom_input_dim, "app_input_dim": self.app_input_dim, + "max_dt_boxes": max_dt_boxes} + if self.use_fmod: + metadata["fmod_map_type"] = self.fmod_map_type + metadata["fmod_map_bin"] = self.fmod_map_bin + metadata["fmod_roi_pooling_dim"] = self.fmod_roi_pooling_dim + metadata["fmod_map_res_dim"] = self.fmod_map_res_dim + metadata["fmod_pyramid_lvl"] = self.fmod_pyramid_lvl + + with open(path + '.json', 'w', encoding='utf-8') as f: + json.dump(metadata, f, ensure_ascii=False, indent=4) + if verbose: + print("Saved Pytorch model.") + + def init_model(self): + if self.model is None: + self.model = Seq2SeqNet(dropout=self.dropout, use_fmod=self.use_fmod, app_input_dim=self.app_input_dim, + geom_input_dim=self.geom_input_dim, lq_dim=self.lq_dim, sq_dim=self.sq_dim, + num_JPUs=self.num_JPUs) + for p in self.model.parameters(): + if p.dim() > 1: + nn.init.xavier_uniform_(p) + else: + raise UserWarning("Tried to initialize model while model is already initialized.") + + def load(self, path, verbose=False): + """ + Loads the model from inside the path provided, based on the metadata .json file included + :param path: path of the checkpoint file was saved + :type path: str + :param verbose: whether to print success message or not, defaults to 'False' + :type verbose: bool, optional + """ + model_name = os.path.basename(os.path.normpath(path)).split('.')[0] + dir_path = os.path.dirname(os.path.normpath(path)) + + if verbose: + print("Model name:", model_name, "-->", os.path.join(dir_path, model_name + ".json")) + with open(os.path.join(dir_path, model_name + ".json")) as f: + metadata = json.load(f) + pth_path = os.path.join(dir_path, metadata["model_paths"][0]) + if verbose: + print("Loading checkpoint:", pth_path) + try: + checkpoint = torch.load(pth_path, map_location=torch.device(self.device)) + except FileNotFoundError as e: + e.strerror = "File " + pth_path + "not found." + raise e + + self.assign_params(metadata=metadata, verbose=verbose) + self.init_model() + self.load_state(checkpoint) + if self.device == 'cuda': + self.model = self.model.cuda() + if verbose: + print("Loaded parameters and metadata.") + return True + + def assign_params(self, metadata, verbose): + + if verbose and self.geom_input_dim is not None and self.geom_input_dim != metadata["geom_input_dim"]: + print("Incompatible value for the attribute \"geom_input_dim\". It is now set to: " + + str(metadata["geom_input_dim"])) + self.geom_input_dim = metadata["geom_input_dim"] + if verbose and self.app_input_dim is not None and self.app_input_dim != metadata["app_input_dim"]: + print("Incompatible value for the attribute \"app_input_dim\". It is now set to: " + + str(metadata["app_input_dim"])) + self.app_input_dim = metadata["app_input_dim"] + if verbose and self.use_fmod is not None and self.use_fmod != metadata["use_fmod"]: + print("Incompatible value for the attribute \"use_fmod\". It is now set to: " + + str(metadata["use_fmod"])) + self.use_fmod = metadata["use_fmod"] + if verbose and self.fmod_map_type is not None and self.fmod_map_type != metadata["fmod_map_type"]: + print("Incompatible value for the attribute \"fmod_map_type\". It is now set to: " + + str(metadata["fmod_map_type"])) + self.fmod_map_type = metadata["fmod_map_type"] + if verbose and self.fmod_map_bin is not None and self.fmod_map_bin != metadata["fmod_map_bin"]: + print("Incompatible value for the attribute \"fmod_map_bin\". It is now set to: " + + str(metadata["fmod_map_bin"])) + self.fmod_map_bin = metadata["fmod_map_bin"] + if verbose and self.fmod_roi_pooling_dim is not None and \ + self.fmod_roi_pooling_dim != metadata["fmod_roi_pooling_dim"]: + print("Incompatible value for the attribute \"fmod_roi_pooling_dim\". It is now set to: " + + str(metadata["fmod_roi_pooling_dim"])) + self.fmod_roi_pooling_dim = metadata["fmod_roi_pooling_dim"] + if verbose and self.fmod_map_res_dim is not None and \ + self.fmod_map_res_dim != metadata["fmod_map_res_dim"]: + print("Incompatible value for the attribute \"fmod_map_res_dim\". It is now set to: " + + str(metadata["fmod_map_res_dim"])) + self.fmod_map_res_dim = metadata["fmod_map_res_dim"] + if verbose and self.fmod_pyramid_lvl is not None and \ + self.fmod_pyramid_lvl != metadata["fmod_pyramid_lvl"]: + print("Incompatible value for the attribute \"fmod_pyramid_lvl\". It is now set to: " + + str(metadata["fmod_pyramid_lvl"])) + self.fmod_pyramid_lvl = metadata["fmod_pyramid_lvl"] + if verbose and self.lq_dim is not None and \ + self.lq_dim != metadata["lq_dim"]: + print("Incompatible value for the attribute \"lq_dim\". It is now set to: " + + str(metadata["lq_dim"])) + self.lq_dim = metadata["lq_dim"] + if verbose and self.sq_dim is not None and self.sq_dim != metadata["sq_dim"]: + print("Incompatible value for the attribute \"sq_dim\". It is now set to: " + + str(metadata["sq_dim"])) + self.sq_dim = metadata["sq_dim"] + if verbose and self.num_JPUs is not None and self.num_JPUs != metadata["num_JPUs"]: + print("Incompatible value for the attribute \"num_JPUs\". It is now set to: " + + str(metadata["num_JPUs"])) + self.num_JPUs = metadata["num_JPUs"] + if verbose and 'max_dt_boxes' in metadata: + print('Model is trained with as ' + str(metadata['max_dt_boxes']) + 'its maximum number of detections.') + + def load_state(self, checkpoint=None): + if checkpoint is None: + for p in self.model.parameters(): + if p.dim() > 1: + nn.init.xavier_uniform_(p) + else: + try: + source_state = checkpoint['state_dict'] + except KeyError: + source_state = checkpoint + target_state = self.model.state_dict() + new_target_state = collections.OrderedDict() + for target_key, target_value in target_state.items(): + if target_key in source_state and source_state[target_key].size() == target_state[target_key].size(): + new_target_state[target_key] = source_state[target_key] + else: + new_target_state[target_key] = target_state[target_key] + # print('[WARNING] Not found pre-trained parameters for {}'.format(target_key)) + + self.model.load_state_dict(new_target_state) + + def count_parameters(self): + """ + Returns the number of the model's trainable parameters. + :return: number of trainable parameters + :rtype: int + """ + if self.model is None: + raise UserWarning("Model is not initialized, can't count trainable parameters.") + return sum(p.numel() for p in self.model.parameters() if p.requires_grad) + + def download(self, path=None, mode="pretrained", verbose=False, + url=OPENDR_SERVER_URL + "perception/pose_estimation/lightweight_open_pose/"): + print('ToDo') + + def infer(self, classes=None, dets=None, boxes_sorted=False, max_dt_boxes=1200, img_res=None, threshold=0.1): + + for class_index in range(len(classes)): + if len(dets[class_index]) > 0: + dt_boxes = dets[class_index][:, 0:4] + dt_scores = dets[class_index][:, 4] + if not boxes_sorted: + dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) + dt_boxes = dt_boxes[dt_scores_ids] + else: + continue + + if self.device == "cuda": + dt_boxes = dt_boxes.cuda() + dt_scores = dt_scores.cuda() + + val_ids = torch.logical_and((dt_boxes[:, 2] - dt_boxes[:, 0]) > 4, + (dt_boxes[:, 3] - dt_boxes[:, 1]) > 4) + dt_boxes = dt_boxes[val_ids, :] + dt_scores = dt_scores[val_ids] + + if self.iou_filtering is not None and 1.0 > self.iou_filtering > 0: + dt_boxes, dt_scores = apply_torchNMS(boxes=dt_boxes, scores=dt_scores, iou_thres=self.iou_filtering) + + dt_boxes = dt_boxes[:max_dt_boxes] + dt_scores = dt_scores[:max_dt_boxes] + fmod_feats = None + if self.use_fmod: + fmod_feats = self.fMoD.extract_FMoD_feats(dt_boxes) + fmod_feats = torch.unsqueeze(fmod_feats, dim=1) + msk = compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) + q_geom_feats, k_geom_feats = compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, + resolution=img_res) + with torch.no_grad(): + preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, + fmod_feats=fmod_feats).cpu().detach().numpy() + bboxes = dt_boxes.cpu().numpy().astype('float64') + + mask = np.where(preds > threshold)[0] + if mask.size == 0: + return BoundingBoxList([]) + preds = preds[mask] + bboxes = bboxes[mask, :] + + bounding_boxes = BoundingBoxList([]) + for idx, box in enumerate(bboxes): + bbox = BoundingBox(left=box[0], top=box[1], + width=box[2] - box[0], + height=box[3] - box[1], + name=class_index, + score=preds[idx]) + bounding_boxes.data.append(bbox) + return bounding_boxes + + def optimize(self, **kwargs): + """This method is not used in this implementation.""" + raise NotImplementedError + + def reset(self): + """This method is not used in this implementation.""" + return NotImplementedError + + +def apply_torchNMS(boxes, scores, iou_thres): + ids_nms = torchvision.ops.nms(boxes, scores, iou_thres) + scores = scores[ids_nms] + boxes = boxes[ids_nms] + return boxes, scores + + +def compute_mask(boxes=None, iou_thres=0.2, extra=0.1): + relations = filter_iou_boxes(boxes, iou_thres=iou_thres) + mask1 = torch.tril(relations).float() + mask2 = extra * torch.triu(relations, diagonal=1).float() + mask = mask1 + mask2 + return mask + + +def filter_iou_boxes(boxes=None, iou_thres=0.2): + ious = bb_intersection_over_union(boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1), + boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1)) + ids_boxes = ious >= iou_thres + return ids_boxes + + +def bb_intersection_over_union(boxAs=None, boxBs=None): + xA = torch.maximum(boxAs[:, :, 0], boxBs[:, :, 0]) + yA = torch.maximum(boxAs[:, :, 1], boxBs[:, :, 1]) + xB = torch.minimum(boxAs[:, :, 2], boxBs[:, :, 2]) + yB = torch.minimum(boxAs[:, :, 3], boxBs[:, :, 3]) + interAreas = torch.maximum(torch.zeros_like(xB), xB - xA + 1) * torch.maximum(torch.zeros_like(yB), yB - yA + 1) + boxAAreas = (boxAs[:, :, 2] - boxAs[:, :, 0] + 1) * (boxAs[:, :, 3] - boxAs[:, :, 1] + 1) + boxBAreas = (boxBs[:, :, 2] - boxBs[:, :, 0] + 1) * (boxBs[:, :, 3] - boxBs[:, :, 1] + 1) + ious = interAreas / (boxAAreas + boxBAreas - interAreas) + return ious + + +def compute_geometrical_feats(boxes, scores, resolution): + boxBs = boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1) + boxAs = boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1) + scoresBs = scores.unsqueeze(0).unsqueeze(-1).repeat(scores.shape[0], 1, 1) + scoresAs = scores.unsqueeze(1).unsqueeze(1).repeat(1, scores.shape[0], 1) + + scale_div = [resolution[0] / 20, resolution[1] / 20] + dx = ((boxBs[:, :, 0] - boxAs[:, :, 0] + boxBs[:, :, 2] - boxAs[:, :, 2]) / 2).unsqueeze(-1) + dy = ((boxBs[:, :, 1] - boxAs[:, :, 1] + boxBs[:, :, 3] - boxAs[:, :, 3]) / 2).unsqueeze(-1) + dxy = dx * dx + dy * dy + dxy = dxy / (scale_div[0] * scale_div[0] + scale_div[1] * scale_div[1]) + dx = (dx / scale_div[0]) + dy = (dy / scale_div[1]) + sx = boxBs[:, :, 2] - boxBs[:, :, 0] + sx_1 = (sx / (boxAs[:, :, 2] - boxAs[:, :, 0])).unsqueeze(-1) + sx_2 = (sx / scale_div[0]).unsqueeze(-1) + sy = boxBs[:, :, 3] - boxBs[:, :, 1] + sy_1 = (sy / (boxAs[:, :, 3] - boxAs[:, :, 1])).unsqueeze(-1) + sy_2 = (sy / scale_div[1]).unsqueeze(-1) + scl = (boxBs[:, :, 2] - boxBs[:, :, 0]) * (boxBs[:, :, 3] - boxBs[:, :, 1]) + scl_1 = (scl / ((boxAs[:, :, 2] - boxAs[:, :, 0]) * (boxAs[:, :, 3] - boxAs[:, :, 1]))).unsqueeze(-1) + scl_2 = (scl / (scale_div[0] * scale_div[1])).unsqueeze(-1) + del scl + + scr_1 = 5 * scoresBs + scr_2 = scr_1 - 5 * scoresAs + + sr_1 = torch.unsqueeze((boxBs[:, :, 3] - boxBs[:, :, 1]) / (boxBs[:, :, 2] - boxBs[:, :, 0]), dim=-1) + sr_2 = torch.unsqueeze(((boxBs[:, :, 3] - boxBs[:, :, 1]) / (boxBs[:, :, 2] - boxBs[:, :, 0])) / ( + (boxAs[:, :, 3] - boxAs[:, :, 1]) / (boxAs[:, :, 2] - boxAs[:, :, 0])), dim=-1) + + ious = 5 * (bb_intersection_over_union(boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1), + boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1))).unsqueeze(-1) + enc_vers_all = torch.cat((dx, dy, dxy, sx_1, sx_2, sy_1, sy_2, ious, scl_1, scl_2, scr_1, scr_2, sr_1, sr_2), dim=2) + enc_vers = enc_vers_all.diagonal(dim1=0, dim2=1).transpose(0, 1).unsqueeze(1) + return enc_vers, enc_vers_all + + +def matching_module(scores, dt_boxes, gt_boxes, iou_thres, device='cuda'): + sorted_indices = torch.argsort(-scores, dim=0) + labels = torch.zeros(len(dt_boxes)) + assigned_GT = -torch.ones(len(gt_boxes)) + r = torch.tensor([-1, -1, -1, -1]).float().unsqueeze(0).unsqueeze(0) + if device == 'cuda': + r = r.cuda() + labels = labels.cuda() + for s in sorted_indices: + gt_boxes_c = gt_boxes.clone().unsqueeze(0) + gt_boxes_c[0, assigned_GT > -1, :] = r + ious = bb_intersection_over_union(boxAs=dt_boxes[s].clone().unsqueeze(0), boxBs=gt_boxes_c) + annot_iou, annot_box_id = torch.sort(ious.squeeze(), descending=True) + if annot_box_id.ndim > 0: + annot_box_id = annot_box_id[0] + annot_iou = annot_iou[0] + if annot_iou > iou_thres: + assigned_GT[annot_box_id] = s + labels[s] = 1 + return labels.unsqueeze(-1) + + +def run_coco_eval(dt_file_path=None, gt_file_path=None, only_classes=None, max_dets=None, + verbose=False): + if max_dets is None: + max_dets = [200, 400, 600, 800, 1000, 1200] + results = [] + sys.stdout = open(os.devnull, 'w') + for i in range(len(max_dets)): + coco = COCO(gt_file_path) + coco_dt = coco.loadRes(dt_file_path) + cocoEval = COCOeval(coco, coco_dt, 'bbox') + cocoEval.params.iouType = 'bbox' + cocoEval.params.useCats = True + cocoEval.params.catIds = only_classes + cocoEval.params.maxDets = [max_dets[i]] + cocoEval.evaluate() + results.append([summarize_nms(coco_eval=cocoEval, maxDets=max_dets[i]), max_dets[i]]) + # print(results[i]) + del cocoEval, coco_dt, coco + sys.stdout = sys.__stdout__ + return results + + +def summarize_nms(coco_eval=None, maxDets=100): + def summarize(ap=1, iouThr=None, areaRng='all', maxDets=100): + p = coco_eval.params + iStr = ' {:<18} {} @[ IoU={:<9} | area={:>6s} | maxDets={:>3d} ] = {:0.3f}' + titleStr = 'Average Precision' if ap == 1 else 'Average Recall' + typeStr = '(AP)' if ap == 1 else '(AR)' + iouStr = '{:0.2f}:{:0.2f}'.format(p.iouThrs[0], p.iouThrs[-1]) \ + if iouThr is None else '{:0.2f}'.format(iouThr) + aind = [i for i, aRng in enumerate(p.areaRngLbl) if aRng == areaRng] + mind = [i for i, mDet in enumerate(p.maxDets) if mDet == maxDets] + if ap == 1: + # dimension of precision: [TxRxKxAxM] + s = coco_eval.eval['precision'] + # IoU + if iouThr is not None: + t = np.where(iouThr == p.iouThrs)[0] + s = s[t] + s = s[:, :, :, aind, mind] + else: + # dimension of recall: [TxKxAxM] + s = coco_eval.eval['recall'] + if iouThr is not None: + t = np.where(iouThr == p.iouThrs)[0] + s = s[t] + s = s[:, :, aind, mind] + if len(s[s > -1]) == 0: + mean_s = -1 + else: + mean_s = np.mean(s[s > -1]) + stat_str = iStr.format(titleStr, typeStr, iouStr, areaRng, maxDets, mean_s) + return [mean_s, stat_str] + + def summarizeDets(): + stats = [] + stat, stat_str = summarize(1, maxDets=maxDets) + stats.append([stat, stat_str]) + stat, stat_str = summarize(1, iouThr=.5, maxDets=maxDets) + stats.append([stat, stat_str]) + stat, stat_str = summarize(1, iouThr=.75, maxDets=maxDets) + stats.append([stat, stat_str]) + stat, stat_str = summarize(0, maxDets=maxDets) + stats.append([stat, stat_str]) + return stats + + coco_eval.accumulate() + summarized = summarizeDets() + return summarized + + +def drop_dets(boxes, scores, keep_ratio=0.85): + ids = np.arange(len(boxes)) + np.random.shuffle(ids) + ids_keep = ids[0:int(len(boxes) * keep_ratio)] + boxes_new = boxes[ids_keep, :] + scores_new = scores[ids_keep] + return boxes_new, scores_new + + +def load_FMoD_init_from_dataset(dataset=None, map_type='edgemap', datasets_folder='./datasets', map_bin=True): + fmod_dir = os.path.join(datasets_folder, dataset, 'FMoD') + if not os.path.exists(fmod_dir): + os.makedirs(fmod_dir, exist_ok=True) + map_type_c = map_type + if map_bin: + map_type_c = map_type_c + '_B' + fmod_filename = dataset + '_' + map_type_c + '.pkl' + fmod_filename = fmod_filename.lower() + if not os.path.exists(os.path.join(fmod_dir, fmod_filename)): + file_url = os.path.join(OPENDR_SERVER_URL + 'perception/non-maximum_suppression/FMoD', fmod_filename) + try: + urlretrieve(file_url, os.path.join(fmod_dir, fmod_filename)) + except Exception as e: + raise e + fmod_stats = load_FMoD_init(os.path.join(fmod_dir, fmod_filename)) + return fmod_stats + + +def load_FMoD_init(path=None): + try: + with open(path, 'rb') as fp: + fmod_stats = pickle.load(fp) + map_type = list(fmod_stats.keys())[0] + fmod_stats = fmod_stats[map_type] + except EnvironmentError as e: + e.strerror = 'FMoD initialization .pkl file not found' + raise e + return fmod_stats + + +def compute_class_weights(pos_weights, max_dets=400, dataset_nms=None): + num_pos = np.ones([len(dataset_nms.classes), 1]) + num_bg = np.ones([len(dataset_nms.classes), 1]) + weights = np.zeros([len(dataset_nms.classes), 2]) + for i in range(len(dataset_nms.src_data)): + for cls_index in range(len(dataset_nms.classes)): + num_pos[cls_index] = num_pos[cls_index] + \ + min(max_dets, len(dataset_nms.src_data[i]['gt_boxes'][cls_index])) + num_bg[cls_index] = num_bg[cls_index] + max(0, min(max_dets, + len(dataset_nms.src_data[i]['dt_boxes'][cls_index])) - + min(max_dets, len(dataset_nms.src_data[i]['gt_boxes'][cls_index]))) + for class_index in range(len(dataset_nms.classes)): + weights[class_index, 0] = (1 - pos_weights[class_index]) * (num_pos[class_index] + + num_bg[class_index]) / num_bg[class_index] + weights[class_index, 1] = pos_weights[class_index] * (num_pos[class_index] + + num_bg[class_index]) / num_pos[class_index] + return weights diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py new file mode 100644 index 0000000000..b836289d5c --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py @@ -0,0 +1,308 @@ + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from opendr.engine.datasets import Dataset +import os +from urllib.request import urlretrieve +import time +from zipfile import ZipFile +import tarfile +import gdown +import shutil +import json +import cv2 +import pickle +import numpy as np +import math +from tqdm import tqdm + + +class Dataset_NMS(Dataset): + def __init__(self, path, dataset_name, split): + super().__init__() + + available_dataset = ['COCO', 'PETS', 'CrowdHuman'] + if dataset_name not in available_dataset: + except_str = 'Unsupported dataset: ' + dataset_name + '. Currently available are:' + for j in range(len(available_dataset)): + except_str = except_str + ' \'' + available_dataset[j] + '\'' + if j < len(available_dataset) - 1: + except_str = except_str + ',' + except_str = except_str + '.' + raise ValueError(except_str) + + self.dataset_name = dataset_name + self.split = split + # self.__prepare_dataset() + self.path = os.path.join(path, dataset_name) + self.src_data = [] + if self.dataset_name == "PETS": + if not os.path.exists(os.path.join(self.path, 'images/S1/L1')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S1_L1.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S1/L2')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S1_L2.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S2/L1')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L1.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S2/L2')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L2.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S2/L3')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L3.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S3/Multiple_Flow')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S3_MF.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + splits = ['train', 'val', 'test'] + if self.split not in splits: + raise ValueError(self.split + ' is not available...') + if not os.path.exists(os.path.join(self.path, 'annotations', 'pets_' + self.split + '.json')): + self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_annotations_json.zip', + download_path=os.path.join(self.path, 'annotations'), file_format="zip", + create_dir=True) + if not os.path.exists(os.path.join(self.path, 'data_' + self.split + '_pets.pkl')): + if not os.path.exists( + os.path.join(self.path, 'detections', 'PETS-' + self.split + '_siyudpm_dets.idl')): + self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_detections.zip', + download_path=os.path.join(self.path, 'detections'), file_format="zip", + create_dir=True) + if not os.path.exists(os.path.join(self.path, 'annotations', 'PETS-' + self.split + '.idl')): + self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_annotations.zip', + download_path=os.path.join(self.path, 'annotations'), file_format="zip", + create_dir=True) + with open(os.path.join(self.path, 'detections', 'PETS-' + self.split + '_siyudpm_dets.idl')) as fp_dt, \ + open(os.path.join(self.path, 'annotations', 'PETS-' + self.split + '.idl')) as fp_gt: + print('Preparing PETS ' + self.split + ' set...') + current_id = 0 + number_samples = 1696 + if self.split == 'val': + current_id = 1696 + number_samples = 240 + elif self.split == 'test': + current_id = 1936 + number_samples = 436 + pbarDesc = "Overall progress" + pbar = tqdm(desc=pbarDesc, total=number_samples) + line_dt = fp_dt.readline() + line_gt = fp_gt.readline() + while line_dt and line_gt: + data_dt = line_dt.replace(':', ' ') + data_gt = line_gt.replace(':', ' ') + remove_strings = ['PETS09-', '\"', ':', '(', ')', ',', '', ';'] + for j in range(len(remove_strings)): + data_dt = data_dt.replace(remove_strings[j], '') + for j in range(len(remove_strings)): + data_gt = data_gt.replace(remove_strings[j], '') + data_dt = data_dt.split() + data_gt = data_gt.split() + filename_dt = data_dt[0][0:2] + '/' + data_dt[0][2:] + if filename_dt[0:6] == 'S2/L1/': + filename_dt = filename_dt.replace('img/00', 'Time_12-34/View_001/frame_') + num = int(filename_dt[-8:-4]) - 1 + filename_dt = filename_dt[:-8] + str(num).zfill(4) + '.jpg' + if filename_dt[0:6] == 'S2/L2/': + filename_dt = filename_dt.replace('img/00', 'Time_14-55/View_001/frame_') + num = int(filename_dt[-8:-4]) - 1 + filename_dt = filename_dt[:-8] + str(num).zfill(4) + '.jpg' + if filename_dt[0:2] == 'S3': + filename_dt = filename_dt.replace('_MF', 'Multiple_Flow') + + filename_gt = data_gt[0][0:2] + '/' + data_gt[0][2:] + if filename_gt[0:6] == 'S2/L1/': + filename_gt = filename_gt.replace('img/00', 'Time_12-34/View_001/frame_') + num = int(filename_gt[-8:-4]) - 1 + filename_gt = filename_gt[:-8] + str(num).zfill(4) + '.jpg' + if filename_gt[0:6] == 'S2/L2/': + filename_gt = filename_gt.replace('img/00', 'Time_14-55/View_001/frame_') + num = int(filename_gt[-8:-4]) - 1 + filename_gt = filename_gt[:-8] + str(num).zfill(4) + '.jpg' + if filename_gt[0:2] == 'S3': + filename_gt = filename_gt.replace('_MF', 'Multiple_Flow') + if filename_gt != filename_dt: + raise ValueError('Errors in files...') + img = cv2.imread(os.path.join(self.path, 'images/', filename_dt)) + dt_boxes = [] + for i in range(1, (len(data_dt)), 5): + dt_box = np.array((float(data_dt[i]), float(data_dt[i + 1]), float(data_dt[i + 2]), + float(data_dt[i + 3]), 1 / (1 + math.exp(- float(data_dt[i + 4]))))) + dt_boxes.append(dt_box) + gt_boxes = [] + for i in range(1, (len(data_gt)), 5): + gt_box = np.array((float(data_gt[i]), float(data_gt[i + 1]), float(data_gt[i + 2]), + float(data_gt[i + 3]))) + gt_boxes.append(gt_box) + self.src_data.append({ + 'id': current_id, + 'filename': filename_dt, + 'resolution': img.shape[0:2][::-1], + 'gt_boxes': [np.asarray([]), np.asarray(gt_boxes)], + 'dt_boxes': [np.asarray([]), np.asarray(dt_boxes)] + }) + current_id = current_id + 1 + pbar.update(1) + line_dt = fp_dt.readline() + line_gt = fp_gt.readline() + pbar.close() + with open(os.path.join(self.path, 'data_' + self.split + '_pets.pkl'), 'wb') as handle: + pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) + else: + with open(os.path.join(self.path, 'data_' + self.split + '_pets.pkl'), 'rb') as fp_dt: + self.src_data = pickle.load(fp_dt) + + self.classes = ['background', 'human'] + self.class_ids = {'background': 0, 'human': 1} + + elif self.dataset_name == "CrowdHuman": + if not os.path.exists(os.path.join(self.path, 'images/train')): + os.makedirs(os.path.join(self.path, 'images/train'), exist_ok=True) + urls = ['https://drive.google.com/uc?export=download&confirm=YZB1&id=134QOvaatwKdy0iIeNqA_p-xkAhkV4F8Y', + 'https://drive.google.com/u/0/uc?id=17evzPh7gc1JBNvnW1ENXLy5Kr4Q_Nnla', + 'https://drive.google.com/u/0/uc?id=1tdp0UCgxrqy1B6p8LkR-Iy0aIJ8l4fJW'] + outputs = ['CrowdHuman_train01.zip', 'CrowdHuman_train02.zip', 'CrowdHuman_train03.zip'] + for i in range(0, len(urls)): + gdown.download(urls[i], outputs[i], quiet=False) + zip_path = os.path.join('.', outputs[i]) + with ZipFile(zip_path, 'r') as zip_ref: + download_path = os.path.join(self.path, 'images', 'train') + zip_ref.extractall(download_path) + os.remove(zip_path) + + if not os.path.exists(os.path.join(self.path, 'images/val')): + os.makedirs(os.path.join(self.path, 'images/val'), exist_ok=True) + url = 'https://drive.google.com/u/0/uc?id=18jFI789CoHTppQ7vmRSFEdnGaSQZ4YzO' + output = 'CrowdHuman_val.zip' + gdown.download(url, output, quiet=False) + zip_path = os.path.join('.', output) + with ZipFile(zip_path, 'r') as zip_ref: + download_path = os.path.join(self.path, 'images', 'val') + zip_ref.extractall(download_path) + os.remove(zip_path) + + if not os.path.exists(os.path.join(self.path, 'data_train_crowdhuman.pkl')): + # Download detections from FTP server + + # Download annotations from official CrowdHuman GoogleDrive repo + if not os.path.exists(os.path.join(self.path, 'annotations', 'annotation_train.odgt')): + os.makedirs(os.path.join(self.path, 'annotations'), exist_ok=True) + urls = ['https://drive.google.com/u/0/uc?id=1UUTea5mYqvlUObsC1Z8CFldHJAtLtMX3&export=download', + 'https://drive.google.com/u/0/uc?id=10WIRwu8ju8GRLuCkZ_vT6hnNxs5ptwoL&export=download'] + outputs = ['annotation_train.odgt', 'annotation_val.odgt'] + gdown.download(urls[0], outputs[0], quiet=False) + shutil.move(os.path.join('.', outputs[0]), + os.path.join('.', 'datasets', 'CrowdHuman', 'annotations', 'train')) + gdown.download(urls[1], outputs[1], quiet=False) + shutil.move(os.path.join('.', outputs[1]), + os.path.join('.', 'datasets', 'CrowdHuman', 'annotations', 'val')) + + with open(os.path.join(self.path, 'annotations', 'annotation_train.odgt')) as fp_gt, open( + os.path.join(self.path, 'detections', 'det_data_train_crowdhuman.pkl'), 'rb') as fp_dt: + line = fp_gt.readline() + data_dt = pickle.load(fp_dt) + i = 0 + while line: + annotations = json.loads(line) + if data_dt[i]['id'] != annotations['ID']: + continue + img = cv2.imread(os.path.join(self.path, 'images/train', annotations['ID'] + '.jpg')) + gt_boxes = [] + for j in range(len(annotations['gtboxes'])): + if annotations['gtboxes'][j]['tag'] == 'person': + gt_box = annotations['gtboxes'][j]['fbox'] + gt_box[2] = gt_box[2] + gt_box[0] + gt_box[3] = gt_box[3] + gt_box[1] + gt_boxes.append(gt_box) + self.src_data.append({ + 'id': annotations['ID'], + 'filename': annotations['ID'] + '.jpg', + 'resolution': img.shape[0:2][::-1], + 'gt_boxes': np.asarray(gt_boxes), + 'dt_boxes': data_dt[i]['dt_boxes'], + }) + line = fp_gt.readline() + i = i + 1 + with open(os.path.join(self.path, 'data_train_crowdhuman.pkl'), 'wb') as handle: + pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) + else: + with open(os.path.join(self.path, 'data_train_crowdhuman.pkl'), 'rb') as fp_dt: + self.src_data = pickle.load(fp_dt) + + @staticmethod + def download( + url, download_path, dataset_sub_path=".", file_format="zip", create_dir=False): + + if create_dir: + os.makedirs(download_path, exist_ok=True) + + print("Downloading dataset from", url, "to", download_path) + + start_time = 0 + last_print = 0 + + def reporthook(count, block_size, total_size): + nonlocal start_time + nonlocal last_print + if count == 0: + start_time = time.time() + last_print = start_time + return + + duration = time.time() - start_time + progress_size = int(count * block_size) + speed = int(progress_size / (1024 * duration)) + if time.time() - last_print >= 1: + last_print = time.time() + print( + "\r%d MB, %d KB/s, %d seconds passed" % + (progress_size / (1024 * 1024), speed, duration), + end='' + ) + + if file_format == "zip": + zip_path = os.path.join(download_path, "dataset.zip") + urlretrieve(url, zip_path, reporthook=reporthook) + print() + print("Extracting data from zip file") + with ZipFile(zip_path, 'r') as zip_ref: + zip_ref.extractall(download_path) + os.remove(zip_path) + elif file_format == "tar.bz2": + tar_path = os.path.join(download_path, "dataset.tar.bz2") + urlretrieve(url, tar_path, reporthook=reporthook) + print() + + def members(tf): + l = len("Crowd_PETS09/") + for member in tf.getmembers(): + if member.path.startswith("Crowd_PETS09/"): + member.path = member.path[l:] + yield member + + with tarfile.open(tar_path, "r:bz2") as tar: + tar.extractall(path=download_path, members=members(tar)) + tar.close() + os.remove(tar_path) + else: + raise ValueError("Unsupported file_format: " + file_format) + + # def __prepare_dataset(self): + # seq_root = os.path.join(self.path, "images/train") + # label_root = os.path.join(self.path, "labels/test") diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py new file mode 100755 index 0000000000..fcf0511646 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py @@ -0,0 +1,200 @@ + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import torch +import torchvision +import numpy as np +import cv2 +import random +from opendr.engine.data import Image + + +class FMoD: + def __init__(self, roi_pooling_dim=None, pyramid_depth=3, map_type="SIFT", map_bin=False, + resize_dim=None, device='cpu'): + if roi_pooling_dim is None: + roi_pooling_dim = [160, 160] + self.roi_pooling_dim = roi_pooling_dim + self.pyramid_depth = pyramid_depth + self.boxes_p = [] + self.rp_size = [] + for p in range(self.pyramid_depth): + s = 1 / pow(2, p) + for i in np.arange(0, 1.0, s): + for j in np.arange(0, 1.0, s): + self.boxes_p.append([0, int(i * self.roi_pooling_dim[0]), int(j * self.roi_pooling_dim[1]), + int((i + s) * self.roi_pooling_dim[0]), + int((j + s) * self.roi_pooling_dim[1])]) + self.rp_size.append([int(self.roi_pooling_dim[0] * s), int(self.roi_pooling_dim[1] * s)]) + self.device = device + self.boxes_p = torch.tensor(self.boxes_p).float() + if self.device == 'cuda': + self.boxes_p = self.boxes_p.cuda() + self.resc = 1.0 + self.map = None + self.resize_dim = resize_dim + self.map_type = map_type + self.map_bin = map_bin + self.mean = None + self.std = None + + def set_mean_std(self, mean_values=None, std_values=None): + self.mean = torch.tensor(mean_values) + self.std = torch.tensor(std_values) + if self.device == 'cuda': + self.mean = self.mean .cuda() + self.std = self.std.cuda() + + def extract_maps(self, img=None, augm=False): + if img is None: + raise Exception('Image is not provided to FMoD...') + + if not isinstance(img, Image): + img = Image(img) + img = img.convert(format='channels_last', channel_order='bgr') + + if self.resize_dim is not None: + max_dim = max(img.shape[0], img.shape[1]) + if max_dim > self.resize_dim: + self.resc = float(self.resize_dim) / max_dim + img = cv2.resize(img, (int(img.shape[1] * self.resc), int(img.shape[0] * self.resc))) + if augm: + img = augm_brightness(img, 0.75, 1.25) + img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) + if self.map_type == "EDGEMAP": + dst_img = np.copy(img) + dst_img = cv2.GaussianBlur(dst_img, (3, 3), 0, 0, cv2.BORDER_DEFAULT) + gradX = cv2.Scharr(dst_img, ddepth=cv2.CV_16S, dx=1, dy=0, scale=1, delta=0, + borderType=cv2.BORDER_DEFAULT) + gradY = cv2.Scharr(dst_img, ddepth=cv2.CV_16S, dx=0, dy=1, scale=1, delta=0, + borderType=cv2.BORDER_DEFAULT) + absGradX = cv2.convertScaleAbs(gradX) + absGradY = cv2.convertScaleAbs(gradY) + absGradXCV32 = absGradX.astype("float32") + absGradYCV32 = absGradY.astype("float32") + self.map = cv2.magnitude(absGradXCV32 / 255.0, absGradYCV32 / 255.0) + self.map = self.map * 255 + if self.map_bin: + self.map = cv2.threshold(self.map, 240, 255, cv2.THRESH_BINARY)[1] + else: + kps = None + if self.map_type == "FAST": + fast = cv2.FastFeatureDetector_create() + kps = fast.detect(img, None) + elif self.map_type == "AKAZE": + akaze = cv2.AKAZE_create() + kps, desc = akaze.detectAndCompute(img, None) + elif self.map_type == "BRISK": + brisk = cv2.BRISK_create() + kps = brisk.detect(img, None) + elif self.map_type == "ORB": + orb = cv2.ORB_create() + kps = orb.detect(img, None) + else: + raise Exception("Map type not supported...") + self.map = np.zeros(img.shape, dtype=np.uint8) + coords_x = [] + coords_y = [] + resps = [] + for kp in kps: + coords_x.append(int(kp.pt[0])) + coords_y.append(int(kp.pt[1])) + resps.append(255 * kp.response) + if not self.map_bin: + self.map[coords_y, coords_x] = resps + else: + self.map[coords_y, coords_x] = 255 + self.map = torch.from_numpy(self.map).float() + if self.device == 'cuda': + self.map = self.map.cuda() + + def extract_FMoD_feats(self, boxes): + num_rois = boxes.shape[0] + map_gpu = self.map / 255.0 + map_gpu = map_gpu.unsqueeze(0).unsqueeze(0) + descs = [] + pooled_regions = torchvision.ops.roi_align(map_gpu, [self.resc * boxes], + output_size=self.rp_size[0], spatial_scale=1.0, + aligned=True) + pooled_regions = pooled_regions.unsqueeze(1) + descs.append(self.get_descriptor(pooled_regions)) + for i in range(0, self.pyramid_depth - 1): + pooled_regions_pyr = pooled_regions.contiguous().view(num_rois, pooled_regions.shape[-2], + pooled_regions.shape[-1]) + pooled_regions_pyr = pooled_regions_pyr.unsqueeze(0) + pooled_regions_pyr = torchvision.ops.roi_align(pooled_regions_pyr, self.boxes_p[(pow(4 + 1, i)):( + (pow(4 + 1, i)) + pow(4, (i + 1))), :], output_size=self.rp_size[i + 1], aligned=True) + pooled_regions_pyr = pooled_regions_pyr.permute(1, 0, 2, 3) + pooled_regions_pyr = pooled_regions_pyr.contiguous().view(num_rois, 1, pooled_regions_pyr.shape[-3], + pooled_regions_pyr.shape[-2], + pooled_regions_pyr.shape[-1]) + descs.append(self.get_descriptor(pooled_regions_pyr)) + + descs = torch.cat(descs, dim=1) + if self.mean is not None and self.std is not None: + descs = (descs - self.mean) / self.std + descs = torch.clamp(descs, -50, 50) + return descs + + def release_maps(self): + self.map = None + + def get_descriptor(self, patches): + dt = [] + # row data + dt.append(patches.mean(dim=3)) + # collumn data + dt.append(patches.mean(dim=4)) + # block data + dt.append(torch.flatten(patches, start_dim=3)) + + means = [] + stds = [] + diffs = [] + zscores = [] + skews = [] + kurtoses = [] + powers = [] + for i in range(len(dt)): + if i == 2: + means.append(dt[i].mean(dim=3)) + else: + means.append(dt[i][:, :, :, 0:-1:5].mean(dim=3)) + stds.append(dt[i].std(dim=3)) + diffs.append((dt[i] - means[i].unsqueeze(-1).expand(dt[i].size()))) + zscores.append(diffs[i] / stds[i].unsqueeze(-1).expand(dt[i].size())) + zscores[i] = torch.where(stds[i].unsqueeze(-1).expand(zscores[i].shape) > 0, zscores[i], + torch.zeros_like(zscores[i])) + skews.append(torch.mean(torch.pow(zscores[i], 3.0), -1)) + kurtoses.append(torch.mean(torch.pow(zscores[i], 4.0), -1) - 3.0) + powers.append((dt[i] * dt[i]).mean(-1)) + descs = [] + for i in range(len(dt)): + descs.append(torch.cat((means[i], stds[i], skews[i], kurtoses[i], powers[i]), 2)) + desc = torch.cat((descs[0], descs[1], descs[2]), 2) + desc = desc.contiguous().view(desc.shape[0], desc.shape[1] * desc.shape[2]) + return desc + + +def augm_brightness(img, low, high): + value = random.uniform(low, high) + hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV) + hsv = np.array(hsv, dtype=np.float64) + hsv[:, :, 1] = hsv[:, :, 1] * value + hsv[:, :, 1][hsv[:, :, 1] > 255] = 255 + hsv[:, :, 2] = hsv[:, :, 2] * value + hsv[:, :, 2][hsv[:, :, 2] > 255] = 255 + hsv = np.array(hsv, dtype=np.uint8) + img = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR) + return img diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py new file mode 100755 index 0000000000..4692e30bbe --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py @@ -0,0 +1,196 @@ + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import torch.nn as nn +import torch +import math +import torch.nn.functional as F + + +class Seq2SeqNet(nn.Module): + def __init__(self, dropout=0.01, use_fmod=True, app_input_dim=315, geom_input_dim=14, lq_dim=256, sq_dim=128, + num_JPUs=4, device='gpu'): + super().__init__() + self.use_fmod = use_fmod + self.dropout_q = nn.Dropout(dropout * 0.25) + self.num_JPUs = num_JPUs + self.joint_processing_units = [] + for i in range(self.num_JPUs): + self.joint_processing_units.append(Joint_processing_unit(lq_dim=lq_dim, sq_dim=sq_dim, dropout=dropout)) + if device == 'gpu': + self.joint_processing_units[i] = self.joint_processing_units[i].cuda() + self.joint_processing_units = nn.ModuleList(self.joint_processing_units) + if self.use_fmod: + q_fmod_dims = [180, 180] + self.q_fmod_layers = nn.Sequential( + nn.Linear(app_input_dim, q_fmod_dims[0]), + nn.GELU(), + nn.Dropout(dropout * 0.25), + nn.LayerNorm(q_fmod_dims[0], eps=1e-6), + nn.Linear(q_fmod_dims[0], q_fmod_dims[1]), + nn.GELU(), + nn.Dropout(dropout * 0.25), + # nn.LayerNorm(q_fmod_dims[1], eps=1e-6) + ) + + q_geom_dims = [180, 180] + self.q_geom_layers = nn.Sequential( + nn.Linear(geom_input_dim, q_geom_dims[0]), + nn.GELU(), + nn.LayerNorm(q_geom_dims[0], eps=1e-6), + nn.Linear(q_geom_dims[0], q_geom_dims[1]), + nn.GELU(), + nn.Dropout(dropout * 0.25), + # nn.LayerNorm(q_geom_dims[1], eps=1e-6) + ) + + k_geom_dims = [180, 180] + self.k_geom_layers = nn.Sequential( + nn.Linear(geom_input_dim, k_geom_dims[0]), + nn.GELU(), + nn.LayerNorm(k_geom_dims[0], eps=1e-6), + nn.Linear(k_geom_dims[0], k_geom_dims[1]), + nn.GELU(), + nn.Dropout(dropout * 0.25), + # nn.LayerNorm(k_geom_dims[1], eps=1e-6) + ) + + q_final_in_dim = q_geom_dims[-1] + k_final_in_dim = k_geom_dims[-1] + if self.use_fmod: + q_final_in_dim = q_geom_dims[-1] + q_fmod_dims[-1] + k_final_in_dim = k_geom_dims[-1] + q_fmod_dims[-1] + + self.q_full_layers = nn.Sequential( + nn.LayerNorm(q_final_in_dim, eps=1e-6), + nn.Linear(q_final_in_dim, lq_dim), + nn.GELU(), + nn.Dropout(dropout * 0.25), + # nn.LayerNorm(lq_dim, eps=1e-6) + ) + self.k_full_layers = nn.Sequential( + nn.LayerNorm(k_final_in_dim, eps=1e-6), + nn.Linear(k_final_in_dim, sq_dim), + nn.GELU(), + nn.Dropout(dropout * 0.25), + # nn.LayerNorm(sq_dim, eps=1e-6) + ) + self.q_final_layers = nn.Sequential( + nn.LayerNorm(lq_dim, eps=1e-6), + nn.Linear(lq_dim, sq_dim), + nn.GELU(), + nn.Dropout(dropout * 0.25), + nn.LayerNorm(sq_dim, eps=1e-6), + nn.Linear(sq_dim, 1), + nn.Sigmoid() + ) + + def forward(self, q_geom_feats=None, k_geom_feats=None, msk=None, fmod_feats=None): + q_feats = self.q_geom_layers(q_geom_feats) + k_feats = self.k_geom_layers(k_geom_feats) + + if self.use_fmod and fmod_feats is not None: + fmod_feats = self.q_fmod_layers(fmod_feats) + q_feats = torch.cat((q_feats, fmod_feats), dim=2) + k_feats = torch.cat((k_feats, fmod_feats.transpose(0, 1).repeat(k_feats.shape[1], 1, 1)), dim=2) + + elif fmod_feats is None: + raise UserWarning("FMoD representations not provided.") + q_feats = self.q_full_layers(q_feats) + k_feats = self.k_full_layers(k_feats) + for i in range(self.num_JPUs): + q_feats, k_feats = self.joint_processing_units[i](q_feats, k_feats, msk) + scores = self.q_final_layers(q_feats) + return scores.squeeze(1) + + +class Joint_processing_unit(nn.Module): + def __init__(self, heads=2, lq_dim=256, sq_dim=128, dropout=0.1): + super().__init__() + self.q_block1 = nn.Sequential( + nn.LayerNorm(lq_dim, eps=1e-6), + nn.Linear(lq_dim, sq_dim), + nn.GELU(), + nn.Dropout(dropout) + ) + self.norm_layer_q = nn.LayerNorm(sq_dim, eps=1e-6) + self.norm_layer_k = nn.LayerNorm(sq_dim, eps=1e-6) + self.self_attention_module = Self_attention_module(heads=heads, l_dim=lq_dim, s_dim=sq_dim, dropout=dropout) + self.scale_layer = Scale_layer(s_dim=sq_dim) + + self.q_block2 = nn.Sequential( + nn.LayerNorm(sq_dim, eps=1e-6), + nn.Linear(sq_dim, lq_dim), + nn.GELU(), + nn.Dropout(dropout) + ) + + def forward(self, q_feats, k_feats, msk): + q_atten = self.q_block1(q_feats) + kv_atten_in = self.norm_layer_k(k_feats) + q_atten_in = self.norm_layer_q(q_atten) + q_atten = q_atten + self.self_attention_module(q=q_atten_in, k=kv_atten_in, v=kv_atten_in, mask=msk) + k_feats = k_feats + self.scale_layer(q_atten).transpose(0, 1).repeat(q_atten.shape[0], 1, 1) + q_feats = q_feats + self.q_block2(q_atten) + return q_feats, k_feats + + +class Self_attention_module(nn.Module): + def __init__(self, heads, l_dim, s_dim, dropout=0.1): + super().__init__() + self.l_dim = l_dim + self.s_dim = s_dim + self.qkv_split_dim = s_dim // heads + self.h = heads + self.q_linear = nn.Linear(self.s_dim, self.s_dim) + self.v_linear = nn.Linear(self.s_dim, self.s_dim) + self.k_linear = nn.Linear(self.s_dim, self.s_dim) + + self.dropout = nn.Dropout(dropout) + self.q_out = nn.Sequential( + nn.Linear(self.s_dim, self.s_dim), + nn.GELU(), + nn.Dropout(dropout) + ) + + def forward(self, q, k, v, mask=None): + samples_dim = q.size(0) + k = self.k_linear(k).view(samples_dim, -1, self.h, self.qkv_split_dim).transpose(1, 2) + q = self.q_linear(q).view(samples_dim, -1, self.h, self.qkv_split_dim).transpose(1, 2) + v = self.v_linear(v).view(samples_dim, -1, self.h, self.qkv_split_dim).transpose(1, 2) + scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(self.qkv_split_dim) + + mask = mask.unsqueeze(1) + mask = mask.unsqueeze(1) + mask = mask.repeat(1, scores.shape[1], 1, 1) + scores = torch.mul(scores, mask) + scores = scores.masked_fill(mask == 0, -1e9) + + scores = F.softmax(scores, dim=-1) + scores = self.dropout(scores) + q = torch.matmul(scores, v) + q = q.transpose(1, 2).contiguous().view(samples_dim, -1, self.s_dim) + q = self.q_out(q) + + return q + + +class Scale_layer(nn.Module): + def __init__(self, s_dim=1): + super().__init__() + self.scale_weights = nn.Parameter(torch.empty(s_dim), requires_grad=True) + nn.init.uniform_(self.scale_weights, a=0.01, b=2.0) + + def forward(self, feats): + return feats * self.scale_weights diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/datasets/PETS/FMoD/pets_edgemap_b.pkl b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/datasets/PETS/FMoD/pets_edgemap_b.pkl new file mode 100644 index 0000000000000000000000000000000000000000..22097bf87d9456abf921d9774d9e17b763eaad4c GIT binary patch literal 2739 zcmbuAdoyt`(8y3OW2WRX-BC#DIu}kczNsX2+ri^05X=(~HU1qAIrZvl1=d5%7IPV|tAK&%7&-$*bbW zlzM++1bhX{m8&dmx$C!C2x0_t`7!}s?tudSjKJ`K;3z|npinQvfbbnWKljj3_b35> z>b6iXkD$OXUTC-nPmnF(%f1&1`0|0Ce@U_hHd2X#FQvB&k_GmHxi-?a=F*7*UwOW) zCod}4>)o44-X`NB8|l9Ulljt&z|PLj`tA66f7wX!1l#vm{30VIHPfsG3xcO0U403{ z%APmhsPR~puf2a&iS>N<$M}J$yabn(u5qD61-7vg-vxUPTjhJe*0D& z`$&Rbp#(n%+yZ~-3gS5R818F_t$9&Y*q!U{`#rLi1-e;UH_jT!1ZIr#Xy#mE;K z!T;(42(?1?)Q#dJ^ z;5>-S8wWjA~AxxYOqc96nw|K;jmW=mbNv3 znOcfq$2ydFR%7IT0R-c%$DbU=^Az~X`6|3?QD3Eh=}@)5I#I3qIN42_%Xr((LG&R9 zq}~ss8RN6Ch1pEBvo}uM8-t;90!<&EMMr#2StBEO=CYgXZ(T?|=^|>CKSp~yt104k zAt|)^F@+{E%=A20MsJZTV{%mv-Ud^##`F!XTs%r{!(U)`y%S1ujd5Go5*HWlA$>_O z9ZlU$v7hvp<7PSS&=XR*!Ueh_Iz++Vhl%)kq<%z19gEMB=J8s3q zx$0MB^Ja`Jny=G=qDz$Qe3iEM+#%lSKI+!GNX5PvDB#suGPUZYpN@#>D?Fr)bABY1 z$eZ+bM{e%j5ilCh%*Y!0%L!9FjCu2rpmPavQn`>%7vSE35-7$9 zY4w^TRP9qhArA2*@jFU-CTV14oJL(PNfi93lyuGFDf4OqSsqHDqc3wQ@Q;HOmzG7Q zFXH~@_rLNN_#gQFF`mC3M|*lO%ArY>wlvi1NV;JhdcDqo7z<-k>oBDUkCxFlMxRi6 zw*gtVEutI0uB4qWm(o=m4$T>`p~uO?7&!AB8G|F3KG=z3}oS|2%&e7(+I_m2>NJ~l@ zNoz2V4t|tRs@@04=t&*P?A=T4 Date: Fri, 4 Feb 2022 17:05:14 +0200 Subject: [PATCH 002/374] add param to ssd infer method --- .../nms/seq2seq-nms/inference_demo.py | 2 +- .../object_detection_2d/ssd/ssd_learner.py | 14 +++++++++----- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index e5e670889f..4f2ac7b0b3 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -15,7 +15,7 @@ img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg') if not isinstance(img, Image): img = Image(img) -boxes = ssd.infer(img, threshold=0) +boxes = ssd.infer(img, threshold=0, custom_nms=seq2SeqNMSLearner) seq2SeqNMSLearner.fMoD.extract_maps(img=img, augm=False) boxes = seq2SeqNMSLearner.infer(classes=ssd.classes, dets=boxes, boxes_sorted=False, max_dt_boxes=1200, img_res=img.opencv().shape[::-1][1:]) draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) diff --git a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py index e86e954ffd..dd800895e8 100644 --- a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py +++ b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py @@ -539,7 +539,7 @@ def eval(self, dataset, use_subset=False, subset_size=100, verbose=False): eval_dict = {k.lower(): v for k, v in zip(map_name, mean_ap)} return eval_dict - def infer(self, img, threshold=0.2, keep_size=False): + def infer(self, img, threshold=0.2, keep_size=False, custom_nms=None): """ Performs inference on a single image and returns the resulting bounding boxes. :param img: image to perform inference on @@ -553,8 +553,10 @@ def infer(self, img, threshold=0.2, keep_size=False): """ assert self._model is not None, "Model has not been loaded, call load(path) first" - #self._model.set_nms(nms_thresh=0.45, nms_topk=400) - self._model.set_nms(nms_thresh=0.0, nms_topk=1200) + if custom_nms is not None: + self._model.set_nms(nms_thresh=0.0, nms_topk=1200) + else: + self._model.set_nms(nms_thresh=0.45, nms_topk=400) if not isinstance(img, Image): img = Image(img) @@ -594,8 +596,10 @@ def infer(self, img, threshold=0.2, keep_size=False): # name=class_IDs[idx, :], # score=scores[idx, :]) # bounding_boxes.data.append(bbox) - bounding_boxes = np.concatenate([boxes, scores], axis=1) - bounding_boxes = [torch.tensor(bounding_boxes, device=self.device)] # List based on class index + if custom_nms: + bounding_boxes = np.concatenate([boxes, scores], axis=1) + bounding_boxes = [torch.tensor(bounding_boxes, device=self.device)] # List based on class index + custom_nms.run_nms(bounding_boxes) return bounding_boxes @staticmethod From a9f26c4d011bf7d089074e0f1324715f98ea7630 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Feb 2022 15:14:44 +0200 Subject: [PATCH 003/374] Update dependencies.ini --- .../perception/object_detection_2d/dependencies.ini | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/dependencies.ini b/src/opendr/perception/object_detection_2d/dependencies.ini index cc6fdf0366..27c8307f01 100644 --- a/src/opendr/perception/object_detection_2d/dependencies.ini +++ b/src/opendr/perception/object_detection_2d/dependencies.ini @@ -4,7 +4,12 @@ python=mxnet-cu102==1.8.0 mxnet==1.8.0 gluoncv==0.11.0b20210908 - tqdm==4.54.0 - git+https://github.com/cidl-auth/cocoapi#subdirectory=PythonAPI + tqdm + pycocotools>=2.0.4 + easydict + numba==0.48.0 gdown + linux=libopenblas-dev + +opendr=opendr-toolkit-engine From 3fc20e1e55fc01399f410dbba540d0b0c9f2d8d9 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 4 Mar 2022 19:11:11 +0200 Subject: [PATCH 004/374] Add files via upload --- .../nms/cluster_nms/inference_demo.py | 18 ++++++++++++++++++ .../nms/fast_nms/inference_demo.py | 16 ++++++++++++++++ .../nms/soft_nms/inference_demo.py | 16 ++++++++++++++++ 3 files changed, 50 insertions(+) create mode 100644 projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py create mode 100644 projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py create mode 100644 projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py diff --git a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py new file mode 100644 index 0000000000..b5ab597beb --- /dev/null +++ b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py @@ -0,0 +1,18 @@ +from opendr.perception.object_detection_2d.nms.cluster_nms.cluster_nms import ClusterNMS +from opendr.engine.data import Image +from opendr.perception.object_detection_2d import SingleShotDetectorLearner +from opendr.perception.object_detection_2d import draw_bounding_boxes +import datetime +import os +OPENDR_HOME = os.environ['OPENDR_HOME'] + +ssd = SingleShotDetectorLearner(device='cuda') +ssd.download(".", mode="pretrained") +ssd.load("./ssd_default_person", verbose=True) +img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg') +if not isinstance(img, Image): + img = Image(img) +start_time = datetime.datetime.now() +cluster_nms = ClusterNMS(device='cuda', nms_type='default', cross_class=True) +boxes = ssd.infer(img, threshold=0.3, custom_nms=cluster_nms) +draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) \ No newline at end of file diff --git a/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py new file mode 100644 index 0000000000..8527647c84 --- /dev/null +++ b/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py @@ -0,0 +1,16 @@ +from opendr.perception.object_detection_2d.nms.fast_nms.fast_nms import FastNMS +from opendr.engine.data import Image +from opendr.perception.object_detection_2d import SingleShotDetectorLearner +from opendr.perception.object_detection_2d import draw_bounding_boxes +import os +OPENDR_HOME = os.environ['OPENDR_HOME'] + +ssd = SingleShotDetectorLearner(device='cuda') +ssd.download(".", mode="pretrained") +ssd.load("./ssd_default_person", verbose=True) +img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg') +if not isinstance(img, Image): + img = Image(img) +cluster_nms = FastNMS(device='cpu', cross_class=True) +boxes = ssd.infer(img, threshold=0.3, custom_nms=cluster_nms) +draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) \ No newline at end of file diff --git a/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py new file mode 100644 index 0000000000..25265d3db3 --- /dev/null +++ b/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py @@ -0,0 +1,16 @@ +from opendr.perception.object_detection_2d.nms.soft_nms.soft_nms import SoftNMS +from opendr.engine.data import Image +from opendr.perception.object_detection_2d import SingleShotDetectorLearner +from opendr.perception.object_detection_2d import draw_bounding_boxes +import os +OPENDR_HOME = os.environ['OPENDR_HOME'] + +ssd = SingleShotDetectorLearner(device='cuda') +ssd.download(".", mode="pretrained") +ssd.load("./ssd_default_person", verbose=True) +img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg') +if not isinstance(img, Image): + img = Image(img) +cluster_nms = SoftNMS(device='cpu', nms_type='gaussian') +boxes = ssd.infer(img, threshold=0.3, custom_nms=cluster_nms) +draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) \ No newline at end of file From 937cd60180906aaaa3df4ff74c49267c8cc86097 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 21:36:29 +0200 Subject: [PATCH 005/374] Delete projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp directory --- .../nms/seq2seq-nms/img_temp/frame_0000.jpg | Bin 325104 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg b/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg deleted file mode 100644 index 5efb4d9298de38969e29c3bc98f9c91a5ae99849..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 325104 zcmbq(RZtvE6Yb*e5?mLT;0_7S;_hz2-Q9xg!lHrTy12W$J3)dIoFGep0J+~^bsz5g z?RlE&o^u|is;lMv+xWK!z*Uq3$pPTt-~bB$9l*aWfb{=v|6le$kpC}$|2_UU0Kh|q z|BL`YfTIJzjWjY=p<&!a&kWq}4H=GAnUwhT{0|G+@PC!^(2)MypK zs0}XuO)BddIk@;A7$w|)VE-=}009vm2>^$Tf{ON^TMq9(Hyi>y(tkw%@xjAm{Kthy zi-^w+kVGP&)388xC*%oFL!p-{(rg@D{7uBW547|kmcB)0(6aK305kIO7dQRe1Yjck z$AgD}2lxcouwSP=W2werz)WVmB2h`c=+F8!0tmb?w@V&BbEsv`U2fJ-)<>#55YH*l zwpQImk#3ty4x^ITs=;hkm->>as<5my9|4f&qU}Saj3v8y0)!!dQYb+pCR$xlD%?M^ zB7>mT+<}gJBYUe*8YLvubhq`z98ej2iulj!^$?GC#e>PTH3|zC1mA*KgoNu|?@u4t zIAR(6hMCUC7K&1t@XkS3S`+XuE|T)W@S%elr@G8j>$=`K&*CGCoO0nG{{d8!$2~+5 z`bM%h&VKA$r}EMHSdI-Ky%FmEfd?UYxUD=n60gOK;r1QhR&+1Xfs%A1%RCDAQlT1_6sA@2(NXd<(^E8++XW zA=k%u8(jEn0D8wNO%-wgeh9DpHg+OA4}_85cuyagW;v@zZE>?wq3jloM-l%@6bX+i z<4g0B^jj$TFi3S6-?zCx6$LV)DW(NQc<3dD^HLo^2`*h5_y^cB`%cQKT~DuT@P%=L zjj+7k8WJqC&Rd_|f}37T@O*WEsJ$}Evz`tc=2a{ccqLR-rDnoYx z4K=?XAoicSc=(&Q!wSEH1B0G^Bo|g$p@1j$no}rpjFHXgmplDya(elv_bU_)3~i3; z(Pto+>o&>eBVS$ZXyXh~W-l74GSM)ZmJ(J=Qs*2riLTX-%dL<;M@m?QHY1MgtNMfGMHLtzET`(NTNY+@wTA zOu-ZCrAeiqo~$$0D+T0Qe5b7x-@90*SKeimG|8f8b1C(fengcs{7o=()}mXj*N=A@ zAz|KX*}g@|x_vSGI%B23 zoh&k~%A(+C_@7TzRjGx`AQpL*KJDroOfXj5^UW0Y6BIFS@*2g2vR>Be?05;PF_~IJ z#c3T#lVZq*DI4#(xj~LU$mD+8it=mdlb*5}a6vPCQ{+xtS3i|YKx+~7Es6S?CJ1l0 zgPclq;Osr>g|oW?N(K<1!q*H=MvykvxlL(=zjoBubpf*YaS{u|KpR7rbiA&1*HOeg4~X( z%D@|QA=`S>t9T@55f>l3>WypK-{~i#z!UzYHy*xpsdq_3#O$7tZ(u(*N~&#`p;)Nw zryL-YPW9c~Gd>oZy|uOzJ(`$C3ofA#VJqXg7(#NFNyGST$Ajf=Z-#6|Z$?Wm9@xcrITD?yz zZF_$mb&5>nSr3`lVSXONuA1e){1=m67A9BD;?mF4XB~t%i-y%FkKKB?Q%*w?hL30` zNh+#nOO`2Fr0(5nc*!oE6^YrDLALrkrvCt?!w3Sk<#7*FQfR0vAKC1P5aG1B20q31 z9ARVmbf5QQ>McSI#m(|WFFmVnNoZ7xq;>qfOu2rh`6!!{byL88m6V1q*IzKzF7}tc zN%-eWVHmT?r=D{bxWpIQNS;I9OV&PqMWYY+SzIzp!d(i+Dpj6t$o>a-$bU(!FeEp% z^!8o;2S{K1Typ*Cx#ZWM%#P{mLa04o_IqyU8mW~rZwx`1<|JLI&4I7<0qiB_4r2zb zXY6jeq^ZySd2tn?{>70W{5R-V&dwK0ROo(D{&75E3X7s5=&{x<);u|_ItPQ5eWh(j(`F1 zJA4{Y=q;i11yIpfj_Fk<`YZaoUMV>MR_nUramFtq6zQi-=IkMLQI&TaaKnj~&HCwX zYtZ-``Oj+iHv@4^_h5`SelK=B$&>n*_%~6#W>r`3k8A;sGxMT6iw4c;q*j^O-$tz* zw^9lqhQ?nz7vH#u0hfi{&qnXL!Ps{5-|ho1*k_=M=^@{)Y2Y^EyxFi-Kc7NBy%sfFOvOU7N68N;+hs#A}@5&@ayEHN{T zT2B`Gu|Xe~6=uMwi%_#jxb#cid>3(yLrS|E=WVz=L0#b1)OPWWPo$b!{k$Mp+fa?r z2Dh&gEr=5fc~Z3?M{XA{VHBP8Gl$VMhdMCtLhjbY?EQPT+wSlBg@1rG*IZ}n;yBM) z9D$y$yF)Y&c`R}@E4+n9M!9diBTHh<>}yM^lzaYfAL7T(Qg}tMl_|;JbwbPgm&-ZP zwngSoT#cX8PkL|p+Q0h8y?3l|X~`1aPR>f~q|j&pA9f<0z24wddy(EFkJWVM4A`cw zH(s)R(ri3Qz5W4W%PTbL3Dc*oOK-EcrF4Zx%EkGEMIV?n&F&8TmW#Q)Z?iA|0Spdm zkFQ{e8b$^UA?9D0kLa_|^l(CSnspVvK_{Ht)I zzZRQKH2amcQF&UL8wOdOOIi&H@^0g)kwm;(Ig9r*%^p5dU&}TwbLoR`RquGVBu=fF4?OR${@LUCgqrzZna17kX=X$bskZcc`%>-iaQgbdEfZ66Eix~ju5jeI zQOR%b%}MOFCB^LBhUD91-pQyNV{1z6m~H4AY$Nd$sv)5Yn~9z4fHG-lOl-yv<_cdL z%@6vL1Nko|grI}p*9=0W<_`DglLZH@d1tFq{V%Dk1B?Q>raM!r!gOrNBd#C*>IR&? zm*_2DCCsHfm(g<;#;(!_0stJc=9TIn8tH4f%ho+?yF^88^8-?iTaf~IWl~Amhf;qa z(9oqD!VvA);Jwht2Eu$)Rv-McCcfN$(pvGP1rm!jotYNr5hfCEle}l#e=M(xTM*`c zTS%#5%lOr@XgS_-t5Amh{p{5!)?Evg$tXu8!XSSLETDBRn8wDshcFze)F6#RY0&vec`FKCO-f!z&!Ix|pVCE%`Av zZ4EW^euM<{qQnx3JS94l+S#aF4q)V`g<*p690*;g1swauiDOj3vVyrwJ(x}K-(#6a zSSX7&aiDkNV*!J{1P?b@uh9|)J>vxXRtjolG3>+x?tw*d`?U9mRw67cH~kr z)y_L-X93A~;;h`dfx6%o=d?H{;GIz{V+o!LJ14$?1={Br*#zXz*uS5-mq{E^ikSy} zu2?)Yq5Ks#7)065In~oIV?APr4_~~P4Z69+RC}R)wFe?@5oX*a!N(PvQ1sODwl;BH zr}R;tT?Knu+kC;fa>=TsJxSskOsBqd;fr9tA5vH6w;M zu&O6dnna2uSH63li}wHWJsParcZ|o7{C7m z2%cM>>XdLmXU(1>_#(ptJ0_Z%wHp5b2{6;!R99#x*G@2+=f|D!f-&+EZVVlp! z?J5uTa@L;0=!9p=cSdnenWHPM0bSx*oy$Awuz*O?(*QG1Upzxd++LN#$mFmeP^so6 z+0R=M{+vw4vQ%LaOmD`OrKxg>!bB`-HE$XTlc_IWnif+v@Pe>6&df!FP?0~c(i7G0 zw?}&QRU---r7wRvn_RR9w=a-Nq>os=v{M_tK{;YC)VrhSy&fqn&tR)#(d^|xz}&oR6WRr5|?KdPEGC!f7OnpMec_iT|*`2?H!YI=U)NCV1E+y7qMlZ&n1mRBD-B0 zhdE=Im^gQZ3cI|v9DOHpW%^RZ-8mMI)B0fEOe6|Z{=MdPEv8cXJ6~zMK_Jtax4&v1 zgW@Zgc`D_oDHSDq#`d#Acn|D^irCwfzS`e_%pFZWUW0K@rp3qEt^yxu`*;&?DY@rO z&9Xp3@hkh?WKF`%`&yChxq9I+K=BjLoxZ+_P6-gOj#Q%Oh=+0 z)jti+W;NN|h+ZyUKA)+kym(%?^j5tWym=nUd6LGT1-1srE}a|}TfB>?66lW^fBwFpZ#;+n&HcD;Ip9sK)9D-0 zJ<*&QDdN-eD)(x%L|!1iwd0U0DZ!QIYYx2pW|#oM`Ses>?CdkviCGrOF3ZuWYHR&s zXF+i~8%{yw421;GSJm<%ezB`W>sG|7m@`rbX(a|Ju@z0@WNt5+zbC!aQ4Zx)DA0u2 zZ_EqRJlXtk#Vf8hbn=OQHEgbj_R9|NtH_R&X8*3MKc$E0d*regrrj;PbsS237j7FE*IKOy4>d-ir=-$Rj5EmLT9 z=g*cp$rn9LoBW^>HRmTahcC=(HYfE)v=sa^jRU%z+BaM>0f&*;aIlH2=T~@X-&B5c zD$uja*8#IU?tcI*FXWFEs*<(={{Y^eSd7x74okp&c1itO!-FJ~&A9UbRi_%dlImcK zX%Vj&HK}r&%sR!AEezsXsrC~EO4s$#e$g8R%O+ht2-Ambq$BuIrwJ8tB znZktf+?9Q&Ga)zXGPXL1j>%iy?yKN6c1Z-Q->c4&q%8-Yg!ig<-CRjqSJs;?rqFmb z^T8HAIhf2dx3{ZTzsf&=dQ+orJgZ_Adocs7W@cfOIdnQYD?aHo2Kef;fD1Z*bk|cEJLI4ZzK9lc&qpWv)o4S+(*qU84J{^F8eojS$rf^f}4$p2XDqMK@9Q|%2ICDn@0V`PX&`7Ci<@yvQ$Kx8W@G~X1NfXYmo_zgkAOxQl7bqv1gjkzfE*sMuAxfU8=t*t=^H?>v*7AzpID%6U;CYO+Xn#)B9A$-XSNEbwH+?RpLV!mVOOBp7@hhf< zC>ehRIzz?z&#VpUU!b^ZvkxiD^#M1v;0V3kc=}aE9Hw&G+~)BX-QCxrVi16u73$^X zbC5ITe#|2^P`*Z5jQQpc=TUJ58O0$n=J30;QsK+w( z1#?EIX2(s|`rtS_30FHruw=o!@$n#2JGl!|pA25<$U0brIH!IQlPlMAa^$GDw zSA9tRP>oq$hqa0#zPk6j;|I;a++XzVsufwk_@vBK0!Rty!X8ptCuoimAG)xZIn?<7 z%3{t7mDXGYF18Tc;8VH=XZ`K{2lyl!qiZys(2TgKlc`^zp+DE%$cNv~v*#-Y(z)pc ze@6J6WABdn&JqIe=&?YmaVf z`_a}u?w1-cNIZE-N6th@z9wB*NAl5{0u7kBreoeE&5aQMD^TqzbMHP<#!nc{V6jdF zwVRVdiPeW)J`zgc=s~MP)`Q~R+skkSv)a52@3N|PAFZyOWP5BtU! zq-l5bSY*vZ-LcDnQAeMK5MWo7ENh@?FStt0GN%J+aEx%*2@O2^k^{s38ed#PrprTw zRP)O7wQ(on$E3JQW~k_!2&OSaW$Hhkpl55&b57NU38hv8S#%7jmE*(25* z(mg7%_=Zc%_F%8n96HVjyY!_STRADki7m~dZt&Dk6l?Bh0@Yb+L#2Y;5h{`Up*l;< zu&7Mu`brGuhxMP5wv?%9JWfuHVt5BNidh9Bx3i~eggm1rQZqvawdWlf)0m(a`PDyx zpu|scc=%KF`T~82wo00Ed$MfKG*s++Cn+ua@<;_L#;T?Jq*pp}Kan>0)6>VD9#~H} zDyI>jNk%kDX}QM5aP@W~38_lP3Gj~-`#s?D-0>QMN4=_VAoUq7%LX;7{nZDeT2Nd4 zoLC!X?q5rqQ5FB_L-<5#mQSeqp=KqUEL;l29BX=_6Byu%KP zY)^8nQ6&M(QaTny9vP-WHKuxCYmkVnJ@3FvwJR0WlmAcgH zVTHFT;P-OvPG>F^MOblizC*-l2FNOvulYwUX6wlj!0*6~fu_jsxnTTz$Po^~R+(;z zj@=zje6)5Pk}evL;RnYo3(6e9PDAGHs9n17sl1j&Nw$TQq2g@V73FZ5BHH5I~`% z5^%nRG9+^AkCrWLqB3SLjB3#ApIHXd1aYqqw5y+NcS^ifGk;+RG$RRg$AWH78?Hn+7`C z+8cJsBc^PAmgQJa%e3N4pxB9%1zy@&=aNIpdq zFZt3#E3&~ZhRzM-k!Q9ex9{?I^BXOK51U=&!#XTH7n}!rm-Af7!fU7T>Q7j1_V5}??W-I*zq&gv9sxgXOHAkz=G)fzGh7(UFc8VCWOW#8_ zlH@86V_nC&u;Xr-=;gVVwcHaP4s%~M=Giv?#+4=3bV#Ej(&2tf%#Yo}b^IRZ&^W^I zQIp}L&EcbA8bd5I%8LHN)r5IT93sA2$N;%MY?g0u;;hiETBcw68oUaqU{K=1dmOPreFYX3Pz_ zTc#qTFFy-P{KJnW;Z$Ow#_WwwdWZg- zTNEfKn8wTBn4qpNGni&>-24J)h)6_wo44<#+h!>P)B9bU_5$Mw3XXT%GGt=v=8lI% zTeYyeKZv%2x{gSt3KjU{s9B5HQZ2-7o69&FbPR#6#?em~qbW>^12y8Y8#3&Zgbrz= z7o!9paIP(V`S4Y0h= zb?e7~W{OA{7tHb$gCbVXDvrU)TSh;l&w5PN1V>;Nm8|DBwAthq9RYT3;?2JuQ7XhZ z(EUQb7Ka+y7cqn~)24y?(?;+7p3XU58ATL-OWA4}3Zv_%(LER|08@7{VjV=fnRYJqnc7=OHC!9;b(hE4a+J*dL&`^h?jYM?=P{p%mPEFpjS+&4Zx z`SOa8vac5;buSy^Vx5AfT%-e+Y7h#&53Ly{UYf}k~ne&;He0O+uE zpvfr?>7}^0#n}ezOPsnAPZ6AI1e)Z}Zf+ff+ujH@&)Gt5g_*J(BmRM%oen06@%X>q z+ilM}mOt^ih$5|B8X`6>Y21I_Vg0IaHtsi|vt@2lwT$9bJ4>gDCNgj(fi_33VtNw1prRjbS3=<^q@q0cObEL1RwFs9}ZXo`)WV36!9hNtw%?^8naqB4$}cU=au&P4@^Aij>{7NnyOFnIs`LPJ8Ie&RvIf4 zp?|(q>!1Wr+{9>Lc2#^5pJYS1$iQP~lPRm-NJ}@7`fLrSEh!lCycg&@07TYWYRwZ~Sjz2vu}Yc%z9=ca#aO-P&d@iA~# zLrfxUih<{|c_2x(T14-&@ozjq`Suu~dF?RATTysUF{*`0YV`GFe6ihc5q}t7ue6bm z$dY5MDsN?vSRFdGi3hj_i_~qSi>2wKkUV~RrF;L?+NUmcYe$SXDA91f-c8y3xbN-IBKAira@lAlc<1!V2KL4v5=a=jo9@5| zqrN>~|FijO&diIsvhSr`Ur0l)vdI*#w^=krbV_I;7_*dBPCiVrdg|SO@KHaj_YA$n z-Xox#BvTi4eIZKWwJsmmN?}V|nS|%_=($ckCAGpW{ifGSynwOsm1G>UAEJ(e+r2D7EfL3Ex7o+BLy0UOqLD+y=ztLu zs2B5R72GR328$+ED?29XSxg~{nT-vlCscG$zY`9!G)sflKLpctpz-$WUCNse>tj-A z5>e1Gmh9YLD=^Zj&8({v?SyG^^=WWM!Eq*Y0f`mxS`>44Gsv!g3D#A0l%=tqY*}+^ zgGfQXhA)#n$35BjN+lgU)?RxtdXrL}q!-;JPr}2PBete8;_pg|;P+=+mh4~@R)E?i z{~PyM?^a`)D>VW$(F$5RvhS)Sv-6JkMqce@r>Wv_uWAZl? zeYWWSFyV*|`m-|HRMU+-B(k&K^)Yr+1_npQhX zJOf;4_Z1;{e4f&e8*7vQ2OG$r7+EFrL3QI2n>HmF0*nyw3Z&Y+J@{=XY=cQst3|57 zZ_q`QaxHSb?s5l}$>|Q&ftM4+9g89I;t?WROt%CDEAem7Ed7S3uTv?8GfUh3O!;T` z*I@_~M*0WE-_xgxgIHhJX&P@SmaVL@PSfA{i+Z1oS_Qb_Iqa_$F=O@NEn}GxGkH z;_ys?G5V`GBc4YQffO1=RUol~R`jK$^$w(O53rz5_8|55HHir30%-jMWQY7bw9bFZ z60n&rG?1nxM+$7pWG&=;N8Nl!fBZq&zR$8BuBlgT>Bv5N>9*Y z_d*-drb)7QXcJ)=4|TBlHJyffn9JEM+3VUU_JsWxpb%+JcSV@EB zjnVpj!bxMiGQjaynwM*G&VHlo-%b&Eaw>V#Zf>@gPXNX?HD_X3#4rHG+WFxQu=XR@ zU5;%s?@L-l6pis9<2p2bQcuFtNt3u)5%2wynMWTw_hDI{2vQQ z{T3jEGDVQT;a8#V{{ZxdhKLb?7Y%GZbKUIBa0=$-azYw%@mC*AF0Pi*>>0XJNjNz- zlWa5BlE_4F_P&(cH?giJLUthIbaCuo)tl{O5v=m?8VLUZL^tR|cn8;by~>p;L~=2Y zNT6fXY_YR@JhWCmqbF{iWIxz-_N9D@IBFeXH9c`YqC}?D+G3pBisA8ctvU`;srB`Q zvd4&`)i(i$cL<>IbnIWD;(re!r;=0e*=GI$DyT9pHsxuh>3^+fQi|slaW!Io_`M^& z%J-YN&^JQg7_D$h%&embYa(I*R}JI$ueA%W7ZyhCbPb+y5?uqQhK5;!Cb}P_6G!C2 z7oH+=O-S-|3S~TOsbv~;mPaxanW99oaM9Py6tKVaYy2-YRreoUj!#cKg?sv}g!9@p z6%cjrNsWA(gae0a{VoPgm4wNc=4tBnmT-iSbwscsCz|qt(z_0~_=?MW^y_rfE_~!` zlK|fK;4t~;+n>9u-xn&DQPR!S-rP@6G9(lq`a$01*e>aIo+SF$Wy>iOuoTt(`x@qg zov22FgO5hJ`lRwz?A-mFO68~Zb;RryprecR(6+40Upa(S9Ac?xWG-CM+bFRrOm3U> zGOnZZaZhsfgJMc*6)WS&C!6~vH26?ie&(&NPWbcA!#YpN0}0B5O_15}>kW(1G+SjH zZK?>=xeOSvw{S>A;@m~W!v^Wv&8r-jv;yd2AKM$uC9Z9N=lNszSbiq|=2IWSY zs0L>3)aHIGNz|EU1wZ-!&g585K8F@m7acoh_mq)Ft`U5mv+xPGQE`%Kvw~Dus@BBm zwSOcA(Y{(sqTcH~+|f0w2ScHgi39{4_;z=FE#Bo#jp|ObC>Tk>1D#W%SCdf@Sli`~Dw*K&zZ-UOx}* zSS|pm!j%${AJ`l@Wp$mI#~_AV-C3c~EMw>mbdM{68Qc8>Ea_<+E}e+Xl;_(uCP@uK zO7_~!(-)nmNj7-n@a;+|V~RK|vB!E`1wPH7c6~f=uYTFqGX76+3o`@1i7On7xRPg_ zYo}M=3Oguv__J6#n6$L9SUDNGN*3W(z|RcHBnnphg%p#vcFBF8O2YKyYp3CsQ=u#y z0JMi7tN4ohH=q3i1*s`vdi3WNV&BH#i3${`FH+|H2{iyj!7#%M+AF5(X?RI@ImGsw zzmzu!shv~OulNO7nodmn4CJvb|2dNv;^Tg_u*U}t9yAw<>{g26t6?er$?ntl2dzAK zZY1b`d{^-|;L)xR>m*!P@`{H4AaX_i zr2P_1|9O=(@qQrC_zadZZmn#pxl z6tOEYE1$CS=}&rk2{K0XFC6`MIX(46(#tsyUmWqGOFOMna+8H-B?3hQMtiiIRmskO zp7}%NQ5a~6^qsETzOQ+9)sR#yzVRJgHe*7d}I8$gD)y`%EA6#4PF0Dp@z*xKk>SEEd6-ASy!oi2^2MswG;kk?t8AUh^7xea1RgehF0~P)LXc7tLJn}w#OQEs-A#9`@4}Edty-RCaIOwV*X+ixMeuFk!AyiV7j_k@=j%E8BZjVujqh* z$5R4)u_C*|Ad95Hgcb(mgL;UpmSb{Fzj*m(w|6OhOlp5z3y>FOv~1z$7MIKysN=xQ zjt9Qw~ z19KK!4xs5$kGINFCZ)CEG{!yO%JWJt#pmMI+ZC6cwW!(|w_x9=X_j0@%{VS$KMUF2 zX_IHa=kIP=s)PUq3=Y*=_E9M?E1J6c!9RvG?}ld+RW2Q6v&LWo#0p2ebBmw|GerRk z;A0%ss}}C?9vkxpldhvyQ}!h=O*>c1_k%46ENZn9FWay5VE(t&+4^-x_wfhHcd-lynpET zY4r-sLcEs9o3%8UHX*Z)a^iz!BTcxYl1jaMvf*kWhABuJdvTy`b5dlNSubE?XY1js zCsEG*hiasav%`wHXT6gON=js~$k-R=GFk%6G|OVjx;vpqA3J zHYy6tjg`hG!Y==ReXSpN%!(kba$g%=kvD*hHVimJCeZWqH!)1PloDmHpdA#YsN z?{s_PJ+{srr^xm^!{+Q>K9<+N~+3E<*tCGe?A z&R%OVG^PLhIj>y$NuszD*?MyrU*$cxNRxHKN#Wa5Am+F5+V4sj=ZL&Rn_(l>HOvp( z!(gKo1&skf;<}QEUxHfsy=BHYW_uTqz;*MliUMJN`B%zPPJeO7l%-6mOq`idLL$Mn zvYN9!33H3e2gT$X273?Th%Y>9rhWw=)wWa1e}K{Tr2Dh}TK0-1oE#8VC^OejH@%C0 z08Wn$dp*I>|HL}4#N?Er1P(?d*F~fM$ty=rIF7Bx^lOGX9PzB2L6lR(ni#N`x4ZiC zXub3LIlDVL_lTLz^X}|+Iqr=rJD32Yv9$(^Jv@EDvhq|jq#=z|@vr2EUA^ZbLCBxR z2N7`Y5&o!9Nj-b9!o|+nX>QINDeV>>QkfovTyZYEPftE+!LO}C_V82UA~4jtZcrh~?BmOLl{?eR^Vwv1s->aQBYm-OTM=VZFM`XBWV>%r?1vuAq zdnX-wEBZ5gc&_-yLT0Q`g|5piRQrHx6iLBEa9+z0=`Ce`>V9dky`= ziR!3Gro)Ra>x(1UFH!|a0Q`Y;JOJjmd@foi@jmS{JgH%|b`?h+l291?AQ~do*!u#17QWwZLU-C{0qzHqU3(DQE%eo0>-a4I~>{Bi{L| z))9rM2Cu%fSP5TNeVR8&jrngW@L_+{e2E%cQ=g`nn$`iYFd6A~fqczNO7*pX z=tl|L3=eC=ulkLvy^4$IjiXxB+I&clZMqw*+VJeIRR-rrV#WRTM2_+tP$4khiw`}R zq8Ak5@mgL4OaTv~0kQlJ#1t7~&P|-$$B%}Ii?+)^wjh>#=M{|ROpf!DuyK>NBsyxf z(+jVX--{V;GI{HSO0?v%rl|b0e=ew(%e=pr-?ow-x807SROpXzkg6LulGuMR{EQB7 ze0md~gluu>aSCiQ1n0LAZF<^@`~x_i4PJyBn#x8-6hbAcAwSk0Byf^AUMzak-_sN8 zV}`s@)OQNZ8cGt+W^C1jAq^LnBO}8pBP*RA+UPUZ+#>{!H641aZ;>XaySyJas@r;! z?+xLzg4=4I4b~O!JidPDxwVkkjK%lOHLMvmlX5?AN|Uc!m_FgwX95d&{Ee{BagG(W z>vZk?9#5%%+A6E3ib(5|fJLrw5KG9R$jm>rSh64xEi|g^?~}R0S4~7*KtK|i4wV$5 zGA+C&>JG!WbgKG2w!*fI@dv$zBZuA`dLoqNHq{-QL=W0ktZ!kP{*p?Cd@R;*ud8?$ zU!eWm&(XnBq(2Yo_2)(YtG!gNZq9hL?<4F^4dHkzcQ%FGqptvr?o#IbY>FOVjHvXU z!%Yes8d*6yj#TsFoWu=sY+?S8B`zC=-a-)sw(E3hAq*07x$mHMqV!IvnY&-3{@LRy zQtHRtI#(}Mt5ssn6~*bsSdB!AjUM*}$EO@!i)7_Uy}AYAP+c~B5nvQ(O3>^Pb5o;^ z{9EKk6#mofAKY^;X!)<8%exS!nT;rRO0~$S*@pA+uHz`nk zB&hjfb7h|=4BeB_`n(u=xFJc5JCx1l*Iztp`urr`<2iPqY z@OSR;V?!jR*Fd=d)x)gh~ggRZd7#hd&|p$h#DrJK5yv)jh;$DXGo| zOmeVvNmsi+rjhB;tJtPsppzgU;c$e%_4HuZC%0n#z?up1NEIB3sD;{EmNrQb#?gV; zhQMxd1)mfoCQ|bQm6+)lqSGyqwj4WnK5yVQSeA~R79|1VbvGiv^lO22sT#T&IPi%$ zfPpjLnm9T)`&ZUJAB2s|Uu|aAu38?=KNe)%qFLo+8t{{eKnn(>GAX+8n)r*oCJ8S) z&diJW^E8z-N!XXcLb|T1q?+<}M=8qR&QX68dYVNST>0&CDtTP ztd-vlTPLX`(0og(vM{`)qCY1z;NzbjRF>B{xP3xz`WeGu=vDi|pNE%Tc{@%xi_x{* zd?TOCY$z+gt$JD+HMK}hKt*9A`7yIts&FhCO(}IOB7+yJJV{rf`_xl;)7Na+CBt;G z&A+yB)Kzo}SKXA{uV*v9E>=%X^L$#TR@rt!FH@fp!q|$KI+I3nls{E1C9cvyIqXJ` z5`sDaF_tncC4T_5bPQ<`(+@De$b%cVrV=$NzuP*!sP7pX8DA6EQpI5x z(R>=;j^sbV8X3u~O=F|zw_0A}^EXrj;>$fm>+Yb|&Wgk`=}26?oPK<`zl*FWi{CXe znDGDV&`sT5&)vM7?T4rZ&Di07>Pgu4uNkD!*_hAF>@9$|uL&p?NND^WS{PDz`?+bl zB2u=(9DQ2i!3V)Plv%-y6^X25g1#CD?`3+hM|?-MwhTgq7Na<1dDX)kc0n!&MtENO zk{C!};&qs^DX05Q7i?2&UJ7otr_oGeiwO)33fYnjq%JVFV%ipSu3s`+W<;3Bd8!dy z)8pZ`e6huJVHD$#tupklKc)>_!`hNE(v+n%#2wYvQ&=&qPtPfkMNr#pqd&7cyGN!W z6stbdsbBmDK)1p$yb7>MKw6eLj%MbWWzQl- zj0oyjP11c4_oU)}l}mOeO&E-cJ%ed#f*7m3`qUuZp2cHH9GM3jcyE$AVdDPX_v1wY zR#V>vUJlEwJ%`M% zrTja!vFz~^XP9WfrH=FtBQ7}sV`8n{1{!#uDK%d+;{vs3x1h4~U4A{h{!9aQ~(*FZ{K!m?$hEl?;Rq_|@wb;L-TFIrE>t&LfSC$y3vaf^7Ya?HXhJsnp?~_2}^T4NA1b2s^BqJ3FFSZcj=vP)7r+-wykx5 zBD@-vlglJK9LWorSj$wd!KjgRFRrV>JbOpt`Y3e~Y0PqskZR14$0V&hamVI3ZQwL+ z-n0s+5H{VStc`wP>+eHl4#b-Ammg*5LuzZv z1IH9os>;)H<*ngGx!OVzfw8ia8x$Lq3{GBZ3&)P8EwZgJfvLl1U)S1&;WylYM5G zM>1LaYnG>3tyG=O!}keVLh47`R`1P0U^{4QWatsBd0N1Tq@y(}^TzeX)wCs^K`~0j ze@;C$Z(#kc>>sp)uzYi+a*3|9V;SX{Y2%g(miHZcZX1zlCEvMSLjs{r$>;dc9XYVp zvR14JU|V)$l|NVQt2f(7l1#~H6R5;!oeIEFp$Pg?7iMcaRn#r4b-j$T(Kq zZ=T(*&sEQ=h-zPQunJXt#Z)1Rs_?=>-=*U|k;hE7vetD~e$u8!RbY%^nh8y4`68Is zxg61#vk4{KX~d%v&YFpwv39j;lgBiZKi#8|W9{Wvi`8CW$5ZqXQAtqj41LNhN6I-)cfTqw%83lnPkDBd6kWcuXB&?4s0uu}7 zNY+LMXq=YhEt6Qo9k0_B_o1~M!*Bov<+Qum z3)QXFn$&l_Gj)R~#mhWmFtVg&zTemaNMmCsb=V8o5#k-YhC>{Y-;E}Gf~>K_W=J@+ zM9Zr%#6cyv1T25**7keMgEyCw^$H=Y*@{V^2DoNLj9YnA(P<}dO^c8u_LAhrTlRu{ z79puejv=YnE67Q5G|2VN3+-S=cpvA+z>G6Ie}z>%0+VhyP(f;7Mk=v`ka5vECpBsc zLg2S;jJKI=M_RRbLpLKzMl<&UC*dC%R7dU`Jc92$*{ZZD!40p!w|QrZHhWD(NMS1= ziaN%Q;q;7xZp4?`jr{M#3z;d>y~_0RFAe)?I>`?TqP0n8iq&LAkbKA$2n+dMXR#f^ z;};^7;)d;L?@W_NEZZ3HjU1~Q`tRz=59xzlRk*osOaM~6h>X!IYCv5=TtQ12w7WMN z8L%kiU01)yTN75EL};|eHqY{95z!GuC@37s6X8GTVhQ>D4++3GyNnTXCOlvF1$;5&cm`Co{CQw6dK__HvYO~E`W?4$A zW2-FpRw8O3l0}4Ua@2NajY^(A;EH)`OaU8(W|jKsT1vLf-@Ub{#Ir{mt80-YNLUEf zW9$IgAPsMp!y-jIg!!Iim{nNgF{4lxH&X#a2N|+C7uM1>i4dx>S3qn^ySEzjg;pa3 zb9df>>cPKa+_nH(*0|A`CXp%nixh|_krHVdNN3=HNyVFqAUc4-N!o;Y8`In?RaT5@ z(fW|YB)ak;mQBed(bkEf1AgZ&RZkVs-(~sn`KhL^`?(*laK}8d&laX3!*f?nymewJ z!KEv%Z5sTxycA3ZYDuN^^6^I`cOwDewLNG`b5QV?h?6vg0N%3_pdnJAviQj(kIjlS zNQhvn$`pXEIloEV*M>O1j;9(+7nbP@f*9E{ZX^;fmch@zA2rl`{c80q*tKIOjy~~a ztftJ?*=1Q2EG)8uv4b-qEPH|g2TkK!+U%C|(WA*J%L&tOvpO~W#0aD z-TqIFhRkElRe~dK8!7h@M-&s;g%sO#ts_V)@70-tq^tKWrBz~w+~dZ-W^qkNsFFzS zRk;8%@f=^Db`*~ypdo;}4M{>%f9fRW2!_>y?tr}Rc3R2?$5D6ar#(2E+o~>8O zU}hoQ;aRXNXuYL~Kd{fa=qg=^W-c$O8Y016qKzQ^PEn~xV&nG!&#mj}4b z3mN<0+p3vkPbm5WNQwsf0ay|%185bSx;^aYqAd2B6|Y`8=@&Zk%M|a~;~P`@WStVs zx?|s41ZsTp-zew5OFyRyQ%@EU^^?aXzCENjf^#lmIw_SFj-XW3^^%q#{W(qwKI6HiANMNF8jCGz83;1t`?MdD>(Zg*8yNL{FQCrI@NNj^`Lbx}bv6iA;rXYsQ zrZF3WB9OF>IVfnX9JnZ zV=>EC$n4E(DXdtTAKG43Vtu`}hsX~*I?v6HrM%WF!-whIWH&3xT+(WS?Y&1NQ?ZiW zsa+$DWR1%*6C1YIdLAyHs`z@hDfAoCxGs>MI(fM~&+7Rv+qD#v*R7A6uV#Cb$r8_9 z8NSgTGwU-#ElDwCX45U7)363l9@9x8MCsweMw!1fduCrs8v$H@RfF3Ghg{FpdTmCp z$9{*>jW+#U-ZiTcMKLgiX!J@|NKk*MhTL*)jnO?j=lsj)+*FXqlIoll8DfS51}&{n zON}c6j3tR3Y`n5Fk7R2r@*oIVy~?BJXPlT1D{$2MgR5y~@z}d@z}0Nr$5_QhZYx9- zG{#bFR8~@59yS7TAP^?v#ZN)~f921cxahEQS@Q#^V0@NhC6(}ua1vJgcJ+g`j2lz7 zt|f_OhtszJFtB6!D?M#=zg_qay6O|sod<<{mRd++c*VQ? zg%}=V1k%kF2ESB8=_v&N08@@YT{WQI-L~uQuDglyhcBAOEHP%N^qjXURgEXqmg1`N zL~F?+--z(xDFR8PUci_b_fEU|cgg;=>5GQ{08Zy|n7fS-fu)C``asIn{!QZHK`i755KmAWk$bsGE(?jL} z04hAG4${8H$i8m_So$B#A2&S8>%2xItn*fv8)*`IF}0hL8O0Qe)G)kIO9d2&JgK%^ zVoVq+iwdmK$-KW*{XgjWC7nNgEN@bVB~`1>X1pGg?lMIT~?pyGzr#1y$Tph6W_f&_c)eFQp`sk^op)e^D(iyvTL`09t)8`MI3y zD|lfCOZ9g}bmld1`1h+WYb&3nmdi8{SGQ)}$fLty`g1Rl%Gfd(m2Kc7J1&5cd~!W> zsM=Ieu#M87b>6XK`J(o&(rVPQw{RP>!}w$3-VLfvR=OBr(MW|Lfwdx8+g}`QBuTJ5 zjuJquRn3F3usG{j{)_rztxmDZWRfPC9NnUrd-*UEODq3FL53V=dk)geJ)GzfG zvha0(leFPz&0CV@BAbTGfd}-GU}An$>=HW-p!}2J^XT2#GTG^ZBN=Ppk}%U5oJ_La z;>DXl86x2s8t!TjkU;TJ{{X13t^WWSc_kf));OeW;B_6hBTJ3>Aotpa?c5CmzWuH= zGqk#tW{rzBnr1tSQi26lHh8-`NzJJ1&9re!x~~^!kwXzLsZ7B@4G1KHi?o_M1rYal zW`^;32X4iGD|&tuNTaJ`6OZEp{`OUbcWr-f6WkrJI{7>Csa{#vjQRJFvm}w}x`U|9 zN~4no6=y_{VpWbv4+Sb}{|a2*iN)?Wl_O@89I>ekj)~I;l{_S)*0{rVas9Ox%-$ z@mS5bG6^&qn_|(vs{Lw4$u{~_-4M^o%>V{@17rTNxTit%WI*fv%96mx?PFEgMX5Hu z#>wr=+J1N7x0h3xysgH~G#r8HjAt1bLN&t^Txc{vzK6K~0338r_UR+)+Dmr&Po|OB zi1C?8A`&<(vKcBC2j_br6Z?Jv?nxuVpO@jF@{<`QkfeXYl-zMn1dp?jMhQK&>a=Bs zzsM)@a4mGvP-6?dsl#q%P;Z*|`REad@59Tn4ymL=mS74wVzw(igA9RyYaMFu(k4tM zU#(dLd|Lfd@5h*A^(XcXeprxq?gNK@N*tW8{=VJ zfM1jD?c2p;^k^%8RqJ6bSYF58)M!ID6%uOPlbIX0>Fh4YZ*fET?BmzjnJj%r^ky~E zO4aG!wDA(i=zi+3C1MhS3!f&> z#N!5lJI%C%_*gK2Sb z7X$(R0Vn5Uumid1d~ndx2^=zwPllRyE=sWsRZ`Vdk^lq)@&M0C_&daOI(I_RJ$RZB zgZX5$7AJAd<2mi|*Q4lh@W~>{DqCWql>n23O&kuYba$e}xc2w#4`N2VPDP3+-f5zm z5Uc_Qi;@)48)x|=_Wl4n*xrcoN?|CFjN zu!wBSw&Tielq3Q%^q-o!jLkS~Wg^4Yc%;bIuqxEH>W@<`ZyN(ydlqIvA%+N4=>uu> zrBt^3akSdEJBeMS07Ex%M~WQZ2frU4fZC`Na**Tseqg1%?gMTK_PYo4>ivdlawHBp zPRONDLl)L1E{*CQ-rXQ%*zOB}KX-CeuR#^^@zZ3C@)5)s28cXvSQyFLteOq^9f#*Y z&>cPImF%uETXNH-6w%wuV;-eP^w;h&ISKKPD=8#ttmB>BZ(K`!YhDK6{LSiYz9x;f zw~fQvuWKz{#jJHfW;sqbCpI}Gfg5QfM;1BOWsv%NBoI4z(9%cjtGqpAm`KP$5=eu~}tSuw-BlVM~9fTRygIQ%Q)Z%@f807=6;BzVv&J!B{Sd zAGm{|zjivd8Kr_b3P$2N1kXHsusP|ImdMm)Hiuu5tO(ZpYv)J#pXLSbo|bHmQw=?+ z>~#(@e65@{c+n@rXEHP(dbO%e3=+sh4Zjg$MlWcG-9hhJ?>S# z92R1pw9L_75oN2Dl`q3)N}S!(?NSnBCq!61Bj)|ir^sXR`P^*?GC3@DYn3IU`k`({ zQETmFMrmXdqzodLYDU?>ZsRSo;tq4U{~#l<$G%HJx! z)S*fRS2U%E!L#~xdkppY(G7P)IdoA6pd2$q!asqnX-f`U_!`%J_+-ZQJ=`By`DxV` zWr3fiJj&>vsEH)(B2J&`Tz*l&QUD$6uD9{;2jm|L)$%iXaL(@^rrg{QZx>lk&uuqo z+AzP5k-r-2^$pZ>`+>6AOZ&`L{fI!R(utt zZxYdn;tMCA6DUTq-dS5v2o+-&n$N*8)+mZIGUi7Or7fDN)SzMw*3H&M8{)@a(mt}Q zL1*b}&v`6QTC^C?EPAs)C5w}q^w@T-Zfh*U2d#2P67Kd8pql!e)#07&)pcfni z=_Z(ik)MI*-$tYU2gP(~%1m0+S7M}4QdfQ1uy%f5VsqBHMVW%Nq_I4PYSTcq<#0A2 zS)CB_(d@qN{{WG(_|fo_nu%hkk*yNYp1r$mEK$5`Gsv@pYhhj~KrWJ%B%m5S*bc~y764gB~Cn8d8|#Vk?J5Q;|hPkuV_M+Da^N#%xqN1$B-0-TKCABr?jeyw$pHqdtlVs{;{{WhRv-C!E$ zCpiT4mqH2dS&?Z=1{xJH#*yNv;;KDfIxZ)+m7%bb%HR{qLO1)DdgAX#7{!{K-O1dZ zNft?Dv1ZBiqC|9LXruipW09m+Y0iKu7r1W=IQmUy^?It{TDKuKqlQDEjO$`Im~Xs+ zWD0wp%-;ihe~`91#dy|18D^Fy_wAifs0*SsquBfw96>uL!)I5h0}@RcI58;^ts2hT zADffu@0uM72w;|EFAOqR1AL{K)TIre1z!9T#Ao#AOjrz6IawMC>g?s7K~g4N^8}w) zyz2V^^KeiQLjc83h6ySF@rc)&2uh@$p_zF8?FIk);Y$jVC3r%X z3hg^Pj+kzkAoL5vc9ecRCPJN|XDf4~|~EUN~Um{}o+ za&j?-Ekm%X&mH=>h>*n?L;{)wr4I>rr-MKoA=b`O1gerztE@|Op1?%S_?^5`y`%Ee6^AJW|yk;V0gP)jsVB$CB7R5-M! zEm&45Oo%NsGQ}FKGKVi3^}j6qzQQN}07qc_#q%P_us-MhG3&0J=nO79gNYseYPcJH zNsvooVyG!Y8^s-V0^*hQrY4X};xj&)G?cnBf)*xwwY|bXe4+>yLP78 zOh1T)3o5cSWX%&67#rXcqPQc}tmA1us?SQo?j2bY&SH#HFC}E;SO-;Q(*v%+a__x- z1NrarI>M4>oTQ9R+r)CStcq)ma2ysaR}RzEj-7S3u*#WL+6*n?pi}S!MAR#4R0Ix>uw+ zO9c^Gbp(Xnr-q*?DITJgXfiR{hd>Dc4XddBp4UFhj#Wa6ePvXsVnOt)IH9)x05CcH zqpHcgZ6lCw8)hI7gKUUUfw8yg+E6!(I|$r3We2LS7dB5LijvkBrt#NX&JGJADdH;q4;<`vVdl({W9B}GxDjynGU`D-MCdbAIfd8=5ARa>2LUc3?g z%hz}r7#{!#xb!bg$31}4Uh8gJ2zQ$)DdIQJC}1Y0)POTKRkSsfz+;r z=^lv6Uc?D{Bc@}?jU_%Kpwr19%CvCFAi~is#gExZ#gX2+i+HeB z^3zeNE45Zc^W6ah^3Vro$u5td*R9d(Z!CPHixpEUoiF8ey!LY1Ly>EqTXgH+)b`>z z3zf~0_qH$z_oyd8@3}8g^M8Qo_umhbXjtsyS#D2ikOJ)7mtiFQP{trgILE zGX^7W3n>5&FF)Gio-)M0nW&#>RgRxgse4uYtBKVGcciM|0d;>-@{beH*}J_}fa=;8 zFWipQ*%}anBD=zqm!i|E|{=Hv*%T03>T*!UPDXk%?q9&=#sIL-=638 z_Zu70@D6V@V75Z05ve<`AJRytfmgBQ$sy8wYt#plgP?T9d{?%o!Qj-cseETeH23N% zDVPK406_j&tmF&#?0Pi6Rqs(0(~_G+bWF79pacZ5atH^Ie@>b@E6a>dKdUf3G1FN* zW5b;{){T7DOBr0-mMnFAhD#A6!#u(~envi>YGz1~Ni4G0tQakZ4I}CCC_{(pzOTEO zz;x{Rxq6o;N}o_==~la)j~CU6(%A3l#~~~)Vtht5DbLiAD{-Td%Ht71^*IWcs&h4S zl+o;C+tiL&tk<42h00j0S?f<<)Av`k9NY|Y?~iARj^+cwzbQYb-{@$1BdR(+46WRj zW6f{4%3YRZxkCk7$3*o6b#S$7kM^+TFXmymOykg+Ds@?aV5HmlWPSzW%j1)3b%@(E zdPk7iNR%1OMALb#DJn)9z`9U6PyW9wa%m-kWLV>pO~gj>GOH?t0i2DbH>k1|Et~6m zItwd+Onle+i_HFkg~gfD#OJH}ZnX<{Z^ezCr%&TDHnM9RH|RqY(q(A~>^n~~Od(}~ zoj!SqnCh&*P2xYG^56gK#8CM#D zy(%!n)K%J5$NvCJtBW96!fmSkwAkVw!? zS{tIqm6c^?Fo@bfL1sqr=f6-it@U1{AyFaKxMYuTKnBV*?8FvakhBGg1Fux@S|3kn zRz*~XJsF8ZMIuT=F*e3Ul%X4_C!RuzqN0>&C7Yc|hWcLX>wO>9-C59mNlv}lF&$OV zeP7gF57wB8Z9!EB^p2wGOs*F_jdxpQS$a7t(mh{VH)9cTWL1THjl> zqj?N#8vSMcN=L$2(F~?Y)6F^4)0dMyNg`?eL|F{hBYq*fdFl90U&y|q-s4*j-B`6FF5bS-^R$yR8Sab9JAQA59EfNNhNbbB4>{y_lvyztFT zrdcD2r9-?46=f=nR44`2ab#m4k=XRyx<3rl_$U2Ad?&&+x`V2Q7n4__(`sdCmLj1y zNRl`qKd4Wvdf%xR*9X?oc4F>Z>qqKu)KaQJD1Z5yLNEmAk;H9=yO0S| z`jYz92b^DAUtLDDVdk*!^`-SOJcmr6B9Z1|ENC6nf;8aq;ztv)QqX_|R#;T}dj*$> zAZU#?yA$vM*KME1ykxOjD6!Xx^a1-Bl?TsvCmTX_?Si+njQ(ZF>9E`MN^&3uTJgjyI8`K+XKb zQfWyfEULWVn&#~F$@rXlEfxr`S-RX%%KW?xkS23uWqY9Ob3FX;vxKn@j(y_?ma>K*mB(DPD* zA@$w$w31qdlt~xVmznnf5GqJnq@SvnktT7=)C@@*WjY7Ol;b0fuG&xef#q?nZ-M6; zjSk?22VIBBBSXP2JS20G!WihSkGxw2q;bU}UqY0ONGNqEP$-&Wzs;<-GM1)4YB2>J;8BgQo!^sfii>NE#UG&{UEOj+S=L0SI* zA}WhO0Q5H8**AS{9yk3@ez>zJrjPoA{cP4~o#I$u&t9*TIne?}dFHm{1M$vB2bXiO zzB`Kl07WmZAF2NUG5)W-!s|~vKC-^4yw~!l=~w9k>I3SFto*avj5(f{#<9fezNK*AN`F^l z0f+3W-^AhP$h@P9W8$>K+^gZ;H`96;HO)8SqGKM%fl5YB<)=?I!du1&-L}$*1Rrj1 z#=L$BG&-XXg7`F1mW>RN=vFD=f!a2nNT!I#POiM;~mX&cf?o*c`73{3Lk(B=c;_4GmjvX!jp4lOdX&^bAhg*G6;jk8|*ZYWtv4zES z-;&*JUpH|ov$cBpJm*V7_I)^P+o&8C^S|}2^!sz^ugxs?m7vLy=?rzeepAaHqG@Kc zTdRDq&CyH!71U8%lk}&aTuhN;azd`7ho~|6==|rYF#K>!i|#0e}JEkp&A}Vn0#+ zFW|Z#7miH~+K<5MG&)UOdMG5){tX*d5=zD*nqeqbB(-^j?q=O=PhZh1%g_EJpY*!x zZknN<>VH1}0QozRXe-Z_>0dH>AIwZP41QZ+Wu63^Y7|QBTkW?LFIpw*`AQW!)2{UN+=(xJpQxf&NlUN zG||ms{{T)Np|2ev^FS?FFjKMo`sBgaF~kgitYbV9S&EJ5=!38cAP(Qg&d-Y%rEzf6 zuacTE6f-U<7Dr12oi&Q1S_9lUX^-S+b~^{hF{VB};cpa08E8Jjp<)MJj&`v$0X|1GubaOyt=#P zb_)({y?d>V#q>UNB^}DOc=fDR{^A$WN&f)XJN-tMNDZH?nt3vjuu1ZNOutIjqIFqh zS6Eh`l9>5mQ5V}Gjm@}-Vq&=}fUDH^QuKUpl(!>EW=64k%Mlzr`?Rs1$75l)+kXU} z=SM>)=nB5HW=U^E?3*zdIPE<)Vm1$d`vI=UP4nVfeG;Mx3=nFkcJpL?W{W|sn{=B? zDow3|dBj19DH}*qFi1e6hgb3Vu8YGOZ5ETl{47DHnrJQK)p?H5IgOmZ;x`iD1L`hv zeN}}}hq_=}QCo@Wgtd4~c0YIu8kGrixJ{XTf|FIpZb9g6Q`9U<~xer%U19E%g4g#yo+e z)oFZ7NvB59>b22BBr-%xtH=19l111f=KAa+KlRlA08r@{k@F|%=EOvPqDk~+^!mvn z1!gGGo|lMx=#~r|9cThU8KnOJU2m^R=MxMo<$S6)eB7k$iM4zE!E0IVO^PrAtRXZ=2J8zXGf{T}rJuP|NiPE>sHg?&S% zU94!q8MZ-PcmJ|SY^?LH$3nV}V*Sb{=?L1Y8)8C@{%q@9@hCP;Eo|U+-C*)r$hzJ`xD#R21 zKm>O2*chT#E+I%&-|mk3+a93-G$@-H z&N=D77K=lt@hw)4B-bn&S$wG3ykEs-b^%cBCAGV0OI8q^ch5;RKhz`63ha-U{{TwA zBP=*b6WN&?9RQp2#$ZU2BMu&X?zmNxF zPl|8PjAKRRN0=Z%A0_FV?HG098Nw(<&cS;v@Q|^28u`l}9`9%}@ zSs(PrvrVNOT27w-08u|OmU$Oj4Fp&Gik3onje9IZHva(eR2L2P{{Ysr>E+<`ll?gS z*2crkS(&llUOhv0)5%qg-l1&2mS$q$q3!CTXlsBZ74seS2bjs>ddhg|UA;yN7)I2;EY)d6Qw1&u8I8WVX&P}osqfbTW2-b#sr6J3AtSE3#V*%G&Rz87TEo+Ovm#iK z5D|AE_a0hs2AGxXG!KsP{{YgN?p*66y<%9JX}W7F*Cn$2;&{KV*Hw~vG$0+5BdAXfQT;>fnuf*kj ztmSpd;LoIJckWMigmXEPvd)grC}oJDg!3+x{{T#VHRC=#u4wcz4-lOo^Jot&tX^l9s#(G= z4T8(R?s^Z7eL>*f37|=QLTI#6%;?aTGXDTL#x4A{{$n{H-o$O&Mi38AT1(}>N7wTU z%vya5{{R|vw??ekY=(0q)xBqwpBsR|;c%3i-b*Kxv09cw!HTaKqgdgmJdZ1@D(*5@ zfAL@FHRTu8%?dq5ck6Evny=9}B(IZ)${v@Y)KqcVYqTm`dih-EQs$wys&VgH+%cRs zG0MsrL`tmQFOM$%gZ!%LPN2zk3B&a!V$LdCJu#W<>p5dz7keYsc&eE>x^`ZlgilKo z6>1aL{cpI9nn}P}RKAa39!1u`c@1kgm=v22(!EJ7yr)u7t1Q=6-b!3h!&l48K1FWJ z49Y6iL^UjmW-9Kl5k8+EZTeT~3AAad@f2M$~9>!TT`juVf2BlqWDGU?Kic+kg(IEBKjejLRhCY;h zrRu(->8Ov@_fd2&SuP7ZbE`5PRnQoUR&8f1^xX8T8qi>A*vHzs**L7n z7vIV&BuW?z9(sdVLjm#W*oF zY%~(I(sqtO)IB$l4T}a|Y>QSgEpm^qb>iV!|ev6YMDj<%Z znz=k|hl~nEmh%@ee#(8cdSoP6skwK>bQgaA01F;wMrHcd`rCzLtM>K2rZd%;6B4{o z)aZ_ktr$q-_ev#>1F6qt9^LK6x!vl@Id7z%tLZ11YTd(mmiDYt1TBPzE7q@Wn23Tl zUN(02p5T-CC&!v-!bRdAT#}HZ4IZcg8otw&qDQKj_s9peb?kcBrf;o(gmYZ_f&T#1 z`e_sl!c8W9HesGL~G75>J)O|E{~6C zwZ)@kWDJVd1!R{Zutkqo#($>BBd@hJx**cQCg%QL`0nYwC`cx~84X{W{%@qXuXPn} zw$wR{h^t=(RER{gOr}RMfH=rP09BZC>~*oN6XR|2mYz>9tlXwVSL@)WmP?MloT}c7 z?5lR$4oUzYI{4V^kL5qp*PT9g_2tC!r^$acJjIW;F>7OJz zyBmYK1uPCh4Xap3#bd0qx=8>X`5iyMJR*3*H(XEXx;yAKE2KeKyM@RfZ*7$dc=@xGt{6>(#5@SB94-t$B z5!KXN$`$=X)w;p$U3oJ4M|s9$IuRpDW~YbZB#1`M?YUn{go%+<4eo!{mrEk{<>Isd z08to%b+?hwtfth~S1u$3jxnuljRh(5u0SyCI~|qny&qB@QGf8%eOmcpk;_dlnqEa^ zqMjO%S9r4>X-OsfWs%H+FZdo-MQL0pibKSYc_5$-Lw#X?@YQ{Pd9~HPUgo+ZBjjdh z8`9LWhba{PV&<`#2`<^QN?Og0OWg@txY9u??rX3C%iiN-#g32Z&3ef+URKn}+|Pq` zYA8`7*b+0}XiUBQwsraG)vf|Yruy?Rj>|*#39ovHFaHKCHy_w@={hK3gOA0?mwGC@wvaZ%9tyq!C z8?n}&{U*sB498MWF$(!BwBv$4JjpP_Vb@A@b_IjnACBbq(6j1vy&Rv_9ycYJwQ^eV zOH?&_*xNT|k)IPBaMpsoYIm8WX`VR=XrqkB8}3kequdy8r@RMFW+`Q%zmaG{lkKa$s_e}rxgmCwhbdW)sTn*wfZN$$ zXXmi+(mW$u6ABcsG7ClDkQbkcCD;EyI zm6RSx76}88NWQC&seh*i^B2n*rm1eV374;(3^$;%wc@E-hD9tz9a!e4AhORbe^RZ8 zzSW44ojpk6E33X&d3#@@`k$owIr@rRmrmq5lM9W>;!QkWKNlQ#a#ZP0NYklSOH!@x zSix!5SzR&G+?G(0B$i?AgU$S$N6M;L`trQiX6tO-ytTbeVkoRdC75D}OD2GGVtG#u z2GaJ}1Rke6y6MZlWqoRSH_=I$#Nf5&Mi(nSM>4amF<%drsc!se@IhcD?0{6qjhh*1r>)e|yDYY-`fDxf7@N`}n5<0OEoRWy z6#xQD1EJzSMah|hpHS15fVB1crzKud4a&(RKDdV<%H({Yo_Tknvit_NJM}$3`i1#| zuVz?2o^o)>acVV$Z#p`PDW;k#kyl%H-mgp{xg;3qt5A&JCA}()%ovXYNBV*Jp^6V~ zpVNf$+B2lNEzhv9)w&^(1|0@LBtzLWbZ71nb29iNF+>CNaZu)<2)7nda zq*^Jr85cN|3IXP=$N)j_ z60Q}6dXZm_7^StlgG z8Xh(Cp?uc!1F7hBvt~TJ@>X1*M|56)KaZ0fe9XtokiCnB3F4)ljCGi=C1*yL*SB7` ztdJuW(is)H@9N+6Hp*eL*75yy^o!-rRwS40EJM?NX8DDNX;wc{3t??!PIgHyOvxLY zVg_gv?O+Y5ILLi3hH3TFyn0b6WK}N7EJ|3gT7TwhQZfYvG7x0v$JRG+SjlSfwPw@HS_?TiWNDl2 zp!CZupu)V#;8=0jxqf3P+jx3Ddb!#d>vZhXilyiKqxQFP^=-vcW*_*7G7$jrd`g_+ z+2!A*s^99D^z|%@V>$Gr*R}6`zu3=r73Wa7WWtd0G0OQKlY#7Tv>J8$h6)jxNGD7k zdS~jx$o~K~I&#)Gr}|sXZjjHr+sJfv?y0}h^K^|Gxa$+idl!(gM>;aoWF*GI@?$55 z7Y$jmHQ=c1vsi%}pp)rcJSH=!0wmbGfI3;C1%S#tQ@(D^(IAsxSREjqFRxVF46(G3 zsACb)Ye@#ho$U}%FM?Z}HIBV7^u3yyY!6Rlay?zrxcRabJuHM(E7*8(*P&^W)fkezoR zdOM}Et4`E-o}9&EW4}(%-(&2*9$JT|{y0Z?Hv;1JcYW*n$GmG{p zh}}8CA}sR=#DI1PKnH(<6TkNOt+OqWnw6^aiK|Z$nU+Xflq{xHeMK4gjdW!#ph1mw zq2I;H)tIaYP04cBO8my1%X7^^;X^rD62vSSzbN#4Wb=Cu>`=6co`mg+S>^KN)_AgAM{5e%-k`^?whBpsd8Jy*S~BQjlEJ-d>X~K8DQKf2=SAU~pA?)l zacZG;iZd6T3jinp$9C=8WIWjxD5)K(m(sm(&W?I@xc|4q%Hup%JJsPVcBEJ^^ z1z^&2=hL=3q$0@mzg1iFKg>8RDLDTCE_&OjsPyD<3x2N|KG(~;t#r0J#bt_G-9;#d z!^LRUk{BeK0XeRV%Jud$2~*Bo>-DY7C6>QTt}6|Sr&{RsX*AJS#p5yUB7}xjbdbmi zlikRwuz#xTtz=kYK_A;ju!SdL9^T={_Z@a8zP+aROZ23sq|{9MM&5TF zEW;``;Q4}Wt616yAYN?OO25@Jp*04H;&cIGI%bkZ6;=3|9Vvxmq*M>(bI(;qBR5I1 z?0mQKm!Y~YlvZm#KP}bimGfh)R#u9*yCi1yd?r4m5=r+BSVFc1m_b1NL(b zORuRWJFT&GI*KD((X~>}I)zHJLm`zTuJv)1DhX>z>N}d&mEeq`tHn-19CH!1)Hr-> zZxwH|MvMjv7QH~@OW%EnJNWq68yh1-?{%#gP8F+3Jn^D)kPxUz9GN$>-{Zd>5!`%u zx;js%v<`9yq>EDtq>ah$1jKwvu6#cl-^%!{ZuP~>4-&!_7$ZknVG~=eB8jVlaA5Cavc#>nN5rMUI znt53dAN|6rmwfuJ^X=7H))p+qrgvv2)(aM5LBjx|v+1Sd->r?4D~*8eCJ7owM5C8A z2axW=u>-NwcKiX{_X&5bvCz1BwxTEyETv`VA04S9hjJTgpp)2Xm%kycdpC3KB+6%* zVVW2n;k6$&P$MCpF|DgOB!>Jh*JFC|kkvE#adDN&)2Nl3k(3ZM>4Vs4w!VHeMw`bs zKk+CrnRK2XwNMR>sGHK(Y>knITln3(v96YFPP2Jor)N?CQ0^2dz}ys&)NjAXYCTyQ z9=(r>N+?S@38V{ZIRrkMtE-Z-08cmIB8&e3%E*ilW3>*g>RilONuZ8wW!Ta}k!3Mc zM`2_WLmYwX&mhyH3m%h2`;D5mTj5FY4oH#-1h-G5APhkmn=dnBd4;(7q z>8sWi1hH6>NRbv3WXc1Lw*5V6N40@E_$7b4#S49D<65gRMl|YwF^Uo>9{bA{;__O% z&>dq*t&?*wP!uUFOGzOHhSC%esyI`8as_m;m9=urezlCwMh3MTN^(^uSj5C1SS_mX z4r`-76DuAAVS6(T28$h!%fSqmuDo(^mKzh%d0zZw<9MQ$6p-<0IWo-3NIsfL@uRCB z`bf4M)T%ibp#-9>Ndq*sPny^pMksHf-oPt)U1sNN&n>=xjnukj(NfR}d05S5w zBojngV;X_(ESl!=(ku{v^s8mWlR=wogeaKX5qeeUtun_kj@%#p$isBpoypLiNWH!Z z{{Tmd^{FSOK6pWD@QYE;9B(fbsk6Vggq|m4d$^w89y#Ox0H@}9;!1UGUA*$*s--CB z05Vdo_R+nL9e`SiBi7j0dH#G}@ZzzQ>qL-A@Ja*;&7?&HDI?$jzMyXV*$NJ|;=5Tp z{w6}f*L!)383cvh`9|Z&APzem-&53S)G;dH#@sU!w8E?qM{kP+=FWPd#tGpv#-5dh z(Bf4%xc8|ieTf?yBeu(LUAq!JJ7~)luhdl_dsOL%6>p!;hQA}XZsoV))4fX*T}#6Z zyk%V^YMO9c{$t0YJM1d_j>PZdelUIANDL|xG7MlU@#Nduoz4cwsrb?Sa_^vYsnkmT zkQZ^FLvyznvPN%!Xc62R2D!B1A2SIo1Np(BLa{@G$4Cu`lF*0~Gi#aRVG>cJ&rTAc6+e4qMS(k+2(G^gI}z{kYY{RZ)<*A(aYz z{ytB@`S|WT0sse`cCri!YQYuR6d!r_XpjLwSf9uQ0DnJ?DIk#@8Kp?$aYD1|1a8_* zS+kq2{Enc}>GxSI)B!51OJc7#V~mmC=d5w`_Cipyxr!AVCN4!00QpdUbjz>?zmxN= z-@a4yHcKOe#%HPYwpTrl>Ax|vQ1w*ZKQ(l_i^uh@7ossSO=4S)w4tF8#)<98a7_}% zpYobR8znAhREvz$Ol9swA}M83!(^|eAY$i0>(fHdBzB6}wq1mMSasU(#ysz(eKG+EXyb=e$ttl&Ei6uPK!hwnqtyJrIVFxIR9`~}l20h3FXd?6 zhQdYU6>H#+aNTj$-ctEdN;85$dB? zu^f#d-zK!Ie;To|pGrMRk+8So`eyQ$)Hfn%)mzVwoVb8FS-~=;Xqk(8qBoC`+)_vi zki3VdOZ6t6IUtQAo-Ho$>84$7i(xYtmD(-83h+eO0+_|Qzp0O16aN6C63zogGBa(+&IWc^HG^IbVxrse7z`GZ>*i^#!lgb9fAC#oS48Dl?fZ85_6 zgBfN}A^Ul)Y;q_(c5T-sXbV#J8zhjz?EH7DcgMR9-INip&`C5m)^Ivd3g0 zJO|VTVe$DUM=biiMwVME0AOWBV{Hf)2N)}UzyLb;F99b};B0WlA31DBzz|B%$+g>G z`>*`^_wwqD)_kz)s8XzxqeSo%A!T1dD8r;FKCBPbS&!yEBjlb0^reGop~!U1{+|HndvL4Q<#YknE=x2*0-ik58#Nm1Ak9WmZivXXV6e zkkH@AI{yIMwzs2)nmkq&AJrnQ!!QJP{U_59KgY<}17q>O01crjibC3Qkh7>GO~FVC zJ8R${os;+@UL?UWk%?KgwJ2lxA$7}<8`18gU4S8h_yc_>k|qv?+%UGVcK{53KO^3{ zIUS3 zlk@NUg;igVk+658{A=;ydaWwL2qd#O_aQnz+DopRd*1u&;A?sWe0b<|=<;avl8Iyy zv}pTyAnj3C$vDZsiXBw_M;kAVYoJ6z$*Ia zgzXB##$_KLq!X9iIM=0EPdWbpm%j@Q)iDNMA)iD7v_aFrR?FBkcU(NVrg~8K5a}4SSr|UXh@~-}?3X0A7rSLy`KU`YGw$Usm*_ zNeA^D=b64hnh9sEx@xUZcbv-LR+YTo77pfFFn8bMIoqX}GV6?4U2auZb0pwcfX>Y% ztS1fkdQ&n=lE$dV_j(LQ_;}h+rq8MVwEAG`FDd-{=;ocTbd`>b$Y=3Txg$T)gk!69 zE(KA)PR*RA7E3T=VzK_+GQ%HgZ_}=PIe)3w(}zlVRp#~!&R-E_;#c#9U{o3L2nI_*dW>o zjkhorU1s7V_ujjx6bx7sxR6OF85KjGl6u3aZb6sI!5wP)uXV(7MJJ~uj7d=; zB=-ap$PeydM__agJmmhgKDsdMzZNBZI}MG5Jch>pG&Xcb&t;!7@>9|49M1-5z`oO} zs+Z(vim@bsPL!hPlh}M~M1Z;f026M+ZN*556_2xvG>oS}{s<~g*I?^oW3lmP1OEUj zCNu7j$%>b9rCf3HrHQ_C@0@jA;^`DVE8+;ixBjkk<|#FqnCFvyjSxOM*e;05*ORI6 zz?Me-wLlJUI|gsLi)+R7H~gQF2X4c`zcA2O&sMhca_5Ru9e+)v+nL;tlh`N?w)_LH zf=7y1p*pG->Kr6y6jvFnWMx4kOFl}na{mC`wc9~<2DQh<)#kmVgExuv^vy0d`-jL%44httbBgr*s50go0OcXo-g9U9u=Xptp?QZrxsKiZ9T9IPs}2 zo-3dN_KR6m(Xz&f1K9OewoV0CA}!3)ZJVDi9h*`5e+o~|^fX3}_B=~D8b%n%iA0LY zwmKj_#?HvtZ4=x0AP>k3Z-0PbwWCme-DFOl;j>I|z+%)Fc@~s< zRYIt&G^Foe0385Z;Qs(W8WH5Ykv&Z0FeZ=m{Bwb#eSvR}&VV40H{ABo@w)vbKCqb8 zk%;u`FBIp;pSbBs17v8DM)r7({D6G-#RA3S6Rd2+JW;zbax%impg_e8@_oAWAQirh z@G_(jd{18m17ug0q^QX6{&#&n*vopMRw&1Z(NL zlPp|SkoG1(0q3F)zixpb?|+SW86$dol>)rd1Ho8_*CDGj({cHWGrS~h5m zs~l|Jn#z5B?3qx7DmF)O31C1PAbxjOBRP$f09C`1!S^sIMc|7!fzC1ZHCjU-;~;Tp z1dE^XREWO^J8sDCd9JP>qWe-ooAVAPjfkBwQt3Y$vycRxemm>_`~2u0!lcMaC{$lf zqeK8H-othZeg^(e=ePZdBd(vLmj3|s%glQ7Bw(C;8-7IW{{UIF>5Xg z!u>VUF^xkafyjK7_ygl$cO?G+ALG90HB1@M(Z41>eJ6@IBj1|p=f{TM8}U{J_O`W{ z68v0HW~=;(v)|u0^($V7A4xd!*a}yX?V?H0-}vrFe% z?e;$Bx$DfYn-rk2)iTXuv@^)mYOA}#jT^Y0!79Q1x?#PLIRKyn7kZ#t3?lGpaG2Qy zORr2p62w1F1@$)`n8-dm`$%RdWDVUOcG{A!Rr-+cB1SmNbvrh=tWBKbI>``GE=;_wq#jGRSY2&Iu0A{0u>La<@`bQtOX03H7T zl1FcU>6Z+6zPzbclwv5S>1@=Rh7R?Hsb{Y4HhGRx3^7^~{{T#o`9Cpn(aa`UA?Z$~mN^hd=tRlXSVR(7=1Uj= zau~#YQsqMXd5;PGQn4?D>X-)q0J)~yLh*yaI3D$U`|(lW5`HIM71@+Qq|`lwxmt{C zgF~F3YP@ydELHOY-MHSZQt(GzXGE~aDAnAScDD>a>`bWuk>l3p;-`ozB;Rfy>Hh%M z_WGO4p0Vj{g=wkW=#H@oUMo?Bu$YYQI;KVdwZR;fZmw3Sf9)}=Z1(Zh8e^%$n6!;& z9dsNuc^Tr9BNUBkN-&F@{noipTbWHLbxz0I<7vKy^Er$Dbora*e@MkVeMRPHmNr+W zY9w;WT5SISNQ-Y9ef+iUs7jdZ{zClWE6X6OQpAc6rhHHMUE;=>5_x99-25A`YZgyj*YO|0Pm1_=hQ|7HG-=|x5iFs?EP6-Pta`RDDOeN;jS%dL z9ELVUb=_}C{XTh_*4BQJJk7y%{(l?gg#A>|8yq? z0yBMQ)H&>SZ=mnv^L-hTua&CUd|Yv0dWQ#t%fVJm49Ep9MoT4?dEmm$Cs)s!jnmrd?h}ip1gIZu~b1edN^%CJG6=FG%P(w z!+b|kqAKu&2T&Pxk;tMnkq!Fg5r<;wxxBIv5NKKLL*gC_rPsfRMdCg!5M42kQQ@b} zePqzfrH^Kq=_k-dsM9f-Rw(t!H1RBo17(mA(O1>?n0Vf#`YCRe!q0yvj`G{i4w2|f zxhojUcvCJ<3pLvl#X;@ltmN!fN0^zXH7PqdM2az0=HF&NP?WlwmqGa()m~fSVUw#e z`CfwQPOr~NMRU{RIy__Kvw7&IK#W!z5b0t$rmhQmj~lk;C_HI*`k;9|iSlpAtmjQ( zVvN$xdFj)6>w>&uuiRua)#kVBDos4fLZpn6!|F_HGa*?7RtP(<)P8v3dLOBLpyP$8hrL#U+RLN#6X0KzY){f|^%4yqJoBqp0t<`ZfI9a6D#V(7CRZC}%`BfWW)jXt=(w(263 z3-vG7LF7n6uf=3&d>Ci;Tvdv$U&9tNdy zNwE00$XJ1(vno7w@+*G1pN8!Wcix8r&$;3|iItYp98t~Yo=zmJ+vQR;$>Z8| z{{Yj|S^oh406*h<@#Y$6WnFjH@&{xsq}1gA1ls@X6}Ddw1f`Fxc0ub003+A;bu5& z9UI-qTe&4{btuwids#aYEnIz6Ff5a+*}F6lA&Mzqo2cNyi4v@2EAE_VR#qWFs5X~)-Db1O!WoL`mr?4Ovm z>PgFrI_0zdFNMOGm^;qdF$_!Uyl$Rl;C>u+ej}rS)PFxwr)O5>)DUbFg5CI{M{d5d z`rF5}o(1%`jCiK`BN{y{^2X4|=14URqfZG7g5!IkBNzmluD#m*BzX_gzeyiVzD)Ta zT1*`m=#GuU<9d@T2&<2+)O~$+xAjiA>M+d(BVxxp7tOaZ} z#TW3n&Zg@=qVosL9<9m4jk5C6gD;fn%YI$dwP_%V#fmtZQCWXR3QZ@Qd9itJf$QuB zPs$px`FqvaxF_xN3)U4LJv&Qhd2&{YI zlj)5z=&2!TCy66b87Za`Y?M-@VLaHuQa}wTYF>7lqxt>fkEqkbt=CNd0EnI)KjUYO zgDc3=r=G`kIrRqJxlzZejU09TpUF|8Sw~^qkO3e2>%WhJNZYcy6Z{5K{{Z4XJi~vk zE>Z9Kr}Wi_%yp+&VsM=u<(_}4*9p_zch$Wmh@UsrS?Dm*^(JQ*(>bg)T;@)lE|hv5 zJ$oXyZQyI(>L_sLoLTI^x6yWE>W8bmq3NEh&3S+I3H47_#abB*#In`;nEHb;Qms~` z*I`^v8Xq%GFh>%TBo(EjWKT3vR`gkA(6C(;4IDqt)Opgg0>6bp0ubc@^UkEPCau4a zHsk`;eRFbnr-_ps+HVih&7)|bk={=bk{wZLVp(KJbmv6zNMi`!& zumfcO004N09mu9H=q!>lj>poHG=AiJC6Q7&0nj@}VWJMokbG;O(Px_(Z$5sG{*=7% z&)HjN4j{E+iUJ8d9}s#(o-@0Oi2)j3(xv<%SKNpIzBNRULvI8}sc?NQ@pj>m8} z{DGnW0IvT4Klbo}0U4Erm14Lwwi>vgXxF&?@-D%7Qa4lO2SsL9P|i1iKm<0>%XDzS zo;q3TI}?l^O{`&J$kO`@ha*aBCO5H<6{R+yfg!7N?rhBvXyK~DDCcM3)*{#^`N;X7 z(tl1l-#9$s%K2f?dCW!*ezncEC#U+}vexPzl1nz`xh6W!It$mU!|An@Ol*x}#D@jhkNJ^VdQ2*1dGCEK};`*mc@aBGed?Hjy5d zNW#XWalN~k`jC~OU3It7-5rX5VDG$|^Zu+C?xX4aUptAOAu8pf`CGjcN@C>dh~BMP9!q34=YhB%HcRJ z2?uD6Swey+`mebIj*WEROXqsa8P!ts{YT8?`gZ{~aNuBx?B_F%u6-PS5|mKQEzE?H zOB_oAdVFgeGdznNPOo(NXV89rV7gwV9G}qln0;TH%im?So~_p7rYv;EA~u>vj@4t* zIb2&cbx7(-7Bcv_l3YlnUM)EqKlNSa$DQ9zmHf2wm&wk#$oX^EU1v)p<}aK5Z_}8b zpPwlQOuk}HobunIar5;KCotGr*KT9_|sT2Mi5OO$X;4aks59J_brmtJ-M08;rW ziRxc9eEaJO)JcVtBQH=*kG|$>rp<@4>mCYQ@~wYYhdS<&k3gtU%^tnW>5r$p4@VA+ z__SKNwerIp)->y=iA=#=V2P7Zq1rJ-?Y79Z9e6+0KUsLp`pFN6$KmHdWYngXNcFme z)=2|6MO{=2qmno_GPv^0tOx;`iN*KV8Goq?bn3|m(1)2gtW`S7v*2&O6RT|7%+(BR zs5FyTsBZ42)}9N3^bF59r3H(&OqX$;G>(^2g4c zy&PxLzeD-|0MmG1IXZLdE3E4IZi#(Xjn7w-)vNVvo0(ju0iTU1 zF4ls@jEzeX&qzZzYcGZP8$6F1`HxD`D{1G_Oolb5StoX&6dP0|-E9q<>(8V5%f~}6 zh6tt8L8_TU%cIt=uST9zs`-=YWzmx(ODv%^3lm8u(|Z)99~5$QMHGs22Sizzs=11^ zb@6rOoq!-DGfQ{${JvCw(KHevm3oz9$UR^4RvWToq z^GZ~+Ebu6+#wJ4Eqs9&WCr!ZG*!yoL4N_sI}^w5xfi-RJIw%5~4DTrDkqJi4A$hj#~Q( zg*ODTb23w8lX8S*9{T?9qmeDYZ!RG1g7_(qt#b5;weZ(WoMDMlD^iI@#`zfJj#c0| zosfXT!vKMVe#_V!cmLmjsh#C3TdklTVaYA&* zL~55&eHZ65*KA(NWN`4sG`_Seiu<{w{dM3PA!f8NRDLTjXJep9Dna)4sWN2UmY~Ml zio`#s{^mYP&Nc!giqMZ&Lu;~j6|@M}q05l_H){9sHoZ|125AqX$oz(w5!t~2fSUmC zkRH$rntdmSubDQVMKlIQ2`$4UCYNX)lNykDw%Tv7Iinw_b&W3Y8TJKO&ZB&#N`MP( z^9ZBaZilyBN&f)+zxq)}+ewGbT%Sf+?n05x9L*}2LbTM9Xwq`idWr&v_PN<1fjJk` zu20L1RSI1{hRIj2jBz|s92R=z)tXu3v?fci(g?f~S8x|ZI9+dv@!G~GC5&hP0C`T! zK%M{7;?VC3U&nX6TN&>KI_it(Jz(%$zF)N(wJnl4&85^zqahRdy`s zJYEoa8`q1At$zOiLiI*FBLt$Gee4|x(Q_nF5Qb-^U;6E+(zB6aT6c;?ScongvvxO_ z^E3LLbQSI9v6a9JC3v!LUcBlU0;V_tP{&~CXz|%Q*1T7@I*Oz1MO!k+&nqO-TC*|Y z%%hZqe5fZ}za_h$pBmNbbOXqSe-iNTEhu>{x!FMg*magSvx7#!BLk||@dRmJT{26j znX7Y6Gqf#L#-GYvzx=$zxO`FTTyTF*l%=SPR2ioS_LJBej6JY*i=%0eshAPpVsm*aYskfq4iiV7kpK+7XXXVo$Q z+Ad-n;=H(yLwY(L_B?X>{cq9!YsaY7NvMrzgp9nZP6<^efFA{o9D8)sUOTVSs1fSY zB6$%)rD*LSk2XTr?gj?~71q=A_tc($%j&kNbT?C0!8TS~7VkE5qoVA08?ditTLq{WySy+CYYsfm$-EZd?T6G)~*s;|1v$xiKj!7C}Lk)|yCSFT+ za%)PqDzq?S;mpp`O7&?7=uIrK$>|1)GN{qv;st$L(X+7%q5Y?s01ch&cHeWo6aN69 zB-9qFD;l*QY^lN9mXw|C2XEBm00&y)N#A|=r+*##M@&S1AK{XjitkzFf<4}rpcR9L zADZa3d{D|-uNBnlr9-OJ%d1t|-dife9pKuPbDlx@{kr?*KTuMyM&UY>r?@LH({d}@LA)3h zE?PRCi&AAtDVMl2Hos~Yy- z@Brtay}KmPl0x91Dyvon(x}h5DV{KH0*8Y2Ix&HvZybhZ+Eag#tMAMBjrcu=isR2 zQa7s{K$7EwmM9Ca2+q4`9zO2sNE_~a4l_q&?N-5!qGgIeNL7Bt`4V@)5&ryFxSc0Cug^eICr44QnxP)k=LFgDp_AvyqaJKts6}Vbo`a(c()fTuz0rh zMq0N~*v3t3ABM&X6h6kZ7-~Oa*94P^7F?A70CPX}31Z=>=it7IZ8;8I*@`_IBvMPP zT|0TcW5lrP9zwfol#P%E6;$}mftr9>0Swa?rX+<}!iB{PRfvIj@WAyaj`&$(4qF~%4M4LVZ>@3Uun2r8T~n;+0Qt>i#jvN zj<55_rZL@d<@RF-<+Lr1>khnrr=K60rGKqDV9Vu(OQ$Kve>D$B$~wC(j_J!-44u56 z^?P+Q844n`44q=SlTRoA01kCNAE~gHG8hh}z)s7H&SCD$PVHGPK`l17PRu{64Ua<1 zw8N)F@hjK(Z`5B+cz=c;58E!Ko6IuJ_)@IltJCI6MOG27mB6E(o*pWK z5v4^_6BFjK9%DA*0|f)iU_t_*7G%FsQ&rVf(0x&zkEC$l@r|0TosL|}ef1=bYh|m^ z&0EJol8z>MB@$VsPK}!j1oo=KB>v~F^F<4>p0LMdGF527eOgNo3?7R_cJoU#FruK* z+wzbQr2KNx?hlEO^z~ZRsbcXsIBVna)xO%DRjSJ!O6kTJsv^CKq=i-(AdKyQU+qMM z`#^80g^?ec<0(-wu@X#VD&i+$8#f(s1o8{<%VXr7lgdxxA5WPcNFvn83*Z?vqKPZ% z6)PHE2crN0b7Y9i1C|iJx<^G)HTO3+z_ZD9we|u5-^oJdzLQR=2(Kd*w-WZB!|gi&0C!> zmrF3VHE!i<++!hOU4|_pjtw#Sl2Vd>t# zbsHdWdhC1)U*cL6bpHU;PWKdNcbq@~i>pvUAbTAA1C@14Zj}o+p%{Yg+ykAs?T|BfV8(AysxC-vNArH|Db<0*9`Q%4`6{v#3 zaUwz$nIvK(;#-Q4P#?){f=6T9zhFTimuwPLeZ!)z+9wUeE z0=oehyfTu@nl>ygUw&)+fLdntEdh*z;DhPmXjt~K+rLk@V@s2%$wrEbV-3Zm1~nTB z$?0s8JN9l$N60;oiOpyL#%}ZMupNunmGpJcwDlS zuIWBTW_cwsBz=}@{6i8Mmw|7AuEe+bDhGWJ24tQnVwhc;Nm@6CH%N!23`p)72Egv# z&^RBJ@A%OYL#szo515L86iAh~2F5~#ZPseW?EDOM1=efT)GU$$xD~$I>)0Ca{ax}0 z9c(5W>MN`|daym9B zm%m${S$Z+!dhh8A>8q<)#8cFcOwUHm%aV?3VoCag?c|aX69!a`k8ms?+*0*zkjYY} zT25+VY1xu70e4}o@Gdkp-0MR?s6UWM3ptASC6rdiP7Ea!MD`Xan9H;>GQN~)S++D- zC~bTldLPre?-psGk5%AP_{=Dztg;r`Zp?uQx3T(ofJF(6*#8 zpAG$A1WE)I>h4+;P2#K(q;=uXOT9%cgm1E@X9FhPWDLdpnrG9@O_TI;BZ?W2f zs=QGM*_&w}Gq4Y+@yDaCZi;j~hq-0M%E|8jt9nhsfKJ5-{Q~=yNPF6)aB8 z;z$e?N!NXi0r|`S0M&EOxm7rH4nf3`Pa~Cs5M<*VY$YH=f1hai_t77~9kp;{(}OBB z`eiK%K+)=AWAF7t?rTF={m0ldDz`Y7y(iBFEBa zQN<*%ub2IM1*)g@%U~|c?PYSV40LzBl~caN6U$wJb53(UDM1)dQZ5V4Q; z0yGI7oAJaRB=3)XeD@*O%?i^=<>yOtQq3GVgR!n%;hhNl{{SO@BYN-n@x74!7Iod# zHfecz=0RqHBe*(SEhnh1g$ZF5074F9lW(~Tuv?FaIWMQoaCU<7i79bymF4Ac0WD=yEeEgB| z;}n>-uC(81svHf;y>gX;_6Oj$^a0QS9c$!vqigA>8w6gX^kw*#O`a0h$)mG@%a0bK zBu>GI-(ke;1FeCz^z+jOHL^Nx;CNXOuiRUYgp!qwV8or9JnexcAKOUuLZX*Cuk zIyv{LBofgplGH#dWi3O1c92IIa=_Gqs@d0FIQW%rGEo9Kixy%sC2>Rh{sy+Qu~MxAW?+CJ14Y1f@6<_}2q0&7XM3NVp3r0kgeU#RTg^Gp=cxIDR8_1KxDkQSJl;DuE zSZJIO2rPseIRp|o$gut(X-|nw;Tq2fmrtqj9}n>4+VRf|ZI&`1cmz6g$ zI2>1<@#Fe$>I>z)niSc27L(gUJoX#*3m2OS-F)~7_$#jA}YFD#16yJ3(i z-&eAO0Yn-bzu%>PnG%g>gLt4tXbz`OIxg}a5*$Y&%e*V2Y1@2m3X3ba5~n&z<~?^E zUDR?&k#O~BXgCGH{-04dwFK;M(QssYXE)LF*&&civ5&^OX#$szG5H9E{M%_YC-tf$OL7KMpai_(<{>I^*Pcr+OtYr@^mgXAg^qIL)OcOz$G zUANL<;K}N{v_8-*9wU%V_V;XT ze7?l`cRJl9yIoJ=W=rzqO5DoW+!d$*26?=6&Y#1zIxnWYYs2*rlQi1R2Cf)VSe>0v z?0?AQU>n7dDM&ePwLac1tdKaKHFxx*RpS~`Ww*zQiW03*O=sazy0Br%BO zaEw+hIp9Wt{{YGxi6m=BL-^LoS@L_VkQF#t3MneF2ZA(b*X?5-nU{&%DLOs3+yUWl zA>{8{Bx=V4ET#|?ED-aKFw!d>wua7!$8Y2x;nfnb{{Xswm=(5(95V1Kf`!e0iE&m3 zTwC~VsU&wgZ9)euLNsQ!lR)}I9ML@Ab4RbfPR&?J)DVUA8DK!(q9Z_&<7#?!IAQA6wPZ(O1NxEACZ&iMRYAwG2o;C$dvE8(7mR7- zZFzJO5ZZk@7H2MPMQ{TSY}kK-GB3JKH0$(#ghLWK%APCY63J1xDheu#O8%?6v3-Y3 z)7TNBdlCJDF)oOGl1~%d_W*1L14IIM+!*m(21Hd|$daQUZh#zu_WW!X9~=+K0QT6{_4D!b;R6i7 zFQ!8n3+WzW(G_F>2+j$wo~YMHtd3}l#V89rBoP~u!2+Aw6qOBm$s&ihS9j6frmyA? zUN05f(P@}4AOdqGKN|oZe}G252D|v|acnEbROxuR2an4Z+2D7h#Qg7D*dNc1w!V?; z%^#TkXEd-(qD)PYCG|i?4VkFjxAU>4_#J@Pe~!f?c$5eA6z~qgLvnHO2G{Ta{{Sbu z4T1Qg@d(M(mRDdrv=v5y9}Swmb6Lk%9z0+Eud3b$tivYV%}N>=zr?Fpo~qrUYN|Qk7*!18I9G8$j&*8ffvZFwOqDOE%BKeBGr$P0UZNM<;tm68B1~VgLEcaC-K<`^8XTFBU zkA-yh+K8d8?$QQk0;no+M#UQD@^2WffuWGc;yxZ@+7)#$5(%=_70fK?L%lW*X5^%x~kl1Nj~`DomP*E0Z*4M4v##5J<`bSgDkDV%jH$ zyXdnHzJ|!G2VbSRH(gf_sf=_1=%U4+3%1`cc{S z0rUd#ZL*fw@7Z1Z9q(iK*N{f?j;SGHXGsi0DS?&LIQFUb`&v=yhX_u_wbJ+W3oCU{$79h#h8Fbx zROm>9M|v*6fJVt({Olg+ztVysPtB|(ZV*E^O!ZV`&l5=smC9hBRuM?&9;4!UXfqWg z6R!*XLp-gaooq0qwgDFE@vt`2SNVY;kPmxqjz&058uO~wk~_IV(+Erb#F1{I%pE<3U6qT}9DBB%ewF;!kI4T3 zs^2O6(#+%~tBJt%bP#86=8SI?JvY?2>-{I3)Oh(3QW|*d?AbSPlgO56Kui)KekxhY z@;+&=$$!$Q(Z~fhtxA?A1&l-lYZ`yLD=zjp4*J;Ehl*#aZC16NwG7eLt6S}n;)Wvf zt(g%SRjZ`huoR<7#lQ*f{&;~w;M(-i>hxNa)1u29ahV8JFFKk5WNL9h997T*+opVT z!pDkuez(IN%y8-mR&n{g4zeMo5zD)JsdX|ipNM;>F+(fqp#<;lh!NA)7ad1SoAg2XTZmSmTJ8(k{7e>T#Ari&rSA|P6k-VO=pfT zCfWZ0D*Uwbcj^nv{)+4Tu6rGW$W`j=`MaGfMuo1buZQW5jOtFQxegY-R(kmPEl!wU zMa{WA1cFJOqL{{zzos6F{{Tx*q0g@mqmQGkM_I?$eM8fKM7X}X@&l*l>k3^vmg?&r zJ9@86^-XLZY*V_}H~xc!tAeeFUrkcF*?Q?-sb-4Dx_D2BXna#c9OFdL?3Moj5YMSr zmP)O$#8qNQqBM7t8@pX3$=8VZkA}C0_^16hRRHop4ZrmctIaS=AZUC%q)`zZa>QJ^ zY9o-#n8i#PKR1+l>!UBOKlPUL$NfWaxbC0wQ_9aV{GEdr)SWBUuuapMJJ!0FBG}w! zYajMGZ2l7|ZfbDYhc#A6C=2fd_G!reyU6gjQrShL4NYXFwr9UZpXQR4?-Udi*bRSanNWqW9=w>CI8HKdyfO4|mfm3bG3Q^IeqMQ}N=zr1 zI6kRC)R>cYoy%3S8J?TPXXHzEt2DIUNOAY8$mXofg)FpM(}K4zR$ZGbG?5y(S zG2MRVqEUt%eJItkErqWfP)FV${)*x2Av&fEgOu)c&*wA6%;9mx&ptplt5MPfDb2d@Hh^=SEv z4RlsMqjHNghjm_mDhRW%t+BE@5WDfnN2gsM{{T|O9LXw4qHRLDs{*nutrG0SouuO# zHY^J3(4~?Mf7Sm0K+PVQq;dHEffgQoxSK|j7(k)5V{k%{G6mOK@g`CvS_jqF30ReV z7Yc;^vzH&cPXS$TxjWweJLdlY;nC?zomchM)O|}RR~}t?0p>OQ^cf%U+qK zaY-mce@M5VgL;!oV1T{(r<>=>*qTawSCM;i0Kcojr}asUxQLRGcB=h4w=N7OoX)k@H!C}CvpjK0sEOTSU&6;CnMi2>QutC8SeECnM4#$W{)k^wA5T5Az zuK875<+81Tj?`F+QCo&NaxzzrTUh9eU#stNe8zY>!~PS@bbfoM;IU@SY*$m|vwmGB z6FDR?Ni<^_La$w0>j!&LM9&NsI##sk12u@Di5^j8tcd&I>e>L1q!Ixe1b|7=1QFY~ z?luVV?~&>w+|G-qmB#3u(1#(wU(8X662=Gu_`HI1*T=7|(`wUE9;ZX5)JY;NQcELi zp>+!og&0E)svR>ij0Fz*c{f#?J$c&y09X(7>H4Gkuk)kJZ!o-yqlW4}n8SHCJh{x_ zX3X@~4=s((Q0olmQAd?CbuL#49n5x0hH@Hd9b48Usb?1LEkL&xanc7^f1AcMfG;4LgmL8?swrEccO8&L3uCI=V)v)m?p58_Z(SlxCRRLk|9)6d> zTI!5XT2DebI-3W9>JFL3WlWQaY2do6A=5cr{ysQXQCXwO-{|g|vow-G^P^&5SY?Vi zEF{byJ{UeDtJ@S{X_^R=U`ZizoS`xNd|>u1Em*Fp^ak;q+3YQLkT8apb807 zBcUNc76MowmhSZP{XIOE>#wH|pzot!r~d#mlJI>hCfQ&aV+t?sUVg1)=N?(>llhZOJ~%PrYj;YkGUdP zqz+5*8fT1YiP$D^hnuc5gF6hfX0hnwST8Hz-;IzuV-;tdIX%*bathV#lXy)%$!ipQq2WM-*~ zsUeNo9ne{y?>!(u;WE_YI)0>Nu7itB8fs;9^B@Iw?^7x(Mdl62T}$p&WwNE{F!$%A zd~R)Dg+Zg4w3@Ir$n)sjz~T*5am(bnj(0;7D#{8tR}2_YuAOgW78WuyF-VAT6+i?A z0YeZS_4#6|4ufbD*!kc3(Ek8RTu=Iid9l_XP(4}o7v_JJnCdv(r%YDz*1tkvvXGpo zmw7Ar+y-j{mb0BWs(4$s>g2NUHLMTSC$@ZC3IX{RD-$gz2_G z&YBFN822CT`9sug`VaCT!B zI&y|C(8XdhklDsk3tH`p)vL(tts#$uvA?4knn01SsWv@5$^vr=1%Kuj)_2oC)bCJa zeBt_kvzgENZIiJ!GZB)`^zEz$Um-pU)Y!WgYxIT7S8n24CpBN{6<04bd0TjyvDPPs zJq=Pmb$QWq0p*WXWjcP{yheJjOJwpG#+IX9nw8pBC9_g?#~oLh;b=sHjlEZ3h2K&| z7mp6{T|b%iE61s6bqN=UB9~~`KQOWQn0liT)%`Ef_3*EU>Q0fz z=DKL%I#(G&<|i$T>kPgHFUuY1EnHJd^@SrKH7_1)G&9Zb^u+%FQ2vw4Q;*AkrSCBO z!Rhp=3Q3)-*IrJ?JaNXY>TtkU^8+Pjbyz_rtyz6%-y}^d746gME9!SKm+~XZPOa-4 zjoV#InCLtm{-v7IEfkk0V-s2nq~j5myaKz4Z6#{Kk))C~3VlCr{AW7<0Hd;bELD#! zeCO!Oc+-loooY zrPEG4Kg6|>>WE*%_Vf)g#j{P?FE#EZUy771MvRJ*`LI zNj#NgwSvU?N7Q+|m~?2~87^AGzDcbV^r4CCV@0{9c&3s#I6*9fv%z=$M11q=UnghE z{Ve(WiRv#ey8EH?ogZGel3r?H<+WyyS@hObO`OJKr{lwP?MjP?`>eiOH>J}b*^g6cl9wbLnLm3cD>(^z{Mc`0M= za%6`7NYWVU5?huuj%#ZxRJkIhcb9~Cq&_vEpI@TV>vW3?d2$~U@U2&cG;WFx)zfR@ zi%?VxSDC<2*tViTCZEG}zAdBCY5YIW)_AJ48fNgnsXRZ%HcPCTA!vW}QB4V+M|Ei8 zcUf!#!133SN6X%l7FM%W+Cn8U$yiFmdiQV}DmHXj_W`*6d+{Jxlbc42;Bf_FAQQx% zB0UeC6W`!+`278>^*AhmdNE5F^*vY%$rOaC*E8Rbw31KwKN}uDSssx|1IEc<`&79e zst){wd(b=A{kwy$==_Bbjrg>VH|w=3sk?61*sM)vnTuKPnkTovxtCx=4W!Vea&c8c z$vl3XS4XMmb5Yb<)u*!x#*77c{{Toi-njBVAd|i$vFuN9b(#*K>adFwWbDHjJM^WP zy2MB4i3A4GKH^UHd!AeH4RREkSYeS_*;J~NsS+ci01N%C@&o*jkI5oPT{7?zFkVis z@&gfK-G>Fzs65Yob_4Uh_{H&W6F~Aw;yR!ih!Od!$N-=SJJy@;@q^ToX&lqi05DKw z@IWnBo8qu8uKHz;?tWO>R?Z`y{ED70quYl2f}^(d0oVj+0td;Wu*>RM$r9|Po12CX zoPZz=cV^flWaxYYy?6q&a*CKW_$f0Fe^mU1!mk0 zWP;mol5yI{Zi+Cd1ZEp{b?NbVoc@9CHhz1LfCtWxZ6Ap;Nl}#}o=#4xI7c6N_1%3_ zv)zFzHU3WgMqCt=g;4QEj~@jE#<_A=8zc_;2l(Ic8^40_;3IJylB`Zp6eVN_VMere zM*je4*#7`OgWJGA5Yw}Ii6HGZT#EGGS<7aD{MFkQdduFxA)qUe5Ce-lMFaiso}kM3 z0e{O&qI`8}qXm4l6Pq|lUlYW@fsA!`NtwzVN1NQq!+0fp%+qfdQ z>QSPs5FmcwF#Sz;Q?k4K5v`w-y&nEP%_L-ieMu!m-*=E#xJM|VS#3m=bSi=PrP?f8%Se6 zkHKU7>-)Sk*J{lQw2^uyG$j!4mvW#1@(J1bExqsZPk<`mGRZVBMeQLac-Tq5kO>E5 z=o8q1ur>G|F*ZtQ3M`51p$q|62ny`$Uq2vxAM>-~vr!Vdv$IH%mh{PB?#iCnAEo{J zEV_6Yt4L5`cH`5Esu%tJ^T6rOIN-Jw*({Gt1SBUlAhIz<1a>`v3_dmTcii$~>ew7( zni|QpZA~Cqj~xQ6n>tN*<=F3t?Y;OzgD7T-xNPtL^~xo$TgzG5wCY3x*pAvma4xVj z&Tpu)K^d{-rqxok0b|B>0uvV&Ian;Q-)ERSWZ5$`FQ(FPC)?PP8$(0^+m?#N`E06lV=_q`oI#0V0HhlI zqz?KX&<3=2Kp({D@)nsQa)BX5-n1eh5Jx?LIcSlk_-*(2*@W=B%Fn21nO=oPp-yNW z!6;)Ht2bvi(lgG|vwzq4IZSZMQ}D(;xYm@g@7QeY?EID_ z4#QR${nL#fX;Nd5hB5*GQagYSyPm)ucGlR6GX2D|FE3O`rIE|*0kzm0Bk~X9TI4|S z#VoSOkxL@_QG%|4{V;otp(B6y*L~<8mGQkiDW;Ynf+QALQ7picFl>tZcCMhil12>s zh2SWonxo$HoKfT7qLA7VM(V~G$1=>!=0;F{bfa4L5!?_pzQ7L|p~yoNvCR5#4u-n| zgg9w5PV_VY{{Zi{H{uFWRcR&?*K}jaHDi%Oz4~vVu0I8j{Xs|M_{!18A?}q?S~e2Q zjIS6%OA-|52iRRU{{ZR>^Wcv&2Ff!6$ByF{p2HtKfarjb>+3tDG!GnCeCObc{{TtD zEks1r;DQ++jc2|qpbPtL}_$BE66rpd%KKmepfh**?G3$i<&B(T{e_wD&3 z!1_4oV2VdYhTpC3Nu-RdYs7=a4)kANA0VkG@DGfZD@fr)W+(*PGB_I&4l*>0CJgk4!NIfcPOcHbLsa9KV7hH4;4qoPr{Cp1k(fy?;OAv8bIL#5xF_3qcG^Fk>t}t(v>xNahr^ki2-%%kLH?8K zCm{O4$@NL6_@ zwp8}e2Sw3Gv=R8w<>Q#Am!1gcTt%THNEIF9RDdCLJl;=6V2TJEbwJC#avM8)Mc|$< zB#JazIoewT`B5t^8mnePH(%!UdPZv%({RbINlAh!5ETI0s(^4#OIcr<0lWMKxzjar zcz^hQ@%%r}ITO0r? zKqKIizyq&>bU&C)j;|_@LVbo{trw&TkR6Xqf0Llw`8xi4c#UtUaQ6ffM`mj9R)u3o z;KfUja8xnZ-N-dEkfi#m!GR!t(tJRaWo=DWYUJ`uin|-g{;+y*w-LcqEPEu7eW~z3 zZSP(z^uNOxG)&TXua4=UMhXhXtm5&0zb|E;c^NnNj9Nwhx!kpzC7Be99+Q(@h3&>Y zx@=yB$l7RRsaYaZ89ud{t5ktDK;i0I+OzyOq=ZO7EC!Lc9!`#z7*b4zM;}{(XZ5P; z;6t#z!T}ca#d&-w3ZQ$*@g7W<#qzf}6KnVS^N$lo*y3yoUXRsO| z?O~?L3jY9ea@5u3V2t*x$d2QQb{rxkfI|NOf%qRf7RlkCMtE~1bLwT*$bfC~$$Jzk z(P;($0P?ZibYJ~8ol7tm?6bVjWRJ|Y0KfhwfHrLOZznfNVF8o=AZyR|~(Z5U|xFJ2t+dNMp_}Yfukhoek zU1NqQ=2lV`x}?%G1>@Ya=n=gx{{ZS>0RZTP$l~ohGdU|?iQ^g>f(U@`qK93(0DJ78 za~2?hg;337u+DwDQcn<7A!9~-+KQogCmV1_d%DHZ zJt3`p?rmYSlZ?V5Qe#)W2^${JeK>~s0zn*r0Cwzqcp7m2g!0LEC?l1llbRw&DNPP> z`=run1quipws?R6Bf|yW5k~ED?8Z3CE46hg3k?(LwA$~!KN=jk>~{c_Or6%Ml1TYX zH9E37dI&Bw_Z696)0Lo4c}{#1K)PYcM!-G>KCSxG#Lt(Z(ta5xSEPf(-7Qtsh!e{Y zBmsagjw3Z;?lfN67qNQQ*F&KA(D`dE|$tjw8&x zE+mm!Sn?zK6vpHeM1#~=mT6sTz$2*N*MFip^Wt{H0TB#cYK5n)b{3cB78$ za+?tZx>I(~-4qi>tbX5(Vpww#j~zArKUV6_qw`nEx#>|oN6}b0dd^6!wDs}T@fKvQ z6gfLs%C`Ri-``)ku>wn0Ka(-C2>W0Ub(g8En3;u%pbu7(#H3^(tkTzx&`__OpY`CK zjEIRC9-FH*FWq503+m%EUMT}={IA5mlS*Il4vNblL<|Dh$Si1rF1Q1)X8J7Z4}wHq zFjgr{QULyD!c%_z=FJi-WzZeR9d#At?Y5)lM_Qz6_N>#&gb;;1N*2nqd z))k@)LOWM;iT1A~FCsLVKTz&yzwqS|miuF+jPW}64;#;rw{IWO*}v#DEWUNI_D&{R z0YsmB_7W^IK;}r9rCpf{#>P_;$av{V6`JRDlme+K2^idxRSHr)ex<7ZlDD3E>hxim zqzIsTn3u~jN?e6N?eKR67{Th_wTza`(|Q(Cg{do1xhZPg(nBqX%b-#Z5~JI;*Z_Wc zZ@~}vdle-Zrx8XPCI#kG5*GgeZx^dC>h{+#qi6$cf}>j=1J*aztSmNVIJ&Zs(z3+? zXljRywAa?c$gcj3nkF*v0mEfTX_magYVb=lBuy(jrb5y~6p}S`(nnHAc-V!HyVo`x zjcbDkBm>SWL@HR=3_+D$fNCXw?5+h+2R!7Sm{x&EV#9iqWQAuW)-TUc0O#^wz4Z>o z7#AM!VX1PvA|tHcq=(d1k~1c^`XgUEO*efGE6c?7>8xp?b17z#S**=n&lw}KN+c4) zKj=xdP01n_llLf6gR`AUXed+1L;CQ+d5oT<1z_VUnO92;5&M=Rzxc^iodK`OC==sz1_xZ;pULi9~T`m8V*%1F6!&c5CsCVKKw*0mJew zz8W7Tm}y?$PQ#STJf@NvOfid0!6D{#?GDlq2;<*}W+VfzYY!IERmw}KqlqkNUE@2g ze_;chQGqY&L|p;Yjqm{t-M8Qp*2#ZOGRs0#n#02yR(6J1Aqysqp0s4M7Enl!VR*6M za5N9Z>L4+%nU*^?p(qCi!V>1q}z~ zmUxTxo=L0JQh7r0dQnLWCpB$`Kp&U2bO{PqXSo3Q5PBaMk8+U36yYVABZ{mG9LR+1 z@Manl5*cBV;1O2_8^`Mq5bGZPw6w_|u zF7p7PIVbJ}jj855pXmr>f$QLUV*EEhk z-=@-}i5yYNy_!KGPC$IdT>d;yPpL^vv6*G^jj3YHwp4&{c+-+Nm=?PUB{xx+;F- z9=~Qd<8OvbRT${~yG8*4x8n4c3)B|P*&ts_R+<=Okx~V_R1Q9t^&}!Y4Giw}$E>qP zh&LNIjfVP{r3NOClv#@KH{Eq_kUm%Sc3Sk%){4Tfos!7Ew!qPt5LNdo- zvC#u!USsJW$lS&btPkbCNyB=KmlkVrW8=rk_Rl;L2XPFrGb6gg89azBBC!PMt@iSJ zDqOcpYH(SefD$!WV2b>4FojFY9@=zoL`YncyrTr{=y=O|TsAumVcNZ`g8j{zrD7v^ z%2qP04X{-a71x&c+prtgfR7vTWeXf$A*hkXmXW8EaU_ckv5`pw40eOu-%mb=O)Tx^ zs~x*T6R9Xkug~S~*_zHQo4&`bMt`FJ03dP|n#G=uhY>V$v{OM#C7h0|f;D0uRZISu zNdPQ${0=9%J|?HpUy#V}T{n{Gt$pz&FV=h69}XC zHzg;xVgCTGh%CN0;?hD9wR+;&xuVs`xHL9}H$;2xqw&^$8$d~Vgt$;DNR`Oi6ocj? zAvQnCuRUv|{{TYXO`kz)#hZjZL2_ePCzdiJ%l`mV%{pNv2YNag()L&Wk+_EW{PLv$fXJ5r{1HOAG@$FoVADP+|~!EUmr^`Q>Th$ zG95jYf?4pH@wJ?B#mdMG>I7<*o#SAg=OCm{YPsXk^B47Rf-0-vP~8{84^7> z4T6%-4j&mUnU=guEYdA%s)4ql%WX()>HJe!1VTfs*UEPhAk+zF3ci~DV*?omjRL~E znms}ZV-g7Bf+Kac(gqQ__ojIyri{=#*;mzy1#e5f*myUes$5ih z^RN3^sE4g)c~nZ?qQ}HEUg67;8Yh9-1fJdtAJp2&*v5t?YYY%Y3ra&*sDTWC14QM| z*dCpl6Fn+wjB_9b;e$|N+Snv*RB+8zxPg*zah|TOf2Qp$rY=Jlhw$A)F&IU$I5g85$R zt{aZmXMKw7_i2r}PX%U7blFPw;$>S-O>0%EPc)vOL=ghtcPfb*aVa1$k+w#`@ecMm z@-x9SwYfw+Q#GoPK@2i4c0$kyX0Uhxu4Wfpfi=AalSG7?e!k`zPeU}{Xe|i>9%WFPOIta;!qWuq?rm9 z_&4f5CW6fJ6fTkSLV-(!B!)!?^&h3LJ*?(w;cWSVjiV&?6+>9c=VhDHO*x!GD%|x% zOp5${AT$XMG*$bYv(p(XNlxV%ZPBhI0eG5`Rb@vTl2@9%S4!w;t1*Zc?xloB$JeIV zw}NzrrSy`oJ2z@i1CLQ=V5ogQ{--0~U-Xbh$ngX9B+?Mt$g~r&0ZSMmLs$T8iarNp zSB&2s5wxJFE~%>2(7AOQiKLc=Y(o=BLj~-2=dc}h8Jzk(`k}*KiYzx?biQhb^ucZ9 zpQ>_rTZzoes@3uLFor2*L&g;Y+(mczQpd$Fo$`RNl1!etMC2sK@a&33_DJlq3%6%#MrB)yJzF6LhDW-VROI0v4`h~$N z#lHL44<7Ok<75G{-aRPElEhRHnX$2YlT}vXRZ=+`NSrG&te)M1NMcA}3DS^z2I?5P zQtTgdJs8&8tZ~I$&jjqm%CaxqLmKQ!>>FY<2Go=4A@MC=)YEx~W{bnd*y3OnCu}eS z68xn;!)lDcY>K<)AjHmz#Qmvr|pyY#Nip!K_z;pE(U5k0XHrr zd~wouJ-x(h@#9c>($`(n`k?a48rfOt^ySW&w;YwdIc(wOw2)8f&vGcHfSH0Uv4YL% z>Q@DMYfP_-!>iLt6tD;-DY*GFPGdfR%S$ZBByPTPIKHd=LsP6(m7t4Fu#YZQiXAL7 zIvFDeFu<8w6uU`aNiHj`n(B6H*^23EHF>3lCU006ZyO9y%&>+dQWoMz+x~|Tc6kKx zuDyJHKBbaMkxe|Wji#*2F7BffGZ>tHPLYWOk6>;800U^VG%}Idqa}+JF4>tU)oSrW zMi@x7$wDBtJh8^<%0nqo0ZtnQlp15M?^1^}4Ddv@tI@~2Q^Z-JAs$|Bz7G_f9H?pR zMIy3f>7O~)OoWxcN(UZJ_4zQtAOn$XZE|`i}NH%73g{wprT~(-3r*n7I0yF@3I1w?*VfP)i(xvOKu#9x9O8DyvlT9Ck;X zTpyZVWYhCw%G^8E=nRYzFBxlx#i}}3kqvhxS03g4p<&k=4r+Oh^>gq%8 z(nFQCj*bi_HQ-rd`?=nCGY5AfC4u29wgh#N^+D9WYxLig-g@-CoAdO=Unu;*=|3+z zex?F^l-58c@!?jNP&z|y+4d!o=zE@-KWT|3f>6Ym} zw4S`YQ~JVVXb74nvCD%q%Vb`j-N5r&lAxbo?wN;0BszUG-c(@7Vzvs5+Z~-lDQ0C1 zEYV@MfEF0_Q93hAq|?tLua^$06q;66W+PM_Z79V-019oy+Y)hu)rZt~nY{~=^J~n! zo=c`I^&V@ebF$i+mFcAE>d;!dkH*)oUd1aC-}TpeKAo@UznGa^-(B>M zGYcnF&r1rA5yx7W3kFR9KPQp(O`i{$S6{Rq;rzm+vX51ZdR4X_mb|n2t?2JE z{-(UQi>~VVbJpE4)_z-cEcyJtIC)XlJwKco1?&2ld@Yo<)wig_3{|P%A0L~EEmw-V z;-1Wv?@`e#*OZa;^<=x$`D*m-#M4@@jm2Dw-IcQOqJ^4CKv58o0{ngcr>CKy!^Jz8 zSnJ_(3xQi$jDswk`iNh@9P&!U`s|-=`f#$#=>aRBPh&?#fbqrsGo%_Vd|KUBot`vi zsEZKgkK~lOkPk)LfW+OMqaAxk*WXoXJWs+kUJKzKE2)E3D#E8#rd3!MPZ=ekE#&WH znNHc!eC1#Tf(KvGSIrOg0Qx)g08q}6=nD8N7}1Wvbtlu`Q06RSrg*Y& zWZtaZYtgu@hCc35E!P%iw_128#YPz-jwG5#lHT$|&u^v-XPI|A$;$m}eJy68%REOd zUhW&qe=T~eD^C%Ju}h~CwT#7VCUixLy?#uLnJjndT4#=`@rAuJ{F%JT>+d>zxRMEA z^K$*Cu_*NMuRcC|wW5>Mm`o$H6!T3GXq8&PMIgGXH|jSieLwYG=J)i#w!GPk7jCo2 z>su$%m2z=ja#PcDW~MH7uF9puNU0kQdr1s@b^0%)yalzd;|by)QR(&Xt9@R^@vTAd zr)C>OGI)B#H^)Q`tt&3j6-L~3;9Bixk4%Z-sNMo#iVZwIW9Xv%Lq`oT+p0&=0OXR_ zAm9Ey=O_C=^vBn?(N|Yj6Jmayu2X7T({`j6_5%$sRe#z(AtzUxU!sc0_rZcfy-b-zp*P_ti>hV-VEtWL8`oVDy( z11TawvV(W-BtVt2W?oqt(HKzmDzs&{dnw~26URu$2Bk_Srg&AEn{!5yxKK#)!6~hE zqPb=)KlqN{))W0vytwiQ&p)WIqG>wc>&v5ln|hDw*US;;B>q!Nj>Gi^bI!bDbx)T! z@tri&S?Zi5ojWDleJm*A7*fmJ%BEuEwCGC}DI{GR{{U5=^~&n6p?^F6ntX`zU(4Q$ z^B1rD?a$-$9%{0Md&~t52$gTT=eEwqdFrcj_M4JJTbY`_{(^Xo4p0;U@~MD{a9de zU1ALN*h4Et99%6l0POG857iG?dEJG>f2by3rf@kQGVOIoNK-vMl)Y;)g0D6X${vlu zLliHFv3noW*xYQH83h{9NOKo0E&C}cfh0Q5_;{w9O*{irF@_1_GOjj&6>DbvC-rO> zL=%pM;#zq;ZKBZloF05S4-VC7zMp@?tT!{w_=yaSr=NVK7_^EcXR>_0I{t~BSM>>n z$Kfm5&-JZXT`9$8U+L=tBeI5hL^5ADH%`1|RuLU~k(3U7uAnzqe^>tiSUy|U`c3o7 z#y_rL$K*WA=xpbc7#!-^`^=P6d8TCOe9lh?ODSW6$%^Tm#&;m?1$4*PHGb;rEhr~e z@O{^RULWdJ^(kamezWUpv@P*y@V;MQ$4t~@EX$?0N)w-y2==Bn%gZ5xGcOV&c|#XP z`33b;E*~Fzt*GQ%D%WY+{{V_Q^UTY3r^eBO#Fr8ZILxh!wh^US3OqQ;l(U61AaSKM z{wkr?Ek?a!2!JESAXab`Vb)JA)o%lC_8?tWdav-$ru;)l`fXgAT`cj$@w>&WAIX{H z9+AC~Dm7rP63uN3x`mz3^1iNP$*OleyT#s`y}FrM-W)|AUcpFhLbhp{OyB*O)}f!& zGlTcDr`rj;q29}kx0oFpO23$XVD$zwqxx?KC}d-;)t6}E?A@;n@yh=IYmT*Edy=V+ zH=Ro&L{ z62=++;AkW9sp4TgN6+%ZEPBXW%$1SEqj1j5N}T?7O{bBO*H(NeYqYZI+Lv^cHK&-mdbB3LQ1o;*Kk+@)%z{Aun5`+RRpS)v?wo^+rlTa{W5(j;>&V zEJY>7u(N6wSwEijZkhV3=|WKIf5-)eF5aoFS8knC%*8u5;QGd`=a zwdbXCtvu_mT!u;O-OP1+BLWX3Ww$#Lp+P)$Kvmwfy@9LxgTZxDlCf&cKwpoQ68^NB$_>Mndcz{O3yRS3&nR6 zBC9J6#mUEBqMI6xBoL)())!5MiY+evx@JAO4m%yl-q&Ne@KrH#mPpz-OaXWSG<;oO ziylMd5)?Srj`y;6vEgETq^~Eo$c-Z%r3=jSKMSv)jz?hr2XK3Mmri?pi<=@s=t-I5 z;sTv-O}^wEc0U?p`0em-oLkEXEU~L$Wk|012L}SVzWn)W7p zzwQ8@!1!LZY9v^mOD`kvWiS1j+Llwl#>UC)e?Bn@!@P3|2LuevAzny8R@m0aC%D&t zj{g9k5_vb3h?O?QL0hmuT;!U+n){K_Yl9g;Fs#I|Zr;G-+daDun}zzYkM@R!Zan{^zW3CNiMv1rRbtjmEGEqwoEXew^1cW+Gr#fuTTM$xb@nw-_W3l_yF_ z-nYNci4o;eYVyP?>Na7?_3iZ!#`Ulc#=+m?;KRc2c)?m~^k9WIXdqIM%9k4#xeB$H)=fwZ2+g<`Wn za!L0X%(1>&(11Z!!LU8R&%GM%Ixi)AZn2ReiP1wi*!OGpCiZqXl6F5M{OiUir)qWe zMCD}!C|)40!R||TC**IozCRoB!7fc)EK=9?bi>k?cl8{o z>`1E^nz|VrD!WDiL&ey3{y04>B}W>pLY zlXsE*HO@cEz50zM8&c0I&1$_j3BJ&ZEnA)jT7$VpKb`QVz1F0n1Me`B%hO#{*Fgt3w zVPxKa&!IdoBf%wUYnw7oE6yQv7=buQeRlcf#aD)b-sA+I6BiMgELzO=2VH z0C=lE!w*-9AZuhP-)(p+E;>k(IF3S^1ybJMQfHX6azcwEX-G~(kQ{*QHVFnmj5JE} zT_|B)0?|ns(Cyu#CAc4r9@{%Q*LXAOl~y4N4_N`OLf9&9kO80hec*gYN&x==(!}IY z-uW~tjx13CWA*RS@yF((J7+;+WrSCeWD&s=gQ?Uo*fJfj5I#oF`0+C>jGB7r2`#Q9ooi#h{1vj2G!aPBv@Fsurc_Q~nRt*0X$cX(&ZPtpy9eco zBzUc5h%OO3LfeWB?M*DvNQOcp1#-W0eDU_73MgDI802lp<=tsp% z5F*iO3at=)t;Wq=6O){fe!{WP8rVBX^`ti7k5IbGvOI(yKoAvT9E0}Q<+KBlIy&(p zEIgDRMtgh~WJfRQ$24AqFOCbhSL9loz z@7$FgfI26?ZxDX@CF0PDvM)$FtQh+5X+(^S6=#k(Cvx&1cGVMFDkK{Pur{k#F;vq; zeIZd|g`J&;zz3hXvM(6uPp{W%9LSKMYX}4|D^L|ivCn*)9S%%Xa76YFM)NbrB2NmQ z2xXKP*iczAe|j}ZmTXDDitm)@=21OdF$H7%MG>QwUQB2A?i!|68`{Dh`I>Z zPU5#P2v_kouS@k_NvSP-L^KlRRGn;QW*F*-p_NKKd1AehC4=%DX;)1nkGMuF9FDa7 zu8!2Iw|a*Tu|pX) zfMeBi2*QKS4Av<1DI?cO5^rspy}RR87FPWr76(4rH=g}hM&#j~zM_P(C)+fCZ=vcV zauI8}9~}NPb+AsyHlBo*{@ytxMlB?U6%uh`09~IxUn-}a8=Y+DxS`EP)$0m)j* zXA4W|#te`}8cG$|A^SO^f;jl821YE$Tv>F)fbe;T(G=y5JTFL~z7^K1tT@P(+?}gQ zVXVy~0>A@cpa7^|K)4Oj>3@fM<{oalU8L~v2`s*BaxhRp7FekSjzF>OdenX&5qR23 zUBZ${h9zv8Id%y|cjR`g^sh@8ZciLA(aGAdV|0#qYt0=vw(3ZhSvwR1megpSZ?_T) zOLUC&Yu6bYbTIW=P(=5#K9r0IVCE>qkcN+BHy%XqdtZVTvb|r|62m-A+u1sUGmffKWVCc}(9; z-v%0Vu2TWny}M9-+gKzT!4h1a{6sNUd4j`nm@ zl;xNYy@;ljoVQQs@~kAx&{nS=G?3S z{Gc54-;e67ok>wJ6=b%G0t>fm`Vxr(lnzO=H|hR0$6G3S61-X#dpp(nmWrlVJv|tK z_rXS2feQCv%``)jj#?W#UGX0}9s{OM)OG9GvBDz7S>OOWDn<)>Xh0tBL$i1IKRmol zNus=7O7PDbsacrM3HN=-+W-LA*sDD=rg(22508HLq6Yix!!D1C*??f8|l|+(T)Y0kNVsS7BOQrHJQ|Cfddl zJ;@0xDv}8UV2)Z{?_;nd=VQR8DwaKFS<*!uVOZec8456Q%f8gGQa(F?d+WB9T_g`H zI2%D=NF{-;crVPbZvP0CPJH6KlzHak{NTN8z`Ok#qFjiAFjneaS1JH}23qfY*Xj=PcBgwS=*9 zqt4*Qh9+p4S7U7JqEzt%L~$+Lo$GIDe0pyVksnQ<@c#hiw&gSE%#7?vvRo5H)y?6tc7&Wq5K;-d z+KD78#tA`;kQv6*9~&b#`iuQQ)vNXum!Tv`Yph;{u7trvhh{MgS8CHk1WOUreu#fm z^5hhvu^lWQ#I1WMO-`Rh6zI%iD-_Nn4YrQcrj-qWg|J2{v3Ah-#*zZW3033(I?1L6 zsCL_~)7^2Du1LPFZl(VKOa7k0WAVOj^bc9!I+eVrt&!?{De12;v5iL^k%on#G#iWn~ zX4GT?<8|eauJ1aeTf$6VLQ7u6WoM2qmz#v`DztW@nJQi(Au=>&i0l|B9^watTR&GF zYdxCsWW2HRzavOR5=)DEdAwaapKif}S+P?hwxb7U*#{>qdnxWkZ;E*T0EhUtr%kKz z7Mf|}iQ-0BWicx=1HW;NT8H=qVOFqu>AWB7Z5Dz#bgdlm#UVx}4J;}HEpE7yb_UKj z7c6p3o~cY=qf_dGs$hc6tewB=SqqO}8&RxCt$!6Iu2R>j6wpm0k%JC`c!rXq4~;wxRc<%Z|a-aZ~G8Arx~*U&wzfdT}fW z{YzaR6!=*zNg9Mxk+VKF)=MEWsbxzyBqu|ABo7Rf{;5)*_)=5>x~(f zPbH;}7Iu4)CRW^Qa6VHsU|oBguz8|-_nO$c(#Z{@Jk2CF*=0+Q9Fe-NkQrhdRZ>^n z<3+fG@(+pByx+uqyLyw~m{*b+0Ifh$ziX=2kzBW=kyr^lu}$|ZWRfsmH4+d>1P(yd z_Wr4`ITxNU_&y4g-A8ESg5ukj5<%t_o{tkCavQ$30q@{eSL#crs^cSyE{ZK}4OpH> ztBdsR@-EFZlEpyImJyXvOP^1RKQDI;k}ntVI%h?2!9Xib8LVYX7X)+aAcMz4lk1HZ z^?4;KJs_5g%-vK;{$vI4gLQ5K@D6i+So5zOVj;5mC=6BX#Iz!zOw}eyA#(PfYOr4} zs~KH07>@QqZUu5j=WaeBSJ1N3#ul`ZH1#2hNWn=J(z{3BgBAmc*aY_^>ssu;P~Kl% ztt2@vm4_c;l4f8a7M>YSfSn!)=^jhSs7d8$KxXEJgk=FAG(5MGXOhjUak+sw#Woul z6_bmVWO#1{Vv=wn3FbgL&{o?}>VBSfjXxA3kbf|Fva5m`h*PyAuaji-^nYG>ZsE69 zju~sqWDo*<=u00sH?UpVCbPUW{K}z~q{Q2?QgksoRC|0*+C?E+xt0MsNWZ9IXCQ?P zP=q98gUk>iwF^l@?UpEvbF`AQkrlJHQ4BU_`&Q(CaZU;biP-_Pwx^nX0b**#-f9%E z@kWwex6}8`3B(nKVqP3lW@#Pp6X~byj2*dXyeW zisMp6aC&jhSg8;V$VVnV)PD@!LpZ?KNpO~z08Eu;ShVtJ(8)#jJH`pck>xWWVrbyxjN^tP`lcj@ zM$zTY@=d$G;^lV>P^Yb^!S#GLEm4NGHORY9_HfpL4pwt=%+DM!UEbxXR92|VTkLFkLnogv8}lVKd3R;7i4e0+6YZj zePTfhr?!s#cYpq&o@8Tk-%s5&4PKze`t1WBJ(NBoZtn%B6oYF}XK$92= zBY=5=x44bn={zl8!+c3KQ%Nh@6pAC~z^s*$hiuEg{9Ef7#~j~@eNm>5$NVN0P5x?2 z{K=V7hnhrrRV_-O1_x)WKIHY)eY^OG@lg6dcx5X_cdTb-o(hrKimVJo;KAvrUMKAT z085i9uD7DKHT*@pQbTHtut1V4tgSE)G^&*vGOJtNBQZND%^rhGGZF|WId*aITfzDn z{C+|tf4YXZr6VFoJzBKTA!(7D)5ssYEJFdv0~rLJ?5^qgF}+K25oS8nthw}Bx~+ih zLaATYP;_JpNd*2o{OiU`Fy|_@cfErWgmq+=t&<$Fx1}n&mIK_RzKS1jAf$YFljt=q zu=%=$T3zhZ#Vltc)WSTeY=4W(quR$=FNtXs+8E>~Wwfy}$?9OVX~mAO5E8yh9`+6Dfts6$x*7+E@fn;MQzaJB8^^G3SCqd zwH29}lyU&0C|LYN^xQCFpmW#+Xl!_+FV(XG z$tUznBD~b$io~`dvn=S<7!{C;gV9wC6-#J1Bm?`8gjVXTz8>BCF;kj1ywM4rW47g_ zkN!g}Ru2{SqYh(ir`k3P0U10#cQ$_-Nu{QVUOZ5sP$i6;{>P`I@f{&1MQ8I>M#qy* z(afZBOtw^mV!b17bB?dSPcovkvZSVd zdq%Yw5ow`5sz!ZQ_O62bvXVx(nhIJoJC>z$$zV+i5=QcWok*ssrlq{U)c@Nk`5G(V8)9?3y?O&Ka;Th~U2ZKrG z)ePt4Y2l?&9hQnmst3~}ny$=22CNTzT3QfTqXsi6U+-$|dvv(RA# zfh3wG0YTvMCfQex_WhM~L2aJ}3#%?39XY@Of+=+?kJ9)gcK1Ct`ncIpnWWgHjm<1? z7VKJprEITrS9!l?8EYmciq&bJXriwhqZ(DAjx=eTXd{sNkhZ%8J%aC-apDGc&AU|V z{hl040HX+_BiV*Hnr&ELT2+i}#-W&K>3K4rkUV_Nb^bOgg3dnfGR!k$*`6wV-e{#( z1(;1d(J3*w4q}bWn_g-Ps}W@N?o-SBAC-Pdb&fkJml>Zn@Lpu+noNV?sA6g1dK0PW z^ki7|j(vmLGLYXY!E z6UY=U`mP$?3=`?&dEjBFd5Rcq5!y6Ybd)Kxv1`@6eMAb#9Z~l!brd+uR1P&B+gGfo z)r3P;Qh8D-1XoDx5gh1&wjdwI{A$0N{Ug*8`IqH?Tx|aU!}uFH4xh@kXH{d8%+j-K z9a7V{;MQ3dc81i4(^%2eoya_Gb>6DQv=;5feI>4#@?508sym5gV67Pd$U8AB`5=6i z8`tkOJkQ4qy%W-MT&)z@ezc*QVGW6F{k;l3JDZK|3ejw%39P{npnadN+t~xbbYoPq z1~DQ?#TR<*b=yx$LVyWS2qx~%KqDd6YL#MUh2dc;JWQ@$Qx}~qd=}garqQ)%5Di`j zPngUN``M`OWft9O5RTS40xPuy1*wQ==(8i#~*Nb$qw- zuj)h0MgkGhy<6q(bVzJeb%k(UBbmy|?_r1NqCm2<1Ks%gUBrjSoKB>(=BGyHI%}&u zspvl~eADwUqVxSzQyqoLd5O^}LY_OUx@G!G{zEZ~$n{1hOqbr&X0B_QtF&@N0Fg?M z7IsJLFa1$5zEAmy<^5lxTwX5$<|K5^e$SHBx^FL=$yrPsw2~YD0M)$S>r}1N)hXJ& zhs(u?>FFEnY%@i{1IH)0cn*_Mq|tbK>V}*|xGXF3?=ni&=nbx@cmfs9ef{K4f-B&Cp*MpcC50lTi_zt$tHIupu1kn7&C>KeTs zy$9FbPvy^DQlF{rXBQusezvV&C0iwSmI^uYEe&kU8MY8riH((jPiaL+?E%$yo4@LL zr<&@3S`AFI0ohw%5 zB(`8B{<2?9UTytb{W5>1KTu~p*y&F#`f?v5>iIe6&Nr-1MCI&xrR7a7p1F#Pr+Q-r z)7c9dZln7w$68B}uBnZy6-;F-GFym65ni%IayKmndOllp-b$dzRjwVQ`<|-nn+EZNb7BODiyu+qlMfG&z|%*gmKglml2%)2 z_XUyG-*BQp+q4s6m!6f3Ak61H!0Rrh!u9CYUk2@;+5$B*ampgy|&dn-IetHOR?pJu1|!u*j$&AJn6-_edMwC0i9{ zl}wOVkx^YZU0;a8T3GaQvNO*dlTR8c^MWWF2Kpc{BASjb9s1}r@MjH#)xUnEiVE+R;$q zdAU4K>78;~t0(k_XQ}JWUMgKXPaW>(avQsM9-N-~)xO_C9guxrxP3CB@Y`)Wb-?*4 zgXy}AW!`@_#zwPiHyyl<_m$D#)tX81@yQfnxTIBKjq0#vW|x#`8dQE)XR|iBSHM)o zR4}4RV%0gIGlG9*TGCg91Yya9pzU~t;(78~YiS&lWmSn%#YS;t1vO`}yYF3Ijcl=) z@7A%Z>_coL7_%8>+Pm|(Y~bzr>&;hN{{W;`H>h&i4x_WxHz>(xjM9%&R6?rp^;%J0 z!^WjmK-QC%xgJN~uf1FTl?{)G9-Qh6`H9-I$zBKqlL=)~sv??Uj#Y`6x3B;KMQ!YY ze0tgHKc-9$W(rm^lXVlzi{mm?K^Vq*>I#Nvq?QWOBCL!=R@?2*%MM~T6|Qs1Ol~^t zwkx)Ey(;{o^sv?IebWX|Bd*o#&jT!E5XQ2IiiRbD3L3-l`pDG+>Lef#6mL){ZN^Q| z_s13O)K^ufk(kY<(Yrt9F9BH_BCV7V8$Xx~)^IxU^>6(!JoQOAeT3NPNGuJSH?DTr z(Dfm&UOr5_ZaO;A8tt;Zlm7rtA2%ouZTJfTrb)3m2)5rkRy*0y?y9A<80$f`>_qe* zQN>H{G8TWM<7W4*t8+9FK!I66gGj)0Mt@V)XrtKgDz_DCC#hej-pT2%j>u*F&g!`= zq&0e9q%gxP5Vt2Fi)MHl)oB~m^us8-6p@JylvXi%Y-aJDaAXM1NCLq`^3NN$%tI>I zKC+{*IXwr-(4EaLlTYd+V#Pecz6Qk$SKYevAJe}MVax zbj-`2mVBL<8i0FZYVgBWRjD5r71+%q$Qc1Z`tJu1^pn=TRI8Kozs;z8u)x=ZtlnFB zcTy~;R#ih0nsmWiMNxx9T(w!qY03S!HR0dn19xJTWG`eVGI+HC4 zhL=jASA|n1rJYc%`b>$tI3~Iru<2usAIL~vCut)Ks**wj5zKA2gMMZelSH1iPow^w ze8P&BI~jt+;Q9**aK={UzMK1u_F4h%kL|07E!~n=17T9Fgd791DGNGUR=m0L*Pe~c}#>8$D*O}50QLEEo9RYGWlZBu~azqcUVB4q4Q&{`kresO?9y} zE{FS^b{$@y-mI<6CHoI7`CO7m@a>YbGL|Y}TF9mno-xfdOrDf+g+dS_PLb%klgT9c zkdQRvzh(o7BnwD99%tHTk~9D)*$}s(R3wq9w~HZ%3;iUF^<3JeBvY|xV{Y_GHZH)S z!RD^G>9;rLRz<{BI&OksXvTqSym5(cgd0u8EOJ9j98SUi0O;IhTC1X_N!gLjOOt}$ zLT0yWNv+wL!IpVj)^{ZA`pwwL{{T9dumEfG;lc5;#0tqGvH%HFi{P==l1|UNShXTCDpgTO&u? z@(I!Jp|1MzVaHCas;nQ2f(*h##Y+4#f&kehf}nRJe~%xe`*;`_T1gNNCDtAb7~lM{ zAqSSu*e>+JNgLLT<3z7Y5XX?pjm2ikv2-gKs}+v7=E*?@=K~y@&37F9_WjRQt5563 z@x7*s848w01`(xoUsIQEC*7@fKc8=J5^6djSZh04V$!08V=pBoNdVu`L+*?7UBX zciw>B$no*$c*?PgH4MyMcMY~0sN#le*w^2nHn0U&3by2spw=%03n$b)LcseDI(1sL z<03Ne>ha|w%O3qL9UUEPFysK<&i?@R@$$ocooAo!BS_;rl4d}jlxnP9{ZfBGaXea2 z!t8I|uK*g)-@+wg!pf+RQKuMropB(6`?NFx9fvN*=fKRyJ#zTFIJ>ghYS&c=R zTOiWQR<*OwaO0tc(3tqsadNE%E&k)N$cDF9k~?_&agOW?E5N z%GR*;-5z{DAALzdl`h&qVAHx_mze;^Sr0}V=zBez^x~~${=yWsdm+<;D)W81V_9)U)`E;uxp%HB9CtX&=iwbeoJz98wQ0Jgtq5 z%vg)-U~6PWYK;X{l}&gcj-`1!t5=MAamO1^y8zehvjgnsC?s!zC8}lQSe(l6`r1b@ zOvf_U00fdF%N(S#bOW40OA{m`NjLx*AzbCO#Z)M|?qQO^~7EU^ccNoJ9K zIEhwWr!M5NEKeVT7hn*+I7tz9g`PI!BZmI~Z7;E-Rdq9s_AVHzkB-cL^<~6)Yn6@M z-@QcEPDIGl$tR}cKqJoo0PU4{mST;iB>~t2$17NFhQ-MoISl1nvO}`zOE)upu`W4D z_INY70)E1}{{X~NblN^TEhq5%$F*!FD;AXw+igR}v@k4&CD@R2OUc3J@jNidO2}hZ zIb~S{?g0y5_5^@X{*zUkJdS|8(A8Cu=XPSOk^0g}>Zc|eBuBld_#pdsM*HY^pF-A3 z+Im&+*6utM%`Jv~uFFU`gkpQPv>2wod@x6s=&W4f@DpKg@no7vY2by4bRzJ<|fDo+&g_z-{##}I}(015$#GMlb;C<5sFw+@F*2`XllfTRBa+l5Ir zV7^}%!6L4xc8w=b=g>g8Jbk(f&j+Oy!Rkp1ywNZZT!0Y*2i%N1F-89E5pM-JC0ey| zIY__T$M;TZ)rKh82+8!OvlPlB2SAijAm6lwOQbIerzyjcgi>{Zc@ zNfo};WAD8uznM_J-bylD>1witn)KN$tE_>Idl?xGXcz_?jwnGQEph}tkZ(u7645%3 zp!_9L*}PX!T>4q%okmmxTTv_DoK5(Dh9DmO`)kBY zM&~qCtpKkSae~nZV{soA41Y^|0I=9UB<%078z00i2AP&G4)A>}0hyH?1&PwDB*vkb zQT(j+_UK1nr;cPuRi}-`6maN@R10$&zRM?^XY}ZfS0j+FYh1=rw+xQz1-#!-SiNm4 zJZ>j4il>)9O#aycj0GW%`0aK|He|16Q3otY5fmNOzvI?|SBM_w~>V9T`|i@t}rf_K?~ zUxGJLtNQoFbrTpzh()7BJi!qXz0lfTtdG>+$4kDk-Q2?(B8pMEHFQD%2Wl|dq@37L z-sJKY1~!g2(Yxpzq_d=ct&D`T+L2#Fdy+;V72?_(*x4g`J_zKcd(91t7a^!=#3QbX zeIUGshZg+k6Qw=KJcq`EDZyfDx>E^msScrg5@K z+~&hGmP*H@E$vV!iUW=ZOEF0qK^xk)eAi%FFoV)|X68`HHb^=>i6i;rrSNuEITV6O z;`C*3BZ9OE%iaLeF#bx0+YaA@*zd&3@iIuUKr05F3vreqqaVX4An#-m-|_)J$nn8a zNF*NkDpifxMD^p~%PA*r+auZB_8qoYU4Ysss%G5rZFLK=$v%_rw}oaEcyG{EgoHIu$ zikiaOCU0B3%fxKQ^Su+Jzt0u^d}1<8zNv!J8R1@0N_(?0DjBI68pNt`&k15O)OfQXlcHYv1F9c&jn+1aNhnv_|ZD?j>Y(; zh9$2Yk-mbg(=$mTHi`6IM)eujCT)SZ)N9~)gqo=o*Z~gEOR}K$wKiCgKG+>?V)c5N zTEM46?m?sSI6nO;$Bnl=p)ze_&}q`ZFChKs_9({Gc?01Tg^qm>|$R z576HoFA7l8^=FoAGQQ?70T6PRIyHzAiuB zOAy>Y^6&W6<*`|-M$ceQsIBSxa2W{+?F+IGZ69{DN!M?{=Pjy(?A|w)3gHV&5Qssi z8XGJ-kO3oG?lyI>d=(^IDm1LujjBZ)e^DQ?ud(V8BN;4jRx~zkrL1Jp{lPc(>pDS- zjyD{ngvLaL79$Sz*q=!M06f2U_Kl7A2gE<=xcS{AjtM1aJj0WqHMQs6PjE;FW8jgo z_#sVbaGrUmQj!8AA-zXCA+%HDL=NPR=eOs^V`{#ZD#;o~SaX#k;~-Pm?X(9H+Soq? z0z5&PmCCzn7Q)?@&jcD3?SI=H+8dHp4i=PQcB2_K^P!%m9>mqeK9o%ws1fge!LT_E4(CL#$^F{!QtUBTk(McJ%N&lR zJM5r-53hIN=r)J(z3W4G)U9Qom5DthvOVjMZiBZ@Aec2*Wk++cA`K8tZ1HUmaUnm*PG)B*Gc!RC%N|wXJY8#WQh@=3tf%cCk!tmD4xh~jj z>)J^8*v}?fc>yBD+?8IXs)~)GIg~ooM2cdkZ|94I)YM!9xvx2G3?1`27C>koIxe z$>WfT5 z;Ho^+R9(+m;DC~`R-CDgmt%tyvGK6Ow|#7YJXc91<&}{k^}7Ju6!Bi2wf#I@i|i|? zegjS&h>^BEZU6?{2LNXk?^(ysRYG+2>hJ?chY%=v+l7qdLd~ zE0RY8->_15?jM8x7#`Z(QbtwVJF=y=*4w$s#t0-(;)ynS=~=X>fEdAc;DUAl0S1)Q zTTrSVu90ijF~(~&aQbn2@kc5rAQi_gAIh=g_$#72AHn@36k(0sr{gj~7TFXdEPESA zBV?gGcm6={q2Z>+I(Wh0jKP;Da2X##Q3)v?KPgEys%X`6Iab>?HP0|+;pm-_9cJ3 z>-PTuo%j&cAm6cFN~-PTo1ij&FWSGzZ8S#Dm_Wt)Nds}tNaW|=?OiCGU5L?rDQ0OT zWG<%AO%!eRU;Fm?{Oe$m;AB)Mk}&o}@)CiVppp10%IoShk?De|Di0%|&EG_i4VGi{ z3PA{Tjkc=IEPyK&atK7*0)7G49{tE9cn2cQ13Xd6(L2PQ)Xc_S+d5Y~KOlk+A*}*O z#G{ezPxHzA+lggSb&FDQ+p#~lL3LFiudRUtbc86y3fx-F4h41eQ^+-#EMct~dS-AsHBsv-e`lEA5B!m?dt$`ssi}yo7U=feL>+-)5eVzNCS`@2~7ndjdS^c&o$Sc zu|HTrBftDhl6hV>XrneQq-H5V4nZ3SZ(Ve(0+l-?oo%P5`iso&Rq5fZ;2InkO-d_)JK{zh~TCMS2(o+6P;@&T> zI(BO$k_35Y{Z=J;f!J$`ot?J9U2FTb;(fm_GtpC$#zir;5J${JW; zw;v;`&;J0eJN=}@`F+zeSztp(77<^AA9Rv%C62o^3Oy^iMxo!S-Xdh=2Etg~eGb-oxFo=%t@e7nO?SQAF#g4XFPB=A?iE2tLuW8@V1PX8NiG zR&6e-MHse=Q$SETA<4#UcKPYw$9+u-0TT_ZH~+mQoOeM z>~-AoJ`^PKd#GL$GQ!9<>hBA3g`6II8)N)$w)-F&?likMm$|(;X{U_F8AMg}$JzY; zNdW7=#`ec#_zQUd0E!|vol54EqsOQr0?^zpQJ&|HIvaTJ)X{)t)N12VcN~%I7~AR! z%XG%bBChOpaZvN)7j9>-lfl)7RIM7r4mP67vq;}A)|zNa@7@f2$=T(^l_XeIe8A~j zA{$B4*?Cw9W1f0Vb*2TPkzONRuYJ3x4{=V-%~Xv5b*O*v%+NSlEZl+Oa?k2F1S}Dk zx%`2$NZ8-c;Dhm^$W!C!k4Ucb0uJI%<{{k3nE_ z-5t_!RjrnT8;r*FPgmdTEWDG+_YfmZlg?!(w{CFnU1Elsn4R26I^a3(rb_Kx=duyg zV%vaN)NLoY9x;-8@#UlL>_|Vmu%ExldU8sVTwsHbCYM05Awzcm00f`MZT1`P>V09a ziCqvv!J3+*Dy#t%8J<#Z_`n0O>JoiXsq>=LNHq;KR=ReYb0Hh4W(pEGm05tI^xcgf z4*6!VzF1JNBzW$v>8WfhJ#j}LcPnBY#8k9%$x;P|5)_bGth0$i`x`}taaYTqr@Ng~ ziR%8V^AD_X*KpPZ)p1yUn{J|n$k0s#Ecb3p845(F(?FBBPU5?Joi!UJlE}cd);nrd zP&*`yNoh~OBd|SzC;X5*Z$}$-Hf2^fhG;CfP#U?2sYO240$$+g=y4y75D6WCzg6n| z=-tOMN$W z5R%1TG9{v7jLyrP=vxZ28J%Pm=2gR1g?IN}vGz)!L!eo-d?a-b(tp$c0A1a9u6pM?8kp2CoSinX}B>^474ro7@W9}O5r6hJI z#ghGV;-Ye^vL-4J7~p~xAwUDn^5F#I@{zRrla7Est<_%U(Z=HhdCxP#7=fQG$`l`g zAMe*=-dTU8&-z>A=w5EP^UI{V%ORJ$J?U)qcBIUU^C4`7>m5O!vo1z^HlS3XB8Ig( zl#%3)yc}f&EcK7lNBVDc4_tpi=`NI`)IBR608dk@IzOwjEn2R6EQ7T8iE;JrQLOAE z^xdtjvU&=KP`GbVGstN=D0hzDufX%vuZ$>X+u zg7a(X&(6;)bACf+x_U{meFfH74>$U9e6LcrG6lPL4&4KjnQSvyc&Q5T;pdi=(!4!E zV%$WSnjvC4!=(I}@}7i?mBUq+D=dov2-(`1Do~2Wy(FiPJE;r^re)7#qG;00 zGQk@xs*^X|G>Da&y6p@Q$6{6t{2*ivBw(_BUfb#m6=~&j_GrakSq;klKTf4;&0MMU zjk|Vl$&j7kLdB+}YERpe)+x!8&nH^_NBPZ)YPGO_WOX(?5P==8eax#PNQ002nJyt+ z?3Y-QPilbbtl-o({-yq)F?K9VW6jQ^%uU8GQaS9jku-9do6vYPXx-h@e0ik-Aw6@;g-l+<$t!`d6^NT6C<9 zhoe%o^Fr(%r6@1ku`G()H*Q&q%YM*w3pg`hBS&Sg`57R$Xo^<3OOif&+Wwiv$_r|3G1>Br+ z0^2sK#?Jf*R*?fjtT{22Sr9hj^siR^P<8iC-Mxy$boWd2g*c(Dl=DBVsb8spqNW)> z;qGFft7gpNsOx$&QV)Ct7*an9g+5T!>p@=y<(>mEi^Af>kYR6izB2_STueYR ztoekm zD+P95mgq^RUs0v6CsHmxd%bY6qNFWfr*U0aud?yv={yROCFDHR=&pjL77xlkk%GN> zA`3N{D&4_!{M;0TlZV`|S7sn((Qo*Vs4*~DazFY#6NElBqTia?FEFypHdClNgQ#ejlr-#N7wPQmMMqlZ)xhoY{g1XBzZ0$9P+_RN;>8koG zB=Nk#kOGHf0Il2n0lg9P`+FS^1t6`ExP&chfs}FfZ;!iR_E0uI?oa2o`;VswlNyLu zoAlUrbs&&^#C9RO{{W44{{Y*?#5!2vAV(ZAr~=2DGBYN(B2^t-hzdG@P!_1O;vMdmydqRR`;>-gE!SK+DGmw5wj2gQEPwSt*7zvfjplY{ZDTq)2p?g5%u+Pb^giTw3P7SgEXFi~C z%tnbL`S0_+{{Y{y@G8bB>~bPPvBbM?cOJxmc1h9iuHPqH{CFW}A?X)bnc3JESppc) zu+Rt(`T5sxjsE}ykCMfkDh;b;L0@zLcjN6Pzny+N@3|k(d`R|}Aka_<3v@{XivWti zy5r{hnPVF=fVW?jPa_=n&p)T@)DN_Y5BpY$q>L8szV+9)nSGEzJ-#+MY>vak8*p8R zZ7haYknMdl+@9Xg`w)9*aT@#p0V>f5(L(c7JhY{GlN$ryTh{%mHg}=hM|$vw)IMNf zdTY~;YWHN4J%VDaSSi^&^nL)*0lWO`M}79H?sljzLw6um(c}#0pZxU!D>HCx5pmEY z3}**7_dn&)StwndgUV#Cilvw+4co8>WDk-@cJ18j^WzAL*hW{5L0k?2&b2TAc6}b} z%jZCi=Hobp24ud7aCx6HKW>LT@AAHkAMYt`0s&VJ!43_w(Tg?32m%Nx}X#(>^;dm*Ie|&PrGk+W>7>uFR$eU-{8`nmb~6Z9lk;jq83U2_b9I%ng;2GLZr3^NkZgnOU{) ztf71M9ESdP<613F*12p&6-8#aWaTIBuP*?02{E$v9rek+ zd#KquJHZY@oU$@QR>g^zj|if#YH8hv5QPOX>$?_l*++i*Jd^{w*zYVnr0F3PpV6_F zEXfo=S}%zxYEu3d+Pq>>vvo;+qY+piS2ATldTx;zT*K+Csd zu6pKfqLCuSW8=UWBxN?tYbdrEJqMBB+L4jXOK6bg29G1+j_FR7>Mt&8=JDMxnU*>^ ztj(P3W9r8ZpS8JhVOiEY5uRUe@uVD(=|g&L*nk_TZyx>~_;2w0RrI#I#5KCTNB;m* zLE|yO63KKlKZBXU3+1q7u4EUB11GB8K9(IPjK7F}8_!nICXG^74{zs*_b3H+IT$4s zN#vX1=Nt6tlbU#D>R&Tx#Z3_z@trM)u|`CRRfEDaS@MeJ`er$gO36 zz&==X%`}f6kEf8i7!P9BV>Ot$>kvo(0A^A)-j#C4-NG7hRhSNcX2hdMUMKura-@IO zZrcE&hhIuai9$lDW{cc*NaUyTcH3nH=e5&0I8>%i)Q};BO3<3to7Ap!$nrOF!1hzV z+hBZoguhw+DWNJnAL-LOp#fiB6cnN=yuUU|6=Ky!emb#V5Skf(k*10zl15-eNR9y` zD#}Z#IR%3TY9yXIuhC*Tp>@3+s7mGJUNRwYR+ML66B80Lvb_H$Dw zw8#Sx6b?tZAOYB%RBO|e(gxEyp+}a)JRUOTSVQW5RPhIo{$Jn^0-yMu<1!!p92#9J z?Nw783eGqbuJT_z1Cdz*@{{B9%TiP=D!3s>qNaVs%fEjZj`+7N z6({k?cLaFiE7PXsCTkj$XaoTAAdM@XjV8v=ZEOvl>%ls()U7(I6?m8v>j`K>h(c>~|jI_G7NGM6udtQt-$>*%H0LQk}yM>p%c|Y=hfT>r=?izjY?yiZo#= z2GcR*zp=sY+TOlLbH3mY5i&RcO~1=u%dv<68qI@Z`-~iS>Pe|F%=Un-1AgNawc9yA zzrRd@E5{1G=>iThu!W-a1dZrJ#0LXl>tknMf;Zp9OA*!&8IDk5ZvM%%(d>IxGzYf9 zJ^ugz9qVNHP_S%XpPUybFw{Pq)hYK9u_t@tNaBh{nnAwg0lr)CN@u@frz+x9N{ST9 zp4kC9{Wgqz0#}jjdxZd>$Vdcn1~il)#zhSA{fWDut#R9CpB;*apGx+?5}}6C5pq(nSM2i5Dp6bZ$IV z<5C#>0Cv0IfBkjhPpCsFC7sxX!-^?YK>RIwMRZTbs(`VgM;RoBt1L-dpcslAUhjf9 z>RgT|5s51m5x|eVg#`d*KZZ@>`Do0B8eS z0Q``95Jnr3lvSP}hG#`dmI?m=Oh!T3^!pHb1nx&|kb7+S04-ev#T@d8tDTe#8<090 zI?(U7+5N$XVW!uHVx3=PW>!#1HUc0A292>i^MF6kskW^~)d8Cem1R&Yb7uSdjAr_1 zg87ZTOAsVdXd+2pT*9*Z!5iNaz!UyJ@8E@bWSTXMDo+}_ax$H|sRfHJ_wE3jKxDt{ z06p7VQ{Q@Dr8{j5ku+%`Bb0;th&)IiJJ$OXqBp0D$GD9 zMfErlY5pZUwAYD0ALEm(9az80jP{H-qP;C-gcS*j8Je5WQqo^tB$h_ zj4?{-6l_!mW}0X8*-A#qwI}3v>^qjE$UOh>Y>BuAI0`Qyxy$%z1yy%N2ShjMjpVr&@ATMaC#+~h`c8g^1N z7!nI{X43vaKlGmmf=5SY@`(f$-dU}xg#ZWudmjG)w?s3+BY^H%Km=}3xxplW#8(}G z_Z>!bNPQZ$9zrLOFlLXuf;4m9PTK&U;Ei_w0Mo%3tK_W2Buf#Y(;~#Mj(bzbXG1^& zNbRw`cJJej%e6TAk;Jj2QL`eX-l33!p}+^=ZGrFDcHeX2HC&WW6IlgB>Ws({c}O(C z2u`=9AoJgCa2Dp`i%-zTNF0c5Nq_H2ftEe zIS~`nSk^{RR#I1vixKYL$A8AP{{X+>Wr~&%w+U5aMOLt?yM623p|0#nJ^TLv+u$59 zXL3`S!ZR3Km#Ex$l{)~&tN3{EqWRLT|TOWP&%58B!m({{Wich9C`rp`o%) zyMdvu!L-n_plyjA6ZxF_vZInko=s8eanDYxO>goPFCOi8?{)4v;u#W~rFpptBUUQH zIHwLBSZ-DfLMs8Xyd92^Fb-7h7nR>d9(MWF(8I4hw#4*jR^y}l*i#D!nLQti>Zz?_ zt=Wd^j+M&w1zVyhgg&EJ2$EbesfAs@UmCw-FIZP9&~s)AY@)Xj!?_Qz22+Wjbh5Z*~USY|Euu{OXrkv8GU`xIU z9I}N~RtZuHswT;?>fj6!o_ahIBuw9kJFNO>3gjFz5KVzx*yP`Q`Ro<$pUq@CXQ(j} z;<|&Uu2{un@$!)s%2`ToE8MAZ65Y6r(AkDs@)(_?HY?a5>s|*wS0kX3S0)Paa6s^C zCt^SeEQ94ZvmFhR+<)miAkocs2FTfYC%E!6$ZR~%YDmdpEVgXVVt2DFh{TyVsXO02 zo-LZCNPQx+SoRa{s94AZM1u?Hd>%a4m;Qf_=f)Cho;TTKD0(hNDToA$=D%}YVRUDz z+?QZ8md%b!Sp%>a&jYSh;e^J8qB2ZDI^skSbJ#y_et3P}coTAju}Hsc9EjPO z+1GJ~W7~-*vk&L+H@}_uD<(bu;ysgIfWYm71&dRY@Z~-AZkaT_+9Uk63&rX!K+BxQ$NaHKXBaigUd=)3T z*aYiZ9oUiiE_NwgiZL6)2XsYD*WZA~z|0 z9)EI4KEU9emC-%E2L2Ag8^X>Iqj{l8vRF59LjM4_7##cc2WMtb!qr%xSM>v5WBz{C z)-y$-jwY-FL=K{vkT0T~N%WbI&bW8i62(9tjsAEjFWX5pk_jhc>WErF189(BZ%7vW zYrnK}8z7GnEJHLjW3s|~Gs>HEhJGLs{iS|N5(5$6yOuq0|owKZAj4329G$g&&_6qbm3ll zDxf50S6Mi-gFKOazY|tenI|p88mSDs?tv8n2^D_x+P7L2vLh9pMlsXR8Vb@MYTXx1)9hd16WcsRz>5v z_IrG_aOl9V1SNw(*&jfTdOi68t%KNX0(+fCpDBxxVlT=*ZQ4VK@85&()Y)_Qy+^NN zMfL!y(V-8_jziRww$OmvQQWqV_V^bx*X%HzY`A7{+#_JI%A;yw2eygdEo3(_{B$7)! z+^dxVdGg|TldeD8y%G;?4S}tAjdBa|v>chpWewd~f{h;Fary25J^uj5&x--@H-zsC z%>#}rBqj)?`-K`DN*J_B3hWAz!&@hlX!t89PTzvPS!PLQX4>*aga%nVaIo7m7dr#F z3OJHUI`AjdOj%V^CWh7A-qnRlyzzIAmnL^)ZJ~nQQnN88s1Ou^`;vQ(s)*`ejb{HR{{YkeJ4qBK)7J7)*4&ctV`dD# z78hnDgD`h_=k-GJ9=5-@4;?_SPT9=I6?)ZPwUEDTtsEj~&)X>)^nbmHBTMtgXIdP* zcR}YaI>%G}6jtdZip6WS@P1kXV^|!^HC)e6ZH#t_NEMWlVpHl9q6Z#(_wV7DnEeCw z{+dYS6H5XZBN52V%+QR1umfi{Pq@b&QEIf)w~lyRuLOiNo=8&@AjvOzql()=ez(`3 zGt;)0UPhB(BzBi*Q#6UCR$;V0=iFW~*fwx_?EE{z=XbfZ zPa+GYQVNCSGXlVk&FML={Y~kAE@)fFwaa}&R0@^2$BPhHvoondI<$9Q!wha#axmM=#V20+jD4 ze8cF@yz;*X*OFtTsc!Shj<;VWG+0@p&0zAci_XL`aNVrPy;AN&Iz_GO@as`f$h-ga=jxpTI&~1 zWD(=E&t;lvX-#IY7{iDoHK2)$1}vdlm$$GA7?0HY+X08GkP~!$>$1vcj~f(i6yI+F zWN2lu(?dF|gh>;UC~zErz-)N0qRY#l$Vqn_V*?g0cC|3Zt;dV0BN34#3z5PndQ!-% zBP3nK-@N>Iu&_4l#aV7-`dcNAfJU-KcFrnV`;Kl$?iHliku<-J79YUz-RM4;@Met+ zT5UXF6G$LbWne~2I-{KC>uJSZo{Z9@EH=gvgjE!(M$##OrN-s3bGUPOu9j~3#h0-K zX6dglsp78I1{yXpH!n=HNE{ZI?Q26-6_~FOePmATrM<&T`E1vk9d|G}zM96)S+RHcp2SEV#h9bBX`ahX_1w zwqpy^ZtGZ!$yPEI8Y*#zXt8yHXZt z(OF4|2#+oH9gnx?w;~B(cwU|&zlR$bpIBfDl{H`^0u-O|55HTNT_l8gu3T06+?MU% zX`ze`->+J`Q_TLi>HD{zt9-M|<#94d_NF)-l(_0q*RdFh+c<4kP13<${0kIO0(Zr!^W8~4Yeu!V^lYD*6p z6tV_nUmJsGq-#vc7BeX&nSC&&g+4sB?IYdW_Y^(0Kkf%*+}D`9JnqMF${`1oFu%wd8c*QXU^m6p(96n0)_P+btBNa+tN zVs73tN#GT5-RVpCi+eE z+F4WyAdDLs3FW>v_KVOsyW68`&SQ(TTP^(Hb4HEl$LOom)zVB}8xJ!#5HRrDDdoHCQjd9~)e6)~;Vo?p`HAF}7gWuj-*n#{ASx+)cNX%E%ZxdXV0a zO4?)0l|I6ZPS>5)e+_(VPQGkDT*H7Obp?p77Kf<(-`tLCT%&c2S zmMKs=G@hb_Q0^0gk=;$hH%iycL2O{M^e?O+yj5#U8`~7o8KWW>u{E6t!v=0XkS(Iz z$}2C@@}{NSwF$bGSHtv&^;}FHOVrPdw`P_urOACqFItkzXCaV-85R3gD8{7Rv0Wn3 z<)-H5`gg^&(k20Tn2En7#%`>2&a&bkg}6SVXM$M#2gyMGodd zp_(87Bod^MD!u1UXQuL-H0hYyiZG(#<-d$1Ze7-XE z%zSs}#EhOtKV~2*zffi>Vt(&7xEQNCS~U_Svr$rL`l<52sxbGw#ORMM@b>zm*OJ{E z<~6S}`d`b-_aW&K)_qS(gVe?K7h1!MW{)M*(&POpYf`mmF9%LRe<4d7dM3M+e1~~i zPpB@2$Mn7o|1(cS1Bd9B%Yk=WuGBpYfluiSep=iYn1A;kGhkDCB48mul+UQ zJ`BDOJWC3+l9!H6W5>Q%og(s#NTuE*5-|oTRY7B9ix<`3h2Mur`ba>P+3I;JCW3fv zTB0&SvPQv+M(kQeZd5G}yxw`E(6_ont+SmdYfBPfvl$#clkrO9g*bz+=m$f|$S5;5l78K_~{V;i*)EP`9S&8G4 zS(+wVHkU8eIsBYRSJaZW10NLmI9Fs6{+XvAVPZs960HW0=$%NFpHZlfPp94%B?g_M zQa3qO{J!)q&GCWO$AqLhmX~*yjO`?5A|!IGL8cpk8MVQqS6uZ=<|th1%-sxsOk*wI zks~iGjPb`DewXV$rI%?N20%+UVHk0+NGD}_GwDA$)EJybPpa#~(%8$A2&2tkXOg|) zUR0Jyu{7+(HTqz#8 z^k$)p%SF*0DJQCk8XWFRE0e7tjLk!rsEtj)DPm6d;_u+yi$jg;%*H)VK z;&>LQ&R9tP-U(Jf&qoVW9fyn4K+sy5E6*3CcyEBR?1xGuF{oAiRFX)F@tWKbFrkBI zc1|)#Jz5P=iFSuLz*9xLSvEgmn#jJI@I4RYr;zYLl8Xp$=jK?fE?cYdQD$?|OB7X$ z%ZKvw9%0AhB$CLH>RRjWpps>TNXdhz3%o^ls{X6|&9=)AM_<2yf+VXQZ017LS>CCS za?7N}*@(q~>15F4l{zCIkCv!G6IqygrRb@!)~z^GVbv@%yq>FR!Di(n5&r;;(zf1N zj*7?vpWnX*(*=pEU41zcSsFda&-sx@9yo*gX!H8FqcyAtd|>_WDOde z5TZN+pmwrJ&5jCEc!RWxH&)YuyOH+$=fB5L?{6V^H3^XpU|E2qdxn+au)i z9y$ng(L$g{8dFtljZ~Ye+>5keV|Q>kvC?lac?$1RSc6;)o;kDff8nlS>8NTW3aMH& z^`muKvFHWhe-xIDq$X0L1VZQyD>f;Qq ztv0Gc7$8PKjLO5AJ0t_&U=!RAzzgDRnF^S(Bvm4P>%7cI4}f;M2W)gS2gn42y#qff zSCw3wCWCYCdB1Vkis(n&l_!9z!G&Z00B>{peg8P=CrZ6?IZCTXpZ)!I~C-3 zos9rSws*1mEUq4%#eAGH%RwB>)$6dWX24zXgiO%P%7puzM<1wBSciymkymoLnQT}L zX47{n=eQ%}sR!HJvDy3s{GSPVR+7x29m;%rfIi>{9y|PUCztR$0kC`-6+u=TNK$a? z>FrgKUvur-9RZY!<6qwVR}$1G@lDwyhIM6rzo zcAj~z*s~zm^_*X`7bBvz+k{5Dp504weyxGYm6=uG;M)v8I{bIo@4W(kJ4>t6(%6Zl zAjbkHdEA~m-x2(5k+a+WliTOV1;s^KjBwdD-XM6#5AF=a9z?frpq(G`!2D=9+?<=9* zeh+x|dhOt0h$PhyU`_};-+$Y`HPQDe8-Y~>@YW5A zvyv+CdQ{2uH%!}ik?>U@R@{!!h+}fZ{HsPmECFWG&>((vJY$Cmg2h1aQK2I`MAD#B z>PmnxLnE&L0ObPXlLAjRLF1g)WuLT?PgXbA9WK~0Dv^-gihiRh=h&|Q0G$sVsC@@? z4^YSDf1AE(^tC#-Gr2pRC()RhE#vFnu@*b}j8;0DWS-P>BDO{5tygHF^^MrlmPTJ! ztNb>d<)cVJuQ8MxAalU`*CM^T$Y0FWX<;DBljiWQ}fg=gg3AVkr@ zVS{U3%Af>n$U7zJ*cQbs5SDOFgpK%*OX5G#)TUg|YMc@kMfv#Pc2by(H7 z$yB)WpH|Y%-ugR=#CfrQ*0XZ$+Lom!jIvJ(tPn6}u@g&fDb)LbEgLVTrDxb>UQWj) z=GRHBaBN_+O7){zn-^+1EpR^h#NU5Q?3R8@IA*Q-J=kl$g;5NCaM+$4gomk2l9@dz zFW7-&VpNcxjfu=*3I=XMvNn`y!tGtkz7x%SoN6b?rC8Y^Sdy`!6yy|O!`6$tHqOeO zDPX64yG8z|NVol5C6@v4AAfEN@!f`j{6@70@#^BW`T zSC>1|DqZ2&<*l5yM94k6T1s|wC0^+D&M(Vuu}NdG9Jyt(ousvUHC`&<{IPN! zRyER=4C=@L(L=CTE>|g^!O_2oY~MxX?M&PtmOFPc*$4^Pbd1r**P_y^9qL z!Q_fh^oND&9fX=)42wWp!yJI%V+rO0D+1>EmdVPvwV54pm0XsZfdMg^p6 zRV&^5hgj7aB9`L`cFG%k_2P?H{5tTq1IX~d50%`UmYN_cfTi^Sc^N$v$)c4Ji1OxA zZE7}VTN^>z6^J+f4n6OsN?%ZZUQQCbrc;bCLtZ&-*~il&c~7Sp3m6d1$%s(|KklEG zHQFSeA8C2R<-PG$S?=B44kR{K|o$UP`km13S&XND-4IZr^SU{2Y0QRRH0=x(J* zX6a6t$kVAbvRGT)NtUBhD-x*V>O)Xjns$wBw2R29CYXZ2kgWp0lbGI^c=CNokdc1q z`gCjb^2KkSf%V(cjtd6SSrtd5%7bjO85GB-=Oz9cX&AI;!T~BpG#c^^`fvllC=7pB zLh?K{t(_fr6X}j14{I!}RmG5Vu-#ZBb!zo5UUX(2Rkt2$IptUN?m{41tLc??QCaL( zg_(OUlamJQ+QcE3mqM>K3h=CG305JvD<@wEkiu!Txj zuOHmO6mh!?Jj^d*&z z@)y_H1Yx9Al1X(Exj;Z>UFWgU)$LDFKK>YFVa_c$5Qy1HX(N`u`+1Rf#FBkOy#PUf z8m-gaTh}=oZC;Ki`ot0jdlnvV>6qHSg7Xh+BX|9zFu@u$q}tqDP*`#c;>3rky5<{3 ztS^nbS}Mt2xAfb1+?6O~QjwWZy=9T=a;yq*Lcr_~75b0i{K908So~j12^(4+ zG4$Hjmb0{Q84;T{}NG;D%qHUh{=0>yrDc>SzntFFgE-7uu|Wrr#&$?3uN z{-m>RKw^K>Pjduk*&iF%!2@`+oiClGTDrw7(cV;8;xhf!XK5l`mo>d9#~9SKe1d_u z0I=nwUEJy(x5eY*dU&p*j=ZiWGE)1|6Ilq+w2vinBaS8Y4%@P9DxDVawOh;##RZPG zPX7Q=IXW1y@t+I;wy)(kXQg8NP#=onsow;$wm5_*|fs z6b9x^$UTSzpL(n4N5COv+$C~PBg|U7U#7v&J%RV?)3H-CPAGy!9KUlO=S8nOG|~bC zvpkie?Xp4l?`3p^@?b8?byRc3U+ppf0B0gT{d+!wM!XwJ{{W>gx0fGh9UeOj4%D@D z&Tj41fX9cSJ*(4Hj>u`Dxb)b1dcO;(*)P#0z$ zhW)U8&$>VTJ27MB$YfASVDT16!J?%?7u-+ZJe%sgrH#l*Axn}aX(fzGT7z<`2;`Bf zx7$LZQm(;vN#d=bPq;{27bIHI$Yiw;ZqgDbl?m?Z!|)k^1Mpk1(btPpKc2%-s#>2< zQ2Qn#QxrDkfX7e zxGZcGa&Kn)5waJ>B)>;^j7_MiJU4X%Ls=3MXk8hdNhjv7<2@|i1+P*^ogFShg_M>C zsO@OM7m=F-`sLFVs(@=g1Cwut-5I4Q}lC`bWF-WMjqn0<- zb%9E!S%*XjZZ<*+${+u?~e zE;`SYb4AYW%>1b0zpiDB2qJfpN+YU%nPaCkntMhgD`hE@dOWwKVlvKdr^&OP|;)eu5FaY-_Xta2tApYq;S z?tP?xa5`YWIt1(E#x|=w+@iZA=v;#oOwt)pZrAaEySIe6jiqbtwxXBhjRywxf$YbT2 zN0pHoB#CkxF~`jEDhG8yJCWk7{Xg{#4xVR(>*EYsz=?v6EYTa!#s$_7G|Zj@ICO2I zV-el57FLmtIgGe!90sF*an`s00K?`bjCw`EUS>8EmS3HKWE^|!=nbFp2Y(rxq~=sM zB7($G+xbzlp?i*6C+D}w17rBtYpUm!T~A&at-VaOx|MZSNvTx3Vze_tc*h$W_GU#w zIRfQEjet*Z4k`S!>Y$J{>}}yDmPqTuwxxRUl_EJNf*ns9Ho-DD^wqelo@}~23*#D6 zu)dpD30GqqG!p=fXp@M@Ap2eWbz450RTRf|hGBJdgs>Q|MGc^LH=d}}>2p$bD=g9y zhC>5rf;PMDv+?i`azDoW6}OM81xLAAmbB!1;gfr3P*jxfzf=S5-o2&A=f$S|3vyJF zq^)Id$L_KA;H$55?cpY*8d5>!zUM^mUI$$1Ds`%vCdJPx#Dj{+3AEuGi^>7sfgl3k zJ9XBN#-#Bt6h?0_&A1vUBXzzhi6|>~_-dEmzf$}wl@fU_i<5gCo1sXuqk8mx?gnOC@D=<7?S zDg$eM^gA8+v2cAihP#kxEyH4(IB6Cs7Lh1=6WsmM%U<$(ZpyOo4pp+_(akg%OOCV4C*}OZ`l}6*P@H zjgD2h-9!QfURtsa1`iip^{)8nEJhwl1)(fqM&7wtT2>nol0T8jwXVT_PvntIwR=$) ziDec5ZbA-mK&(cXE`ba-Ksy^!-OtC1XDN(>nW!OVlFG9nRQ)MeT08;m>TH6)8eM>V zEw(Q^PU^vpSw7H50$BB;Ji<4)#x?lbf;ImDPRIFfKN^{3j1^dcr3?rrg;lDO54DFN z=RHD5B#Q;ijJ58@jT*)=&mPx(mGUcUh-nR!D=b>rV1>zL{UE3L1Cam#O6Y8!!fINc zV)3j-BLgodmHEde!PSS+06LIgu$lBzK}SBC4=3I1b~05&C4eF72Yc*QEMq97w$gp^ z_pi4kk#%r04642cBL|AkdC!7?PIbJx|(`jeaq%R^p!{9~_9{tGIbKk^? zVYM76VUc86E0&3&k4l79#M zPqse&4pgusE7zC@{EN#dZM>n7H0aNbdhE)~h+d&*)@%7X+1A@jEUd~MWEwQ2q zJ(ze~za8+~wPt7oFcZeCBR--30F+1?0C7^f8t>aj#fJti?Q3dCo6tz2F-sJ@>o8>} zi$)K(mbP2)I~{C~6BeZ@Y}PhvMLQPUv8xcWLK}QRCw%$wZ4LhbanRRvo-qrsYFZ=; zJAojK*aM%}wsVAMiByW-!iTAw7ea+_JMwdXa4H*u%2-!1O(11KI>P1TaCFHj1dta) z-K}kzLEp!TDwZqS5;J6FhROpVF_{u5#BMma@4-2g1>3*1cm6Hw70t[HY(kgreK9)b{m#PV)|jDpgC!Gt%f@TdeGQD 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 U%g4RhvxWI+#1uvU5Hyeg!G{K+I0qzc>Z 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

;T`0?0@jkITpwLK|M->l1os< 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∈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

_i{JzeO`lfapmsUFkz^iWRX}$R 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 I@7uTk*-tn)8~^|S From 76589cdee9f46972843dd66aea177829bf6b0e20 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 21:38:29 +0200 Subject: [PATCH 006/374] Create README.md --- .../object_detection_2d/nms/cluster_nms/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 projects/perception/object_detection_2d/nms/cluster_nms/README.md diff --git a/projects/perception/object_detection_2d/nms/cluster_nms/README.md b/projects/perception/object_detection_2d/nms/cluster_nms/README.md new file mode 100644 index 0000000000..bac575cab5 --- /dev/null +++ b/projects/perception/object_detection_2d/nms/cluster_nms/README.md @@ -0,0 +1,8 @@ +# Cluster-NMS Demos + +This folder contains minimal code usage examples that showcase the basic functionality of the Cluster-NMS module +provided by OpenDR. Specifically the following examples are provided: +1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. + +2. eval_demo.py: Perform evaluation on the `PETS` dataset, implemented in OpenDR format. + Setting `--device cpu` performs evaluation on CPU. From 03ab517778508992edc082662dbcb6bf204cd735 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 21:39:09 +0200 Subject: [PATCH 007/374] Create README.md --- .../perception/object_detection_2d/nms/fast_nms/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 projects/perception/object_detection_2d/nms/fast_nms/README.md diff --git a/projects/perception/object_detection_2d/nms/fast_nms/README.md b/projects/perception/object_detection_2d/nms/fast_nms/README.md new file mode 100644 index 0000000000..65b240c432 --- /dev/null +++ b/projects/perception/object_detection_2d/nms/fast_nms/README.md @@ -0,0 +1,8 @@ +# Fast-NMS Demos + +This folder contains minimal code usage examples that showcase the basic functionality of the Fast-NMS module +provided by OpenDR. Specifically the following examples are provided: +1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. + +2. eval_demo.py: Perform evaluation on the `PETS` dataset, implemented in OpenDR format. + Setting `--device cpu` performs evaluation on CPU. From 04d5eda91ec0d9252c6244123dfb987fdcd6dca9 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 21:40:52 +0200 Subject: [PATCH 008/374] Create README.md --- .../perception/object_detection_2d/nms/soft_nms/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 projects/perception/object_detection_2d/nms/soft_nms/README.md diff --git a/projects/perception/object_detection_2d/nms/soft_nms/README.md b/projects/perception/object_detection_2d/nms/soft_nms/README.md new file mode 100644 index 0000000000..0d1d3bd0ea --- /dev/null +++ b/projects/perception/object_detection_2d/nms/soft_nms/README.md @@ -0,0 +1,8 @@ +# Soft-NMS Demos + +This folder contains minimal code usage examples that showcase the basic functionality of the Soft-NMS implementation +provided by OpenDR. Specifically the following examples are provided: +1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. + +2. eval_demo.py: Perform evaluation on the `PETS` dataset, implemented in OpenDR format. + Setting `--device cpu` performs evaluation on CPU. From 37d9b0bdc704117ba98ee98dc73bc4389b917b02 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 21:41:16 +0200 Subject: [PATCH 009/374] Update README.md --- .../perception/object_detection_2d/nms/cluster_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/cluster_nms/README.md b/projects/perception/object_detection_2d/nms/cluster_nms/README.md index bac575cab5..baefd8e7b3 100644 --- a/projects/perception/object_detection_2d/nms/cluster_nms/README.md +++ b/projects/perception/object_detection_2d/nms/cluster_nms/README.md @@ -1,6 +1,6 @@ # Cluster-NMS Demos -This folder contains minimal code usage examples that showcase the basic functionality of the Cluster-NMS module +This folder contains minimal code usage examples that showcase the basic functionality of the Cluster-NMS implementation provided by OpenDR. Specifically the following examples are provided: 1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. From 3ad15033c50712cf6b054007ad212d866af659c9 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 21:41:40 +0200 Subject: [PATCH 010/374] Update README.md --- projects/perception/object_detection_2d/nms/fast_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/fast_nms/README.md b/projects/perception/object_detection_2d/nms/fast_nms/README.md index 65b240c432..08541d321e 100644 --- a/projects/perception/object_detection_2d/nms/fast_nms/README.md +++ b/projects/perception/object_detection_2d/nms/fast_nms/README.md @@ -1,6 +1,6 @@ # Fast-NMS Demos -This folder contains minimal code usage examples that showcase the basic functionality of the Fast-NMS module +This folder contains minimal code usage examples that showcase the basic functionality of the Fast-NMS implementation provided by OpenDR. Specifically the following examples are provided: 1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. From 9daa543318b2f6c736caa1294b2a83bef20049c4 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 21:48:23 +0200 Subject: [PATCH 011/374] Add files via upload --- .../nms/fast_nms/fast_nms.py | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py diff --git a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py new file mode 100644 index 0000000000..4c82488afe --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py @@ -0,0 +1,118 @@ +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard +from opendr.engine.target import BoundingBox, BoundingBoxList +import torch +import numpy as np + + +class FastNMS(NMSCustom): + def __init__(self, cross_class=False, device='cuda', iou_thres=0.45, top_k=400, post_k=100): + self.device = device + self.iou_thres = iou_thres + self.top_k = top_k + self.post_k = post_k + self.cross_class = cross_class + + def set_iou_thres(self, iou_thres=0.45): + self.iou_thres = iou_thres + + def top_k(self, top_k=400): + self.top_k = top_k + + def post_k(self, post_k=100): + self.post_k = post_k + + def set_cross_class(self, cross_class=False): + self.cross_class = cross_class + + def run_nms(self, boxes=None, scores=None, threshold=0.2, img=None): + + if isinstance(boxes, np.ndarray): + boxes = torch.tensor(boxes, device=self.device) + elif torch.is_tensor(boxes): + if self.device == 'cpu': + boxes = boxes.cpu() + elif self.device == 'cuda': + boxes = boxes.cuda() + + if isinstance(scores, np.ndarray): + scores = torch.tensor(scores, device=self.device) + elif torch.is_tensor(scores): + if self.device == 'cpu': + scores = scores.cpu() + elif self.device == 'cuda': + scores = scores.cuda() + + scores = torch.transpose(scores, dim0=1, dim1=0) + if self.cross_class: + [boxes, classes, scores] = cc_fast_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + top_k=self.top_k, post_k=self.post_k) + else: + [boxes, classes, scores] = fast_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + top_k=self.top_k, post_k=self.post_k) + + keep_ids = torch.where(scores > threshold) + scores = scores[keep_ids].cpu().numpy() + classes = classes[keep_ids].cpu().numpy() + boxes = boxes[keep_ids].cpu().numpy() + bounding_boxes = BoundingBoxList([]) + for idx, box in enumerate(boxes): + bbox = BoundingBox(left=box[0], top=box[1], + width=box[2] - box[0], + height=box[3] - box[1], + name=classes[idx], + score=scores[idx]) + bounding_boxes.data.append(bbox) + + return bounding_boxes, [boxes, classes, scores] + + +def fast_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + scores, idx = scores.sort(1, descending=True) + boxes = boxes[idx, :] + + scores = scores[:, :top_k] + boxes = boxes[:, :top_k] + + num_classes, num_dets = scores.shape + + boxes = boxes.view(num_classes, num_dets, 4) + + iou = jaccard(boxes, boxes).triu_(diagonal=1) + iou_max, _ = iou.max(dim=1) + + keep = (iou_max <= iou_thres) + keep *= (scores > 0.01) + classes = torch.arange(num_classes, device=boxes.device)[:, None].expand_as(keep) + classes = classes[keep] + + boxes = boxes[keep] + scores = scores[keep] + + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + + classes = classes[idx] + boxes = boxes[idx] + return boxes, classes, scores + + +def cc_fast_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + scores, classes = scores.max(dim=0) + _, idx = scores.sort(0, descending=True) + idx = idx[:top_k] + boxes = boxes[idx] + scores = scores[idx] + classes = classes[idx] + iou = jaccard(boxes, boxes).triu_(diagonal=1) + maxA, _ = torch.max(iou, dim=0) + + idx_out = torch.where(maxA > iou_thres) + scores[idx_out] = 0 + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + classes = classes[idx] + boxes = boxes[idx] + return boxes, classes, scores From 38b941436d394c84b2f1b7483435048d6c1cf05b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 21:49:48 +0200 Subject: [PATCH 012/374] Add files via upload --- .../nms/cluster_nms/cluster_nms.py | 469 ++++++++++++++++++ .../nms/soft_nms/soft_nms.py | 200 ++++++++ .../nms/utils/nms_custom.py | 7 + 3 files changed, 676 insertions(+) create mode 100644 src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py create mode 100644 src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py create mode 100644 src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py new file mode 100644 index 0000000000..18c7e61c94 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -0,0 +1,469 @@ +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard, diou, distance +from opendr.engine.target import BoundingBox, BoundingBoxList +import numpy as np +import torch + + +class ClusterNMS(NMSCustom): + def __init__(self, nms_type='default', cross_class=True, device='cuda', iou_thres=0.45, top_k=400, post_k=100): + self.device = device + self.nms_types = ['default', 'diou', 'spm', 'spm_dist', 'spm_dist_weighted'] + if nms_type not in self.nms_types: + raise ValueError('Type: ' + nms_type + ' of Cluster-NMS is not supported.') + else: + self.nms_type = nms_type + self.iou_thres = iou_thres + self.top_k = top_k + self.post_k = post_k + self.cross_class = cross_class + + def set_iou_thres(self, iou_thres=0.45): + self.iou_thres = iou_thres + + def top_k(self, top_k=400): + self.top_k = top_k + + def post_k(self, post_k=100): + self.post_k = post_k + + def set_type(self, nms_type=None): + if nms_type not in self.nms_types: + raise ValueError('Type: ' + nms_type + ' of Cluster-NMS is not supported.') + else: + self.nms_type = nms_type + + def set_cross_class(self, cross_class=True): + self.cross_class = cross_class + + def run_nms(self, boxes=None, scores=None, img=None, threshold=0.2): + + if isinstance(boxes, np.ndarray): + boxes = torch.tensor(boxes, device=self.device) + elif torch.is_tensor(boxes): + if self.device == 'cpu': + boxes = boxes.cpu() + elif self.device == 'cuda': + boxes = boxes.cuda() + + if isinstance(scores, np.ndarray): + scores = torch.tensor(scores, device=self.device) + elif torch.is_tensor(scores): + if self.device == 'cpu': + scores = scores.cpu() + elif self.device == 'cuda': + scores = scores.cuda() + + scores = torch.transpose(scores, dim0=1, dim1=0) + + if self.nms_type == 'default': + if self.cross_class: + [boxes, classes, scores] = cc_cluster_nms_default(boxes=boxes, scores=scores, iou_thres=self.iou_thres, top_k=self.top_k, post_k=self.post_k) + else: + [boxes, classes, scores] = cluster_nms_default(boxes=boxes, scores=scores, iou_thres=self.iou_thres, top_k=self.top_k, post_k=self.post_k) + elif self.nms_type == 'diou': + if self.cross_class: + [boxes, classes, scores] = cc_cluster_diounms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + top_k=self.top_k, post_k=self.post_k) + else: + [boxes, classes, scores] = cluster_diounms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, post_k=self.post_k) + elif self.nms_type == 'spm': + if self.cross_class: + [boxes, classes, scores] = cc_cluster_SPM_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + post_k=self.post_k) + else: + [boxes, classes, scores] = cluster_SPM_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, post_k=self.post_k) + elif self.nms_type == 'spm_dist': + if self.cross_class: + [boxes, classes, scores] = cc_cluster_SPM_dist_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, post_k=self.post_k) + else: + [boxes, classes, scores] = cluster_SPM_dist_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, post_k=self.post_k) + + elif self.nms_type == 'spm_dist_weighted': + if self.cross_class: + [boxes, classes, scores] = cc_cluster_SPM_dist_weighted_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, post_k=self.post_k) + else: + [boxes, classes, scores] = cluster_SPM_dist_weighted_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, post_k=self.post_k) + + keep_ids = torch.where(scores>threshold) + scores = scores[keep_ids].cpu().numpy() + classes = classes[keep_ids].cpu().numpy() + boxes = boxes[keep_ids].cpu().numpy() + bounding_boxes = BoundingBoxList([]) + for idx, box in enumerate(boxes): + bbox = BoundingBox(left=box[0], top=box[1], + width=box[2] - box[0], + height=box[3] - box[1], + name=classes[idx], + score=scores[idx]) + bounding_boxes.data.append(bbox) + + return bounding_boxes, [boxes, classes, scores] + + +def cc_cluster_nms_default(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + # Collapse all the classes into 1 + + scores, classes = scores.max(dim=0) + _, idx = scores.sort(0, descending=True) + idx = idx[:top_k] + boxes = boxes[idx] + scores = scores[idx] + classes = classes[idx] + iou = jaccard(boxes, boxes).triu_(diagonal=1) + B = iou + for i in range(200): + A=B + maxA,_=torch.max(A, dim=0) + E = (maxA<=iou_thres).float().unsqueeze(1).expand_as(A) + B=iou.mul(E) + if A.equal(B)==True: + break + + idx_out = torch.where(maxA > iou_thres) + scores[idx_out] = 0 + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + classes = classes[idx] + boxes = boxes[idx] + return boxes, classes, scores + + + +def cluster_nms_default(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + + scores, idx = scores.sort(1, descending=True) + idx = idx[:top_k] + scores = scores[:top_k] + boxes = boxes[idx, :] + + num_classes, num_dets = scores.shape + boxes = boxes.view(num_classes, num_dets, 4) + _, classes = scores.max(dim=0) + iou = jaccard(boxes, boxes).triu_(diagonal=1) + B = iou + maxA = None + for i in range(200): + A = B + maxA, _ = A.max(dim=1) + E = (maxA <= iou_thres).float().unsqueeze(2).expand_as(A) + B = iou.mul(E) + if A.equal(B): + break + keep = (scores > 0.00) + discard = (maxA > iou_thres) + scores[discard] = 0 + # Assign each kept detection to its corresponding class + boxes = boxes[keep] + scores = scores[keep] + + # Only keep the top cfg.max_num_detections highest scores across all classes + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + classes = classes[idx] + boxes = boxes[idx] + return boxes, classes, scores + + +def cc_cluster_diounms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + # Collapse all the classes into 1 + + scores, classes = scores.max(dim=0) + _, idx = scores.sort(0, descending=True) + idx = idx[:top_k] + boxes = boxes[idx] + scores = scores[idx] + classes = classes[idx] + iou = diou(boxes, boxes).triu_(diagonal=1) + B = iou + for i in range(200): + A = B + maxA, _ = torch.max(A, dim=0) + E = (maxA <= iou_thres).float().unsqueeze(1).expand_as(A) + B = iou.mul(E) + if A.equal(B) == True: + break + + idx_out = torch.where(maxA > iou_thres) + scores[idx_out] = 0 + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + classes = classes[idx] + boxes = boxes[idx] + return boxes, classes, scores + + +def cluster_diounms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + + scores, idx = scores.sort(1, descending=True) + idx = idx[:top_k] + scores = scores[:top_k] + boxes = boxes[idx, :] + + num_classes, num_dets = scores.shape + boxes = boxes.view(num_classes, num_dets, 4) + _, classes = scores.max(dim=0) + + iou = diou(boxes, boxes).triu_(diagonal=1) + B = iou + maxA = None + for i in range(200): + A = B + maxA, _ = A.max(dim=1) + E = (maxA <= iou_thres).float().unsqueeze(2).expand_as(A) + B = iou.mul(E) + if A.equal(B): + break + keep = (scores > 0.00) + discard = (maxA > iou_thres) + scores[discard] = 0 + # Assign each kept detection to its corresponding class + boxes = boxes[keep] + scores = scores[keep] + + # Only keep the top cfg.max_num_detections highest scores across all classes + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + classes = classes[idx] + boxes = boxes[idx] + + return boxes, classes, scores + + +def cc_cluster_SPM_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + + scores, classes = scores.max(dim=0) + _, idx = scores.sort(0, descending=True) + idx = idx[:top_k] + boxes = boxes[idx] + scores = scores[idx] + classes = classes[idx] + iou = jaccard(boxes, boxes).triu_(diagonal=1) + B = iou + for i in range(200): + A = B + maxA, _ = torch.max(A, dim=0) + E = (maxA <= iou_thres).float().unsqueeze(1).expand_as(A) + B = iou.mul(E) + if A.equal(B) == True: + break + scores = torch.prod(torch.exp(-B ** 2 / 0.2), 0) * scores + + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + classes = classes[idx] + boxes = boxes[idx] + return boxes, classes, scores + +def cluster_SPM_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + + scores, idx = scores.sort(1, descending=True) + idx = idx[:top_k] + scores = scores[:top_k] + boxes = boxes[idx, :] + + num_classes, num_dets = scores.shape + boxes = boxes.view(num_classes, num_dets, 4) + _, classes = scores.max(dim=0) + + iou = jaccard(boxes, boxes).triu_(diagonal=1) + B = iou + for i in range(200): + A = B + maxA, _ = A.max(dim=1) + E = (maxA <= iou_thres).float().unsqueeze(2).expand_as(A) + B = iou.mul(E) + if A.equal(B): + break + keep = (scores > 0.00) + scores = torch.prod(torch.exp(-B ** 2 / 0.2), 1) * scores + # Assign each kept detection to its corresponding class + boxes = boxes[keep] + scores = scores[keep] + + # Only keep the top cfg.max_num_detections highest scores across all classes + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + classes = classes[idx] + boxes = boxes[idx] + return boxes, classes, scores + +def cc_cluster_SPM_dist_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + + scores, classes = scores.max(dim=0) + _, idx = scores.sort(0, descending=True) + idx = idx[:top_k] + boxes = boxes[idx] + scores = scores[idx] + classes = classes[idx] + iou = jaccard(boxes, boxes).triu_(diagonal=1) + B = iou + for i in range(200): + A = B + maxA, _ = torch.max(A, dim=0) + E = (maxA <= iou_thres).float().unsqueeze(1).expand_as(A) + B = iou.mul(E) + if A.equal(B) == True: + break + D = distance(boxes, boxes) + X = (B >= 0).float() + scores = torch.prod(torch.min(torch.exp(-B ** 2 / 0.2) + D * ((B > 0).float()), X), 0) * scores + + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + classes = classes[idx] + boxes = boxes[idx] + return boxes, classes, scores + + +def cluster_SPM_dist_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + + scores, idx = scores.sort(1, descending=True) + idx = idx[:top_k] + scores = scores[:top_k] + boxes = boxes[idx, :] + + num_classes, num_dets = scores.shape + boxes = boxes.view(num_classes, num_dets, 4) + _, classes = scores.max(dim=0) + + iou = jaccard(boxes, boxes).triu_(diagonal=1) + B = iou + for i in range(200): + A = B + maxA, _ = A.max(dim=1) + E = (maxA <= iou_thres).float().unsqueeze(2).expand_as(A) + B = iou.mul(E) + if A.equal(B): + break + D = distance(boxes, boxes) + X = (B >= 0).float() + keep = (scores > 0.00) + scores = torch.prod(torch.min(torch.exp(-B ** 2 / 0.2) + D * ((B > 0).float()), X), 1) * scores + + # Assign each kept detection to its corresponding class + boxes = boxes[keep] + scores = scores[keep] + + # Only keep the top cfg.max_num_detections highest scores across all classes + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + classes = classes[idx] + boxes = boxes[idx] + + return boxes, classes, scores + +def cc_cluster_SPM_dist_weighted_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + + scores, classes = scores.max(dim=0) + _, idx = scores.sort(0, descending=True) + idx = idx[:top_k] + boxes = boxes[idx] + scores = scores[idx] + classes = classes[idx] + n = len(scores) + iou = jaccard(boxes, boxes).triu_(diagonal=1) + B = iou + for i in range(200): + A = B + maxA, _ = torch.max(A, dim=0) + E = (maxA <= iou_thres).float().unsqueeze(1).expand_as(A) + B = iou.mul(E) + if A.equal(B) == True: + break + D = distance(boxes, boxes) + X = (B >= 0).float() + scores = torch.prod(torch.min(torch.exp(-B ** 2 / 0.2) + D * ((B > 0).float()), X), 0) * scores + eye = torch.eye(n) + if boxes.device.type == 'cuda': + eye = eye.cuda() + weights = (B * (B > 0.8).float() + eye) * (scores.reshape((1, n))) + xx1 = boxes[:, 0].expand(n, n) + yy1 = boxes[:, 1].expand(n, n) + xx2 = boxes[:, 2].expand(n, n) + yy2 = boxes[:, 3].expand(n, n) + + weightsum = weights.sum(dim=1) + xx1 = (xx1 * weights).sum(dim=1) / (weightsum) + yy1 = (yy1 * weights).sum(dim=1) / (weightsum) + xx2 = (xx2 * weights).sum(dim=1) / (weightsum) + yy2 = (yy2 * weights).sum(dim=1) / (weightsum) + boxes = torch.stack([xx1, yy1, xx2, yy2], 1) + + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + classes = classes[idx] + boxes = boxes[idx] + return boxes, classes, scores + + +def cluster_SPM_dist_weighted_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + + scores, idx = scores.sort(1, descending=True) + idx = idx[:top_k] + scores = scores[:top_k] + boxes = boxes[idx, :] + + num_classes, num_dets = scores.shape + boxes = boxes.view(num_classes, num_dets, 4) + _, classes = scores.max(dim=0) + + iou = jaccard(boxes, boxes).triu_(diagonal=1) + B = iou + A = None + for i in range(200): + A = B + maxA, _ = A.max(dim=1) + E = (maxA <= iou_thres).float().unsqueeze(2).expand_as(A) + B = iou.mul(E) + if A.equal(B): + break + D = distance(boxes, boxes) + X = (B >= 0).float() + keep = (scores > 0.0) + + scores = torch.prod(torch.min(torch.exp(-B ** 2 / 0.2) + D * ((B > 0).float()), X), 1) * scores + + E = keep.float().unsqueeze(2).expand_as(A) + B = iou.mul(E) + _, n = scores.size() + eye = torch.eye(n).expand(num_classes, n, n) + if boxes.device.type == 'cuda': + eye = eye.cuda() + weights = (B * (B > 0.8).float() + eye) * ( + scores.unsqueeze(2).expand(num_classes, n, n)) + xx1 = boxes[:, :, 0].unsqueeze(1).expand(num_classes, n, n) + yy1 = boxes[:, :, 1].unsqueeze(1).expand(num_classes, n, n) + xx2 = boxes[:, :, 2].unsqueeze(1).expand(num_classes, n, n) + yy2 = boxes[:, :, 3].unsqueeze(1).expand(num_classes, n, n) + + weightsum = weights.sum(dim=2) + xx1 = (xx1 * weights).sum(dim=2) / (weightsum) + yy1 = (yy1 * weights).sum(dim=2) / (weightsum) + xx2 = (xx2 * weights).sum(dim=2) / (weightsum) + yy2 = (yy2 * weights).sum(dim=2) / (weightsum) + boxes = torch.stack([xx1, yy1, xx2, yy2], 2) + + # Assign each kept detection to its corresponding class + classes = torch.arange(num_classes, device=boxes.device)[:, None].expand_as(keep) + classes = classes[keep] + boxes = boxes[keep] + scores = scores[keep] + + # Only keep the top cfg.max_num_detections highest scores across all classes + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + classes = classes[idx] + boxes = boxes[idx] + + return boxes, classes, scores diff --git a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py new file mode 100644 index 0000000000..eef3a94673 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py @@ -0,0 +1,200 @@ +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard +from opendr.engine.target import BoundingBox, BoundingBoxList +import torch +import numpy as np + + +class SoftNMS(NMSCustom): + def __init__(self, nms_type= 'linear', device='cuda', nms_thres=None, top_k=400, post_k=100): + self.nms_types = ['linear', 'gaussian'] + if nms_type not in self.nms_types: + raise ValueError('Type: ' + nms_type + ' of Soft-NMS is not supported.') + else: + self.nms_type = nms_type + if nms_thres is None: + if nms_type == 'linear': + nms_thres = 0.3 + elif nms_type == 'gaussian': + nms_thres = 0.5 + self.device = device + self.nms_thres = nms_thres + self.top_k = top_k + self.post_k = post_k + + def nms_thres(self, nms_thres=0.45): + self.nms_thres = nms_thres + + def set_top_k(self, top_k=400): + self.top_k = top_k + + def set_post_k(self, post_k=100): + self.post_k = post_k + + def set_nms_type(self, nms_type='linear'): + if nms_type not in self.nms_types: + raise ValueError('Type: ' + nms_type + ' of Soft-NMS is not supported.') + else: + self.nms_type = nms_type + + def run_nms(self, boxes=None, scores=None, threshold=0.2, img=None): + + if isinstance(boxes, np.ndarray): + boxes = torch.tensor(boxes, device=self.device) + elif torch.is_tensor(boxes): + if self.device == 'cpu': + boxes = boxes.cpu() + elif self.device == 'cuda': + boxes = boxes.cuda() + + if isinstance(scores, np.ndarray): + scores = torch.tensor(scores, device=self.device) + elif torch.is_tensor(scores): + if self.device == 'cpu': + scores = scores.cpu() + elif self.device == 'cuda': + scores = scores.cuda() + + scores, classes = scores.max(dim=1) + _, idx = scores.sort(0, descending=True) + idx = idx[:self.top_k] + boxes = boxes[idx] + scores = scores[idx] + classes = classes[idx] + + dets = torch.cat((boxes, scores.unsqueeze(-1)), dim=1) + + retained_box = [] + i=0 + while dets.shape[0] > 0: + max_idx = np.argmax(dets[:, 4], axis=0) + #dets[[0, max_idx], :] = dets[[max_idx, 0], :] + scores[i] = dets[0, 4] + + iou = jaccard(dets[:1,:-1], dets[1:,:-1]).triu_(diagonal=0).squeeze(0) + + weight = torch.ones_like(iou) + if self.nms_type == 'linear': + weight[iou > self.nms_thres] -= iou[iou > self.nms_thres] + elif self.nms_type == 'gaussian': + weight = np.exp(-(iou * iou) / self.nms_thres) + + dets[1:, 4] *= weight + #retained_idx = torch.where(dets[1:, 4] >= 0)[0] + dets = dets[1:, :] + i = i + 1 + keep_ids = torch.where(scores > threshold) + scores = scores[keep_ids].cpu().numpy() + classes = classes[keep_ids].cpu().numpy() + boxes = boxes[keep_ids].cpu().numpy() + bounding_boxes = BoundingBoxList([]) + for idx, box in enumerate(boxes): + bbox = BoundingBox(left=box[0], top=box[1], + width=box[2] - box[0], + height=box[3] - box[1], + name=classes[idx], + score=scores[idx]) + bounding_boxes.data.append(bbox) + + return bounding_boxes, [boxes, classes, scores] + + +def fast_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + scores, idx = scores.sort(1, descending=True) + boxes = boxes[idx, :] + + scores = scores[:, :top_k] + boxes = boxes[:, :top_k] + + num_classes, num_dets = scores.shape + + boxes = boxes.view(num_classes, num_dets, 4) + + iou = jaccard(boxes, boxes).triu_(diagonal=1) + iou_max, _ = iou.max(dim=1) + + keep = (iou_max <= iou_thres) + keep *= (scores > 0.01) + classes = torch.arange(num_classes, device=boxes.device)[:, None].expand_as(keep) + classes = classes[keep] + + boxes = boxes[keep] + scores = scores[keep] + + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + + classes = classes[idx] + boxes = boxes[idx] + return boxes, classes, scores + + +def cc_fast_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): + scores, classes = scores.max(dim=0) + _, idx = scores.sort(0, descending=True) + idx = idx[:top_k] + boxes = boxes[idx] + scores = scores[idx] + classes = classes[idx] + iou = jaccard(boxes, boxes).triu_(diagonal=1) + maxA, _ = torch.max(iou, dim=0) + + idx_out = torch.where(maxA > iou_thres) + scores[idx_out] = 0 + scores, idx = scores.sort(0, descending=True) + idx = idx[:post_k] + scores = scores[:post_k] + classes = classes[idx] + boxes = boxes[idx] + return boxes, classes, scores + + + + + +def py_soft_nms(dets, method='linear', iou_thr=0.3, sigma=0.5, score_thr=0.001): + + if method not in ('linear', 'gaussian', 'greedy'): + raise ValueError('method must be linear, gaussian or greedy') + + x1 = dets[:, 0] + y1 = dets[:, 1] + x2 = dets[:, 2] + y2 = dets[:, 3] + + areas = (x2 - x1 + 1) * (y2 - y1 + 1) + # expand dets with areas, and the second dimension is + # x1, y1, x2, y2, score, area + dets = np.concatenate((dets, areas[:, None]), axis=1) + + retained_box = [] + while dets.size > 0: + max_idx = np.argmax(dets[:, 4], axis=0) + dets[[0, max_idx], :] = dets[[max_idx, 0], :] + retained_box.append(dets[0, :-1]) + + xx1 = np.maximum(dets[0, 0], dets[1:, 0]) + yy1 = np.maximum(dets[0, 1], dets[1:, 1]) + xx2 = np.minimum(dets[0, 2], dets[1:, 2]) + yy2 = np.minimum(dets[0, 3], dets[1:, 3]) + + w = np.maximum(xx2 - xx1 + 1, 0.0) + h = np.maximum(yy2 - yy1 + 1, 0.0) + inter = w * h + iou = inter / (dets[0, 5] + dets[1:, 5] - inter) + + if method == 'linear': + weight = np.ones_like(iou) + weight[iou > iou_thr] -= iou[iou > iou_thr] + elif method == 'gaussian': + weight = np.exp(-(iou * iou) / sigma) + else: # traditional nms + weight = np.ones_like(iou) + weight[iou > iou_thr] = 0 + + dets[1:, 4] *= weight + retained_idx = np.where(dets[1:, 4] >= score_thr)[0] + dets = dets[retained_idx + 1, :] + + return np.vstack(retained_box) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py new file mode 100644 index 0000000000..a959c4ce80 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py @@ -0,0 +1,7 @@ +from abc import ABC, abstractmethod + + +class NMSCustom(ABC): + @abstractmethod + def run_nms(self, boxes=None, scores=None, threshold=0.2, img=None): + pass From ea29a420e14978218b4fb78fbef19087e3706880 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 21:50:34 +0200 Subject: [PATCH 013/374] Add files via upload --- .../object_detection_2d/ssd/ssd_learner.py | 60 +++++++++++-------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py index bab1edb2cb..ec5edd7c32 100644 --- a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py +++ b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 OpenDR European Project +# Copyright 2020-2021 OpenDR European Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -43,10 +43,13 @@ # algorithm imports from opendr.perception.object_detection_2d.utils.eval_utils import DetectionDatasetCOCOEval from opendr.perception.object_detection_2d.datasets import DetectionDataset -from opendr.perception.object_detection_2d.datasets.transforms import ImageToNDArrayTransform, BoundingBoxListToNumpyArray, \ - transform_test -import torch +from opendr.perception.object_detection_2d.datasets.transforms import ImageToNDArrayTransform, \ + BoundingBoxListToNumpyArray, \ + transform_test, pad_test +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom + gutils.random.seed(0) +import datetime class SingleShotDetectorLearner(Learner): @@ -87,7 +90,6 @@ def __init__(self, lr=1e-3, epochs=120, batch_size=8, self.ctx = mx.gpu(0) else: self.ctx = mx.cpu() - print("Device set to cuda but no GPU available, using CPU...") else: self.ctx = mx.cpu() @@ -138,7 +140,7 @@ def save(self, path, verbose=False): if verbose: print("Model parameters saved.") - with open(os.path.join(path, model_name + '.json'), 'w', encoding='utf-8') as f: + with open(os.path.join(path, model_name + '.json'), 'w', encoding='utf-8') as f: json.dump(metadata, f, ensure_ascii=False, indent=4) if verbose: print("Model metadata saved.") @@ -213,7 +215,7 @@ def download(self, path=None, mode="pretrained", verbose=False, if verbose: print("Downloading params...") file_url = os.path.join(url, "pretrained", "ssd_512_vgg16_atrous_wider_person", - "ssd_512_vgg16_atrous_wider_person.params") + "ssd_512_vgg16_atrous_wider_person.params") urlretrieve(file_url, os.path.join(path, "ssd_512_vgg16_atrous_wider_person.params")) @@ -540,7 +542,7 @@ def eval(self, dataset, use_subset=False, subset_size=100, verbose=False): eval_dict = {k.lower(): v for k, v in zip(map_name, mean_ap)} return eval_dict - def infer(self, img, threshold=0.2, keep_size=False, custom_nms=None): + def infer(self, img, threshold=0.2, keep_size=False, custom_nms:NMSCustom=None, nms_thresh=0.45, nms_topk=400, post_nms=100): """ Performs inference on a single image and returns the resulting bounding boxes. :param img: image to perform inference on @@ -552,13 +554,13 @@ def infer(self, img, threshold=0.2, keep_size=False, custom_nms=None): :return: list of bounding boxes :rtype: BoundingBoxList """ + assert self._model is not None, "Model has not been loaded, call load(path) first" - if custom_nms is not None: - self._model.set_nms(nms_thresh=0.0, nms_topk=1200) + if custom_nms: + self._model.set_nms(nms_thresh=0.85, nms_topk=5000, post_nms=1000) else: - self._model.set_nms(nms_thresh=0.45, nms_topk=400) - + self._model.set_nms(nms_thresh=nms_thresh, nms_topk=nms_topk, post_nms=post_nms) if not isinstance(img, Image): img = Image(img) _img = img.convert("channels_last", "rgb") @@ -570,37 +572,43 @@ def infer(self, img, threshold=0.2, keep_size=False, custom_nms=None): x, img_mx = transform_test(img_mx) else: x, img_mx = presets.ssd.transform_test(img_mx, short=self.img_size) - h_mx, w_mx, _ = img_mx.shape + x = pad_test(x, min_size=self.img_size) x = x.as_in_context(self.ctx) class_IDs, scores, boxes = self._model(x) class_IDs = class_IDs[0, :, 0].asnumpy() scores = scores[0, :, 0].asnumpy() - mask = np.where((class_IDs >= 0) & (scores > threshold))[0] + mask = np.where(class_IDs >= 0)[0] + if custom_nms is None: + mask = np.intersect1d(mask, np.where(scores > threshold)[0]) if mask.size == 0: return BoundingBoxList([]) scores = scores[mask, np.newaxis] class_IDs = class_IDs[mask, np.newaxis] boxes = boxes[0, mask, :].asnumpy() + if x.shape[2] > h_mx: + boxes[:, [1, 3]] -= (x.shape[2] - h_mx) + elif x.shape[3] > w_mx: + boxes[:, [0, 2]] -= (x.shape[3] - w_mx) boxes[:, [0, 2]] /= w_mx boxes[:, [1, 3]] /= h_mx boxes[:, [0, 2]] *= width boxes[:, [1, 3]] *= height - # bounding_boxes = BoundingBoxList([]) - # for idx, box in enumerate(boxes): - # bbox = BoundingBox(left=box[0], top=box[1], - # width=box[2] - box[0], - # height=box[3] - box[1], - # name=class_IDs[idx, :], - # score=scores[idx, :]) - # bounding_boxes.data.append(bbox) - if custom_nms: - bounding_boxes = np.concatenate([boxes, scores], axis=1) - bounding_boxes = [torch.tensor(bounding_boxes, device=self.device)] # List based on class index - custom_nms.run_nms(bounding_boxes) + if custom_nms is not None: + bounding_boxes, _ = custom_nms.run_nms(boxes=boxes, scores=scores, threshold=threshold, img=_img) + else: + bounding_boxes = BoundingBoxList([]) + for idx, box in enumerate(boxes): + bbox = BoundingBox(left=box[0], top=box[1], + width=box[2] - box[0], + height=box[3] - box[1], + name=class_IDs[idx, :], + score=scores[idx, :]) + bounding_boxes.data.append(bbox) + return bounding_boxes @staticmethod From a3faca54b10cc8645649ab720ad65faf5a41f00a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 21:52:14 +0200 Subject: [PATCH 014/374] Add files via upload --- .../datasets/transforms.py | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/datasets/transforms.py b/src/opendr/perception/object_detection_2d/datasets/transforms.py index 5aa6f1e327..17d8db3387 100644 --- a/src/opendr/perception/object_detection_2d/datasets/transforms.py +++ b/src/opendr/perception/object_detection_2d/datasets/transforms.py @@ -1,4 +1,4 @@ -# Copyright 2020-2022 OpenDR European Project +# Copyright 2020-2021 OpenDR European Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -141,3 +141,21 @@ def transform_test(imgs, mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)): if len(tensors) == 1: return tensors[0], origs[0] return tensors, origs + +def pad_test(img, min_size=512): + h_pad_size = 0 + pad_dim = 0 + min_dim = 2 + np.argmin([img.shape[2:4]]) + img_padded = img + if img.shape[min_dim] < min_size: + pad_dim = min_dim + h_pad_size = int((min_size - img.shape[min_dim]) / 2.0) + if min_dim == 2: + img_padded = mx.nd.pad(img, mode="constant", constant_value=0, + pad_width=(0, 0, 0, 0, h_pad_size, h_pad_size, 0, 0)) + # img_mx = np.pad(img_mx, ((h_pad_size, h_pad_size), (0, 0), (0, 0))) + else: + img_padded = mx.nd.pad(img, mode="constant", constant_value=0, + pad_width=(0, 0, 0, 0, 0, 0, h_pad_size, h_pad_size)) + # img_mx = np.pad(img_mx, ((0, 0), (h_pad_size, h_pad_size), (0, 0))) + return img_padded \ No newline at end of file From a8914ac7c57400f65d499abebe35942bc919a2e8 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 22:00:26 +0200 Subject: [PATCH 015/374] Update inference_demo.py --- .../object_detection_2d/nms/cluster_nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py index b5ab597beb..444e3dbcbc 100644 --- a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py @@ -15,4 +15,4 @@ start_time = datetime.datetime.now() cluster_nms = ClusterNMS(device='cuda', nms_type='default', cross_class=True) boxes = ssd.infer(img, threshold=0.3, custom_nms=cluster_nms) -draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) \ No newline at end of file +draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) From 5d1bdc6fdb3ac864c31a41ca0733b765459a9f54 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 22:00:51 +0200 Subject: [PATCH 016/374] Update inference_demo.py --- .../object_detection_2d/nms/fast_nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py index 8527647c84..bb3fbab626 100644 --- a/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py @@ -13,4 +13,4 @@ img = Image(img) cluster_nms = FastNMS(device='cpu', cross_class=True) boxes = ssd.infer(img, threshold=0.3, custom_nms=cluster_nms) -draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) \ No newline at end of file +draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) From 77b3c0ff6e8693d4785c0b4951ca52237069da31 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 22:01:07 +0200 Subject: [PATCH 017/374] Update inference_demo.py --- .../object_detection_2d/nms/soft_nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py index 25265d3db3..affe47f233 100644 --- a/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py @@ -13,4 +13,4 @@ img = Image(img) cluster_nms = SoftNMS(device='cpu', nms_type='gaussian') boxes = ssd.infer(img, threshold=0.3, custom_nms=cluster_nms) -draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) \ No newline at end of file +draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) From 3671a33ff217d91a8d7af758c894a95b705a9fc8 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 22:08:24 +0200 Subject: [PATCH 018/374] Update cluster_nms.py --- .../nms/cluster_nms/cluster_nms.py | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index 18c7e61c94..9cd491c8c7 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -58,32 +58,40 @@ def run_nms(self, boxes=None, scores=None, img=None, threshold=0.2): if self.nms_type == 'default': if self.cross_class: - [boxes, classes, scores] = cc_cluster_nms_default(boxes=boxes, scores=scores, iou_thres=self.iou_thres, top_k=self.top_k, post_k=self.post_k) + [boxes, classes, scores] = cc_cluster_nms_default(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + top_k=self.top_k, post_k=self.post_k) else: - [boxes, classes, scores] = cluster_nms_default(boxes=boxes, scores=scores, iou_thres=self.iou_thres, top_k=self.top_k, post_k=self.post_k) + [boxes, classes, scores] = cluster_nms_default(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + top_k=self.top_k, post_k=self.post_k) elif self.nms_type == 'diou': if self.cross_class: [boxes, classes, scores] = cc_cluster_diounms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, - top_k=self.top_k, post_k=self.post_k) + top_k=self.top_k, post_k=self.post_k) else: - [boxes, classes, scores] = cluster_diounms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, post_k=self.post_k) + [boxes, classes, scores] = cluster_diounms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + top_k=self.top_k, post_k=self.post_k) elif self.nms_type == 'spm': if self.cross_class: [boxes, classes, scores] = cc_cluster_SPM_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, - post_k=self.post_k) + top_k=self.top_k, post_k=self.post_k) else: - [boxes, classes, scores] = cluster_SPM_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, post_k=self.post_k) + [boxes, classes, scores] = cluster_SPM_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + top_k=self.top_k, post_k=self.post_k) elif self.nms_type == 'spm_dist': if self.cross_class: - [boxes, classes, scores] = cc_cluster_SPM_dist_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, post_k=self.post_k) + [boxes, classes, scores] = cc_cluster_SPM_dist_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + top_k=self.top_k, post_k=self.post_k) else: - [boxes, classes, scores] = cluster_SPM_dist_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, post_k=self.post_k) + [boxes, classes, scores] = cluster_SPM_dist_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + top_k=self.top_k, post_k=self.post_k) elif self.nms_type == 'spm_dist_weighted': if self.cross_class: - [boxes, classes, scores] = cc_cluster_SPM_dist_weighted_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, post_k=self.post_k) + [boxes, classes, scores] = cc_cluster_SPM_dist_weighted_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + top_k=self.top_k, post_k=self.post_k) else: - [boxes, classes, scores] = cluster_SPM_dist_weighted_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, post_k=self.post_k) + [boxes, classes, scores] = cluster_SPM_dist_weighted_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + top_k=self.top_k, post_k=self.post_k) keep_ids = torch.where(scores>threshold) scores = scores[keep_ids].cpu().numpy() From 0054e8db156029e40f8120cc6b1b3643a2f7eb07 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 22:13:52 +0200 Subject: [PATCH 019/374] Update cluster_nms.py --- .../nms/cluster_nms/cluster_nms.py | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index 9cd491c8c7..eda8e89e36 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -87,13 +87,16 @@ def run_nms(self, boxes=None, scores=None, img=None, threshold=0.2): elif self.nms_type == 'spm_dist_weighted': if self.cross_class: - [boxes, classes, scores] = cc_cluster_SPM_dist_weighted_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, - top_k=self.top_k, post_k=self.post_k) + [boxes, classes, scores] = cc_cluster_SPM_dist_weighted_nms(boxes=boxes, scores=scores, + iou_thres=self.iou_thres, + top_k=self.top_k, + post_k=self.post_k) else: - [boxes, classes, scores] = cluster_SPM_dist_weighted_nms(boxes=boxes, scores=scores, iou_thres=self.iou_thres, + [boxes, classes, scores] = cluster_SPM_dist_weighted_nms(boxes=boxes, scores=scores, + iou_thres=self.iou_thres, top_k=self.top_k, post_k=self.post_k) - keep_ids = torch.where(scores>threshold) + keep_ids = torch.where(scores > threshold) scores = scores[keep_ids].cpu().numpy() classes = classes[keep_ids].cpu().numpy() boxes = boxes[keep_ids].cpu().numpy() @@ -122,10 +125,10 @@ def cc_cluster_nms_default(boxes=None, scores=None, iou_thres=0.45, top_k=400, p B = iou for i in range(200): A=B - maxA,_=torch.max(A, dim=0) - E = (maxA<=iou_thres).float().unsqueeze(1).expand_as(A) + maxA, _ = torch.max(A, dim=0) + E = (maxA <= iou_thres).float().unsqueeze(1).expand_as(A) B=iou.mul(E) - if A.equal(B)==True: + if A.equal(B): break idx_out = torch.where(maxA > iou_thres) @@ -138,7 +141,6 @@ def cc_cluster_nms_default(boxes=None, scores=None, iou_thres=0.45, top_k=400, p return boxes, classes, scores - def cluster_nms_default(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): scores, idx = scores.sort(1, descending=True) @@ -176,8 +178,7 @@ def cluster_nms_default(boxes=None, scores=None, iou_thres=0.45, top_k=400, post def cc_cluster_diounms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): - # Collapse all the classes into 1 - + scores, classes = scores.max(dim=0) _, idx = scores.sort(0, descending=True) idx = idx[:top_k] @@ -191,7 +192,7 @@ def cc_cluster_diounms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_ maxA, _ = torch.max(A, dim=0) E = (maxA <= iou_thres).float().unsqueeze(1).expand_as(A) B = iou.mul(E) - if A.equal(B) == True: + if A.equal(B): break idx_out = torch.where(maxA > iou_thres) From 85347d9409a52977064844fd437ccda22e829bff Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 22:14:38 +0200 Subject: [PATCH 020/374] Update cluster_nms.py --- .../object_detection_2d/nms/cluster_nms/cluster_nms.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index eda8e89e36..86ee9a4107 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -258,7 +258,7 @@ def cc_cluster_SPM_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_ maxA, _ = torch.max(A, dim=0) E = (maxA <= iou_thres).float().unsqueeze(1).expand_as(A) B = iou.mul(E) - if A.equal(B) == True: + if A.equal(B): break scores = torch.prod(torch.exp(-B ** 2 / 0.2), 0) * scores @@ -318,7 +318,7 @@ def cc_cluster_SPM_dist_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, maxA, _ = torch.max(A, dim=0) E = (maxA <= iou_thres).float().unsqueeze(1).expand_as(A) B = iou.mul(E) - if A.equal(B) == True: + if A.equal(B): break D = distance(boxes, boxes) X = (B >= 0).float() @@ -386,7 +386,7 @@ def cc_cluster_SPM_dist_weighted_nms(boxes=None, scores=None, iou_thres=0.45, to maxA, _ = torch.max(A, dim=0) E = (maxA <= iou_thres).float().unsqueeze(1).expand_as(A) B = iou.mul(E) - if A.equal(B) == True: + if A.equal(B): break D = distance(boxes, boxes) X = (B >= 0).float() From ddc2af3c6e6924d42ee3e78ef69f35de50b3a5a8 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 22:18:45 +0200 Subject: [PATCH 021/374] Update cluster_nms.py --- .../object_detection_2d/nms/cluster_nms/cluster_nms.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index 86ee9a4107..b265ba09a2 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -124,10 +124,10 @@ def cc_cluster_nms_default(boxes=None, scores=None, iou_thres=0.45, top_k=400, p iou = jaccard(boxes, boxes).triu_(diagonal=1) B = iou for i in range(200): - A=B + A = B maxA, _ = torch.max(A, dim=0) E = (maxA <= iou_thres).float().unsqueeze(1).expand_as(A) - B=iou.mul(E) + B = iou.mul(E) if A.equal(B): break @@ -269,6 +269,7 @@ def cc_cluster_SPM_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_ boxes = boxes[idx] return boxes, classes, scores + def cluster_SPM_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): scores, idx = scores.sort(1, descending=True) @@ -303,6 +304,7 @@ def cluster_SPM_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=2 boxes = boxes[idx] return boxes, classes, scores + def cc_cluster_SPM_dist_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): scores, classes = scores.max(dim=0) @@ -370,6 +372,7 @@ def cluster_SPM_dist_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, pos return boxes, classes, scores + def cc_cluster_SPM_dist_weighted_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): scores, classes = scores.max(dim=0) From f4e67f9aeb4acfa4a5dddc59456e7e2dcd949644 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 22:21:09 +0200 Subject: [PATCH 022/374] Update soft_nms.py --- .../object_detection_2d/nms/soft_nms/soft_nms.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py index eef3a94673..756bc80243 100644 --- a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py @@ -6,7 +6,7 @@ class SoftNMS(NMSCustom): - def __init__(self, nms_type= 'linear', device='cuda', nms_thres=None, top_k=400, post_k=100): + def __init__(self, nms_type='linear', device='cuda', nms_thres=None, top_k=400, post_k=100): self.nms_types = ['linear', 'gaussian'] if nms_type not in self.nms_types: raise ValueError('Type: ' + nms_type + ' of Soft-NMS is not supported.') @@ -65,14 +65,12 @@ def run_nms(self, boxes=None, scores=None, threshold=0.2, img=None): dets = torch.cat((boxes, scores.unsqueeze(-1)), dim=1) retained_box = [] - i=0 + i = 0 while dets.shape[0] > 0: max_idx = np.argmax(dets[:, 4], axis=0) - #dets[[0, max_idx], :] = dets[[max_idx, 0], :] + # dets[[0, max_idx], :] = dets[[max_idx, 0], :] scores[i] = dets[0, 4] - - iou = jaccard(dets[:1,:-1], dets[1:,:-1]).triu_(diagonal=0).squeeze(0) - + iou = jaccard(dets[:1, :-1], dets[1:, :-1]).triu_(diagonal=0).squeeze(0) weight = torch.ones_like(iou) if self.nms_type == 'linear': weight[iou > self.nms_thres] -= iou[iou > self.nms_thres] @@ -80,7 +78,7 @@ def run_nms(self, boxes=None, scores=None, threshold=0.2, img=None): weight = np.exp(-(iou * iou) / self.nms_thres) dets[1:, 4] *= weight - #retained_idx = torch.where(dets[1:, 4] >= 0)[0] + # retained_idx = torch.where(dets[1:, 4] >= 0)[0] dets = dets[1:, :] i = i + 1 keep_ids = torch.where(scores > threshold) @@ -150,9 +148,6 @@ def cc_fast_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): return boxes, classes, scores - - - def py_soft_nms(dets, method='linear', iou_thr=0.3, sigma=0.5, score_thr=0.001): if method not in ('linear', 'gaussian', 'greedy'): From a58ae54feec1670ed6d4c3b06cc0ef4c8736ad43 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 22:24:36 +0200 Subject: [PATCH 023/374] Update ssd_learner.py --- src/opendr/perception/object_detection_2d/ssd/ssd_learner.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py index ec5edd7c32..dc3a295884 100644 --- a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py +++ b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py @@ -49,8 +49,6 @@ from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom gutils.random.seed(0) -import datetime - class SingleShotDetectorLearner(Learner): supported_backbones = {"vgg16_atrous": [512, 300], @@ -542,7 +540,8 @@ def eval(self, dataset, use_subset=False, subset_size=100, verbose=False): eval_dict = {k.lower(): v for k, v in zip(map_name, mean_ap)} return eval_dict - def infer(self, img, threshold=0.2, keep_size=False, custom_nms:NMSCustom=None, nms_thresh=0.45, nms_topk=400, post_nms=100): + def infer(self, img, threshold=0.2, keep_size=False, custom_nms: NMSCustom=None, + nms_thresh=0.45, nms_topk=400, post_nms=100): """ Performs inference on a single image and returns the resulting bounding boxes. :param img: image to perform inference on From c6e443b586413f8d358aead5c77cad319ce80b97 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 22:25:44 +0200 Subject: [PATCH 024/374] Update cluster_nms.py --- .../object_detection_2d/nms/cluster_nms/cluster_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index b265ba09a2..0bfb92f101 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -178,7 +178,7 @@ def cluster_nms_default(boxes=None, scores=None, iou_thres=0.45, top_k=400, post def cc_cluster_diounms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): - + scores, classes = scores.max(dim=0) _, idx = scores.sort(0, descending=True) idx = idx[:top_k] From 768d3eb2cb774b892e6f012b1132ba7c4ac3c1e0 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 22:27:00 +0200 Subject: [PATCH 025/374] Update transforms.py --- .../object_detection_2d/datasets/transforms.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/datasets/transforms.py b/src/opendr/perception/object_detection_2d/datasets/transforms.py index 17d8db3387..09e75aefad 100644 --- a/src/opendr/perception/object_detection_2d/datasets/transforms.py +++ b/src/opendr/perception/object_detection_2d/datasets/transforms.py @@ -142,6 +142,7 @@ def transform_test(imgs, mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)): return tensors[0], origs[0] return tensors, origs + def pad_test(img, min_size=512): h_pad_size = 0 pad_dim = 0 @@ -152,10 +153,12 @@ def pad_test(img, min_size=512): h_pad_size = int((min_size - img.shape[min_dim]) / 2.0) if min_dim == 2: img_padded = mx.nd.pad(img, mode="constant", constant_value=0, - pad_width=(0, 0, 0, 0, h_pad_size, h_pad_size, 0, 0)) + pad_width=(0, 0, 0, 0, h_pad_size, + h_pad_size, 0, 0)) # img_mx = np.pad(img_mx, ((h_pad_size, h_pad_size), (0, 0), (0, 0))) else: img_padded = mx.nd.pad(img, mode="constant", constant_value=0, - pad_width=(0, 0, 0, 0, 0, 0, h_pad_size, h_pad_size)) + pad_width=(0, 0, 0, 0, 0, 0, + h_pad_size, h_pad_size)) # img_mx = np.pad(img_mx, ((0, 0), (h_pad_size, h_pad_size), (0, 0))) - return img_padded \ No newline at end of file + return img_padded From ba0f269da0aa2130444a7f1b113de20458a39701 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 5 Mar 2022 22:29:09 +0200 Subject: [PATCH 026/374] Update ssd_learner.py --- src/opendr/perception/object_detection_2d/ssd/ssd_learner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py index dc3a295884..26117cb16a 100644 --- a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py +++ b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py @@ -50,6 +50,7 @@ gutils.random.seed(0) + class SingleShotDetectorLearner(Learner): supported_backbones = {"vgg16_atrous": [512, 300], "resnet50_v1": [512], From 90bbe6fe5205af41615412520ae2ced2d5580e9d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 11:19:47 +0200 Subject: [PATCH 027/374] Update nms_custom.py --- .../perception/object_detection_2d/nms/utils/nms_custom.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py index a959c4ce80..e76b39883d 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py @@ -3,5 +3,5 @@ class NMSCustom(ABC): @abstractmethod - def run_nms(self, boxes=None, scores=None, threshold=0.2, img=None): + def run_nms(self, boxes=None, scores=None, threshold=0.2, img=None, device='cpu'): pass From 97a6bc983d8500e501a0e2d389a004e8246cb44c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 11:22:10 +0200 Subject: [PATCH 028/374] Update nms_custom.py --- .../perception/object_detection_2d/nms/utils/nms_custom.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py index e76b39883d..fe8215964d 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py @@ -2,6 +2,9 @@ class NMSCustom(ABC): + def __init__(self, device='cpu'): + self.device = device + @abstractmethod def run_nms(self, boxes=None, scores=None, threshold=0.2, img=None, device='cpu'): pass From ebbe8c7fd2b218e33aa345bf10ce878a51edbd0c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 11:34:38 +0200 Subject: [PATCH 029/374] Update inference_demo.py --- .../nms/seq2seq-nms/inference_demo.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index 4f2ac7b0b3..2107c8802b 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -1,21 +1,21 @@ -from opendr.perception.object_detection_2d.nms.seq2seq_nms.Seq2SeqNMSLearner import Seq2SeqNMSLearner +from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes -from multiprocessing import Pool +import datetime import os OPENDR_HOME = os.environ['OPENDR_HOME'] -seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, experiment_name='pets_exp6', use_fmod=True, - fmod_init_path=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/datasets/PETS/FMoD/pets_edgemap_b.pkl') -seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/pets_exp6/checkpoints/checkpoint_epoch_7', verbose=True) -ssd = SingleShotDetectorLearner(device='cpu') +seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, experiment_name='auth_exp51', app_feats = 'fmod', + fmod_init_path=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/' + 'datasets/PETS/FMoD/pets_edgemap_b.pkl', device='cuda') +seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/auth_exp51/' + 'checkpoints/checkpoint_epoch_7', verbose=True) +ssd = SingleShotDetectorLearner(device='cuda') ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg') if not isinstance(img, Image): img = Image(img) -boxes = ssd.infer(img, threshold=0, custom_nms=seq2SeqNMSLearner) -seq2SeqNMSLearner.fMoD.extract_maps(img=img, augm=False) -boxes = seq2SeqNMSLearner.infer(classes=ssd.classes, dets=boxes, boxes_sorted=False, max_dt_boxes=1200, img_res=img.opencv().shape[::-1][1:]) +boxes = ssd.infer(img, threshold=0.6, custom_nms=seq2SeqNMSLearner) draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) From 8ec29c4432c2cc3bfb70c6cfd7c4ccaf818237e7 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 11:35:28 +0200 Subject: [PATCH 030/374] Update inference_demo.py --- .../object_detection_2d/nms/seq2seq-nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index 2107c8802b..7dd3d50a17 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -14,7 +14,7 @@ ssd = SingleShotDetectorLearner(device='cuda') ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) -img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg') +img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg') if not isinstance(img, Image): img = Image(img) boxes = ssd.infer(img, threshold=0.6, custom_nms=seq2SeqNMSLearner) From f6d8576a29c7805974387fea1ce58c96d58f0e94 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 11:36:29 +0200 Subject: [PATCH 031/374] Update inference_demo.py --- .../object_detection_2d/nms/seq2seq-nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index 7dd3d50a17..e54f9abca3 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -8,7 +8,7 @@ seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, experiment_name='auth_exp51', app_feats = 'fmod', fmod_init_path=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/' - 'datasets/PETS/FMoD/pets_edgemap_b.pkl', device='cuda') + 'datasets/PETS/FMoD/pets_edgemap_b.pkl', device='cpu') seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/auth_exp51/' 'checkpoints/checkpoint_epoch_7', verbose=True) ssd = SingleShotDetectorLearner(device='cuda') From 1545c2376c141be24a2d0c64e47fa645e061ecbc Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 11:36:53 +0200 Subject: [PATCH 032/374] Update inference_demo.py --- .../object_detection_2d/nms/soft_nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py index affe47f233..ba7c1c012c 100644 --- a/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py @@ -8,7 +8,7 @@ ssd = SingleShotDetectorLearner(device='cuda') ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) -img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg') +img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg') if not isinstance(img, Image): img = Image(img) cluster_nms = SoftNMS(device='cpu', nms_type='gaussian') From 981e444e4c13bd329e3824462562f9c65e660b57 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 11:37:12 +0200 Subject: [PATCH 033/374] Update inference_demo.py --- .../object_detection_2d/nms/fast_nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py index bb3fbab626..4927df45a2 100644 --- a/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py @@ -8,7 +8,7 @@ ssd = SingleShotDetectorLearner(device='cuda') ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) -img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg') +img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg') if not isinstance(img, Image): img = Image(img) cluster_nms = FastNMS(device='cpu', cross_class=True) From 6286427f584112941c2db4af03358bafdf64fa8b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 11:37:25 +0200 Subject: [PATCH 034/374] Update inference_demo.py --- .../object_detection_2d/nms/cluster_nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py index 444e3dbcbc..b916a23755 100644 --- a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py @@ -9,7 +9,7 @@ ssd = SingleShotDetectorLearner(device='cuda') ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) -img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/seq2seq-nms/img_temp/frame_0000.jpg') +img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg') if not isinstance(img, Image): img = Image(img) start_time = datetime.datetime.now() From c360982896bebdbe2963d26626708103df84f78a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 11:39:31 +0200 Subject: [PATCH 035/374] Add files via upload --- .../nms/img_temp/frame_0000.jpg | Bin 0 -> 325104 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg diff --git a/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg b/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg new file mode 100644 index 0000000000000000000000000000000000000000..5efb4d9298de38969e29c3bc98f9c91a5ae99849 GIT binary patch literal 325104 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[HY(kgreK9)b{m#PV)|jDpgC!Gt%f@TdeGQD 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 U%g4RhvxWI+#1uvU5Hyeg!G{K+I0qzc>Z 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

;T`0?0@jkITpwLK|M->l1os< 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∈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

_i{JzeO`lfapmsUFkz^iWRX}$R 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 I@7uTk*-tn)8~^|S literal 0 HcmV?d00001 From d6a82249bd41d5fd7dbe52dd666fa1c78598ee22 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 12:53:41 +0200 Subject: [PATCH 036/374] Add files via upload --- .../nms/seq2seq_nms/algorithm/fmod.py | 4 +- .../nms/seq2seq_nms/algorithm/nms_dataset.py | 473 +++++++++ .../seq2seq_nms/algorithm/seq2seq_model.py | 40 +- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 923 ++++++++++++++++++ 4 files changed, 1418 insertions(+), 22 deletions(-) create mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/nms_dataset.py create mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py index fcf0511646..73114307bb 100755 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py @@ -50,8 +50,8 @@ def __init__(self, roi_pooling_dim=None, pyramid_depth=3, map_type="SIFT", map_b self.std = None def set_mean_std(self, mean_values=None, std_values=None): - self.mean = torch.tensor(mean_values) - self.std = torch.tensor(std_values) + self.mean = torch.tensor(mean_values).float() + self.std = torch.tensor(std_values).float() if self.device == 'cuda': self.mean = self.mean .cuda() self.std = self.std.cuda() diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/nms_dataset.py new file mode 100644 index 0000000000..325a6f9009 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/nms_dataset.py @@ -0,0 +1,473 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from opendr.engine.datasets import Dataset +import os +from urllib.request import urlretrieve +import ssl +import time +from zipfile import ZipFile +import tarfile +import gdown +import shutil +import pickle +import numpy as np +import math +from tqdm import tqdm +from opendr.perception.object_detection_2d import SingleShotDetectorLearner +from opendr.engine.data import Image +from opendr.perception.object_detection_2d.datasets.transforms import BoundingBoxListToNumpyArray +import json +from pycocotools.coco import COCO + + +class Dataset_NMS(Dataset): + def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, device='cuda'): + super().__init__() + available_dataset = ['COCO', 'PETS', 'CrowdHuman'] + self.dataset_sets = {'train': None, + 'val': None, + 'test': None} + if dataset_name not in available_dataset: + except_str = 'Unsupported dataset: ' + dataset_name + '. Currently available are:' + for j in range(len(available_dataset)): + except_str = except_str + ' \'' + available_dataset[j] + '\'' + if j < len(available_dataset) - 1: + except_str = except_str + ',' + except_str = except_str + '.' + raise ValueError(except_str) + + ssl._create_default_https_context = ssl._create_unverified_context + self.dataset_name = dataset_name + self.split = split + # self.__prepare_dataset() + self.path = os.path.join(path, dataset_name) + self.src_data = [] + if self.dataset_name == "PETS": + self.detector = 'JPD' + self.detector_type = 'default' + if use_ssd: + self.detector = 'SSD' + self.detector_type = 'custom' + + self.dataset_sets['train'] = 'train' + self.dataset_sets['val'] = 'val' + self.dataset_sets['test'] = 'test' + if self.dataset_sets[self.split] is None: + raise ValueError(self.split + ' split is not available...') + + if not os.path.exists(os.path.join(self.path, 'images/S1/L1')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S1_L1.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S1/L2')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S1_L2.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S2/L1')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L1.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S2/L2')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L2.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S2/L3')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L3.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S3/Multiple_Flow')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S3_MF.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists( + os.path.join(self.path, 'annotations', 'pets_' + self.dataset_sets[self.split] + '.json')): + self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_annotations_json.zip', + download_path=os.path.join(self.path, 'annotations'), file_format="zip", + create_dir=True) + pkl_filename = os.path.join(self.path, + 'data_' + self.detector + '_' + self.dataset_sets[self.split] + '_pets.pkl') + if not os.path.exists(pkl_filename): + ssd = None + if use_ssd: + ssd = SingleShotDetectorLearner(device=device) + ssd.download(".", mode="pretrained") + ssd.load("./ssd_default_person", verbose=True) + if not os.path.exists( + os.path.join(self.path, 'detections', + 'PETS-' + self.dataset_sets[self.split] + '_siyudpm_dets.idl')): + self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_detections.zip', + download_path=os.path.join(self.path, 'detections'), file_format="zip", + create_dir=True) + if not os.path.exists( + os.path.join(self.path, 'annotations', 'PETS-' + self.dataset_sets[self.split] + '.idl')): + self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_annotations.zip', + download_path=os.path.join(self.path, 'annotations'), file_format="zip", + create_dir=True) + with open(os.path.join(self.path, 'annotations', + 'PETS-' + self.dataset_sets[self.split] + '.idl')) as fp_gt: + fp_dt = None + if self.detector_type == 'default': + fp_dt = open(os.path.join(self.path, 'detections', + 'PETS-' + self.dataset_sets[self.split] + '_siyudpm_dets.idl')) + print('Preparing PETS ' + self.dataset_sets[self.split] + ' set...') + current_id = 0 + number_samples = 1696 + if self.split == 'val': + current_id = 1696 + number_samples = 240 + elif self.split == 'test': + current_id = 1936 + number_samples = 436 + pbarDesc = "Overall progress" + pbar = tqdm(desc=pbarDesc, total=number_samples) + if self.detector_type == 'default': + line_dt = fp_dt.readline() + line_gt = fp_gt.readline() + while line_gt: + remove_strings = ['PETS09-', '\"', ':', '(', ')', ',', '', ';'] + data_gt = line_gt.replace(':', ' ') + for j in range(len(remove_strings)): + data_gt = data_gt.replace(remove_strings[j], '') + data_gt = data_gt.split() + filename_gt = data_gt[0][0:2] + '/' + data_gt[0][2:] + if filename_gt[0:6] == 'S2/L1/': + filename_gt = filename_gt.replace('img/00', 'Time_12-34/View_001/frame_') + num = int(filename_gt[-8:-4]) - 1 + filename_gt = filename_gt[:-8] + str(num).zfill(4) + '.jpg' + if filename_gt[0:6] == 'S2/L2/': + filename_gt = filename_gt.replace('img/00', 'Time_14-55/View_001/frame_') + num = int(filename_gt[-8:-4]) - 1 + filename_gt = filename_gt[:-8] + str(num).zfill(4) + '.jpg' + if filename_gt[0:2] == 'S3': + filename_gt = filename_gt.replace('_MF', 'Multiple_Flow') + + if self.detector_type == 'default': + data_dt = line_dt.replace(':', ' ') + for j in range(len(remove_strings)): + data_dt = data_dt.replace(remove_strings[j], '') + data_dt = data_dt.split() + filename_dt = data_dt[0][0:2] + '/' + data_dt[0][2:] + if filename_dt[0:6] == 'S2/L1/': + filename_dt = filename_dt.replace('img/00', 'Time_12-34/View_001/frame_') + num = int(filename_dt[-8:-4]) - 1 + filename_dt = filename_dt[:-8] + str(num).zfill(4) + '.jpg' + if filename_dt[0:6] == 'S2/L2/': + filename_dt = filename_dt.replace('img/00', 'Time_14-55/View_001/frame_') + num = int(filename_dt[-8:-4]) - 1 + filename_dt = filename_dt[:-8] + str(num).zfill(4) + '.jpg' + if filename_dt[0:2] == 'S3': + filename_dt = filename_dt.replace('_MF', 'Multiple_Flow') + if filename_gt != filename_dt: + raise ValueError('Errors in files...') + + img = Image.open(os.path.join(self.path, 'images/', filename_gt)) + + dt_boxes = [] + if self.detector_type == 'default': + for i in range(1, (len(data_dt)), 5): + dt_box = np.array((float(data_dt[i]), float(data_dt[i + 1]), float(data_dt[i + 2]), + float(data_dt[i + 3]), 1 / (1 + math.exp(- float(data_dt[i + 4]))))) + dt_boxes.append(dt_box) + else: + bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, + nms_topk=6000, post_nms=6000) + bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) + bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] + bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] + bboxes_list = bboxes_list[:5000, :] + for b in range(len(bboxes_list)): + dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], + bboxes_list[b, 3], bboxes_list[b, 4][0]])) + gt_boxes = [] + for i in range(1, (len(data_gt)), 5): + gt_box = np.array((float(data_gt[i]), float(data_gt[i + 1]), float(data_gt[i + 2]), + float(data_gt[i + 3]))) + gt_boxes.append(gt_box) + self.src_data.append({ + 'id': current_id, + 'filename': os.path.join('images', filename_gt), + 'resolution': img.opencv().shape[0:2][::-1], + 'gt_boxes': [np.asarray([]), np.asarray(gt_boxes)], + 'dt_boxes': [np.asarray([]), np.asarray(dt_boxes)] + }) + current_id = current_id + 1 + pbar.update(1) + if self.detector_type == 'default': + line_dt = fp_dt.readline() + line_gt = fp_gt.readline() + pbar.close() + if self.detector_type == 'default': + fp_dt.close() + with open(pkl_filename, 'wb') as handle: + pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) + else: + with open(pkl_filename, 'rb') as fp_pkl: + self.src_data = pickle.load(fp_pkl) + + self.classes = ['background', 'human'] + self.class_ids = [-1, 1] + + elif self.dataset_name == "CrowdHuman": + splits = ['train', 'val'] + if self.split not in splits: + raise ValueError(self.split + ' split is not available...') + self.detector = 'YOLOv4' + self.detector_type = 'default' + if use_ssd: + self.detector = 'SSD' + self.detector_type = 'custom' + if not os.path.exists(os.path.join(self.path, 'images/train')): + os.makedirs(os.path.join(self.path, 'images/train'), exist_ok=True) + urls = ['https://drive.google.com/file/d/134QOvaatwKdy0iIeNqA_p-xkAhkV4F8Y/view?usp=sharing', + 'https://drive.google.com/u/0/uc?id=17evzPh7gc1JBNvnW1ENXLy5Kr4Q_Nnla', + 'https://drive.google.com/u/0/uc?id=1tdp0UCgxrqy1B6p8LkR-Iy0aIJ8l4fJW'] + outputs = [os.path.join(self.path, 'CrowdHuman_train01.zip'), 'CrowdHuman_train02.zip', + 'CrowdHuman_train03.zip'] + for i in range(0, len(urls)): + gdown.download(urls[i], outputs[i], quiet=False) + zip_path = os.path.join('.', outputs[i]) + with ZipFile(zip_path, 'r') as zip_ref: + download_path = os.path.join(self.path, 'images', 'train') + zip_ref.extractall(download_path) + os.remove(zip_path) + + if not os.path.exists(os.path.join(self.path, 'images/val')): + os.makedirs(os.path.join(self.path, 'images/val'), exist_ok=True) + url = 'https://drive.google.com/u/0/uc?id=18jFI789CoHTppQ7vmRSFEdnGaSQZ4YzO' + output = 'CrowdHuman_val.zip' + gdown.download(url, output, quiet=False) + zip_path = os.path.join('.', output) + with ZipFile(zip_path, 'r') as zip_ref: + download_path = os.path.join(self.path, 'images', 'val') + zip_ref.extractall(download_path) + os.remove(zip_path) + + if not os.path.exists( + os.path.join(self.path, 'data_' + self.detector + '_' + self.split + '_crowdhuman.pkl')): + # Download detections from FTP server + ssd = None + if use_ssd: + ssd = SingleShotDetectorLearner(device=device) + ssd.download(".", mode="pretrained") + ssd.load("./ssd_default_person", verbose=True) + + # Download annotations from official CrowdHuman GoogleDrive repo + if not os.path.exists(os.path.join(self.path, 'annotations', 'annotation_' + self.split + '.odgt')): + os.makedirs(os.path.join(self.path, 'annotations'), exist_ok=True) + url = None + if self.split == 'train': + url = 'https://drive.google.com/u/0/uc?id=1UUTea5mYqvlUObsC1Z8CFldHJAtLtMX3&export=download' + elif self.split == 'val': + url = 'https://drive.google.com/u/0/uc?id=10WIRwu8ju8GRLuCkZ_vT6hnNxs5ptwoL&export=download' + output = 'annotation_' + self.split + '.odgt' + gdown.download(url, output, quiet=False) + shutil.move(os.path.join('.', output), + os.path.join('.', 'datasets', 'CrowdHuman', 'annotations', self.split)) + + with open(os.path.join(self.path, 'annotations', 'annotation_' + self.split + '.odgt')) as fp_gt: + data_dt = None + if self.detector_type == 'default': + fp_dt = open( + os.path.join(self.path, 'detections', 'det_data_' + self.split + '_crowdhuman.pkl'), 'rb') + data_dt = pickle.load(fp_dt) + line = fp_gt.readline() + i = 0 + while line: + annotations = json.loads(line) + img = Image.open(os.path.join(self.path, 'images/' + self.split, annotations['ID'] + '.jpg')) + dt_boxes = [] + if self.detector_type == 'default' and data_dt[i]['id'] != annotations['ID']: + continue + elif self.detector_type == 'default': + dt_boxes = data_dt[i]['dt_boxes'] + elif self.detector_type == 'custom' and self.detector == 'SSD': + bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, + nms_topk=10000, post_nms=10000) + bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) + bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] + bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] + bboxes_list = bboxes_list[:8000, :] + for b in range(len(bboxes_list)): + dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], + bboxes_list[b, 3], bboxes_list[b, 4][0]])) + gt_boxes = [] + for j in range(len(annotations['gtboxes'])): + if annotations['gtboxes'][j]['tag'] == 'person': + gt_box = annotations['gtboxes'][j]['fbox'] + gt_box[2] = gt_box[2] + gt_box[0] + gt_box[3] = gt_box[3] + gt_box[1] + gt_boxes.append(gt_box) + self.src_data.append({ + 'id': annotations['ID'], + 'filename': annotations['ID'] + '.jpg', + 'resolution': img.opencv().shape[0:2][::-1], + 'gt_boxes': [np.asarray([]), np.asarray(gt_boxes)], + 'dt_boxes': [np.asarray([]), np.asarray(dt_boxes)] + }) + line = fp_gt.readline() + i = i + 1 + with open(os.path.join(self.path, 'data_' + self.split + '_crowdhuman.pkl'), 'wb') as handle: + pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) + else: + with open(os.path.join(self.path, 'data_' + self.split + '_crowdhuman.pkl'), 'rb') as fp_dt: + self.src_data = pickle.load(fp_dt) + elif self.dataset_name == "COCO": + self.dataset_sets['train'] = 'train' + self.dataset_sets['val'] = 'minival' + self.dataset_sets['test'] = 'valminusminival' + imgs_split = None + if self.dataset_sets[self.split] is None: + raise ValueError(self.split + ' split is not available...') + elif self.dataset_sets[self.split] == 'train': + imgs_split = 'train2014' + else: + imgs_split = 'val2014' + self.detector = 'YOLOv4' + self.detector_type = 'default' + ssd = None + if use_ssd: + self.detector = 'SSD' + self.detector_type = 'custom' + ssd = SingleShotDetectorLearner(device=device) + ssd.download(".", mode="pretrained") + ssd.load("./ssd_default_person", verbose=True) + if not os.path.exists(os.path.join(self.path, imgs_split)): + self.download('http://images.cocodataset.org/zips/' + imgs_split +'.zip', + download_path=os.path.join(self.path), file_format="zip", + create_dir=True) + pkl_filename = os.path.join(self.path, 'data_' + self.detector + '_' + self.dataset_sets[self.split] + '_coco.pkl') + if not os.path.exists(pkl_filename): + if not os.path.exists(os.path.join(self.path, 'annotations', 'instances_' + imgs_split +'.json')): + self.download('http://images.cocodataset.org/annotations/annotations_trainval2014.zip', + download_path=os.path.join(self.path), file_format="zip", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'detections', 'coco_2014_' + self.dataset_sets[self.split]+ '_FRCN_train.pkl')): + self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/coco_2014_FRCN.tar.gz', + download_path=os.path.join(self.path, 'detections'), file_format='tar.gz', + create_dir=True) + with open(os.path.join(self.path, 'detections', + 'coco_2014_' + self.dataset_sets[self.split] + '_FRCN_train.pkl'), 'rb') as f: + dets_default = pickle.load(f, encoding='latin1') + annots = COCO(annotation_file=os.path.join(self.path, 'annotations', 'instances_' + imgs_split + '.json')) + pbarDesc = "Overall progress" + pbar = tqdm(desc=pbarDesc, total=len(dets_default[1])) + for i in range(len(dets_default[1])): + dt_boxes = [] + img_info = annots.loadImgs([dets_default[1][i]])[0] + img = Image.open(os.path.join(self.path, imgs_split, img_info["file_name"])) + if self.detector_type == 'default': + dt_boxes = dets_default[0][1][i] + elif self.detector == 'SSD': + bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, + nms_topk=6000, post_nms=6000) + bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) + if bboxes_list.shape[0]>0: + bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] + if bboxes_list.shape[0] > 0: + bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] + bboxes_list = bboxes_list[:5000, :] + for b in range(len(bboxes_list)): + dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], + bboxes_list[b, 3], bboxes_list[b, 4][0]])) + #if len(dt_boxes) > 0: + # dt_boxes[:, 2] = dt_boxes[:, 0] + dt_boxes[:, 2] + # dt_boxes[:, 3] = dt_boxes[:, 1] + dt_boxes[:, 3] + dt_boxes = np.asarray(dt_boxes) + annots_in_frame = annots.loadAnns(annots.getAnnIds(imgIds=[dets_default[1][i]], iscrowd=False)) + gt_boxes = [] + for j in range(len(annots_in_frame)): + gt_boxes.append(annots_in_frame[j]['bbox']) + gt_boxes = np.asarray(np.asarray(gt_boxes)) + if gt_boxes.shape[0]>0: + gt_boxes[:, 2] = gt_boxes[:, 0] + gt_boxes[:, 2] + gt_boxes[:, 3] = gt_boxes[:, 1] + gt_boxes[:, 3] + self.src_data.append({ + 'id': dets_default[1][i], + 'filename': os.path.join(imgs_split, img_info["file_name"]), + 'resolution': [img_info['width'], img_info['height']], + 'gt_boxes': [np.asarray([]), gt_boxes], + 'dt_boxes': [np.asarray([]), dt_boxes] + }) + pbar.update(1) + pbar.close() + with open(pkl_filename, 'wb') as handle: + pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) + else: + with open(pkl_filename, 'rb') as fp_pkl: + self.src_data = pickle.load(fp_pkl) + self.classes = ['background', 'person'] + self.class_ids = [-1, 1] + @staticmethod + def download( + url, download_path, dataset_sub_path=".", file_format="zip", create_dir=False): + + if create_dir: + os.makedirs(download_path, exist_ok=True) + + print("Downloading dataset from", url, "to", download_path) + + start_time = 0 + last_print = 0 + + def reporthook(count, block_size, total_size): + nonlocal start_time + nonlocal last_print + if count == 0: + start_time = time.time() + last_print = start_time + return + + duration = time.time() - start_time + progress_size = int(count * block_size) + speed = int(progress_size / (1024 * duration)) + if time.time() - last_print >= 1: + last_print = time.time() + print( + "\r%d MB, %d KB/s, %d seconds passed" % + (progress_size / (1024 * 1024), speed, duration), + end='' + ) + + if file_format == "zip": + zip_path = os.path.join(download_path, "dataset.zip") + urlretrieve(url, zip_path, reporthook=reporthook) + print() + print("Extracting data from zip file") + with ZipFile(zip_path, 'r') as zip_ref: + zip_ref.extractall(download_path) + os.remove(zip_path) + elif file_format == "tar.bz2" or file_format == "tar.gz": + tar_path = os.path.join(download_path, "dataset." + file_format) + urlretrieve(url, tar_path, reporthook=reporthook) + print() + + def members(tf): + l = len("Crowd_PETS09/") + for member in tf.getmembers(): + if member.path.startswith("Crowd_PETS09/"): + member.path = member.path[l:] + yield member + + with tarfile.open(tar_path, "r:" + file_format.split('.')[1]) as tar: + if file_format == "tar.bz2": + tar.extractall(path=download_path, members=members(tar)) + else: + tar.extractall(path=download_path) + tar.close() + os.remove(tar_path) + else: + raise ValueError("Unsupported file_format: " + file_format) + + # def __prepare_dataset(self): + # seq_root = os.path.join(self.path, "images/train") + # label_root = os.path.join(self.path, "labels/test") diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py index 4692e30bbe..fa4d1e1e06 100755 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py @@ -19,26 +19,26 @@ class Seq2SeqNet(nn.Module): - def __init__(self, dropout=0.01, use_fmod=True, app_input_dim=315, geom_input_dim=14, lq_dim=256, sq_dim=128, - num_JPUs=4, device='gpu'): + def __init__(self, dropout=0.01, use_app_feats=True, app_input_dim=315, geom_input_dim=14, lq_dim=256, sq_dim=128, + num_JPUs=4, device='cuda'): super().__init__() - self.use_fmod = use_fmod + self.use_app_feats = use_app_feats self.dropout_q = nn.Dropout(dropout * 0.25) self.num_JPUs = num_JPUs self.joint_processing_units = [] for i in range(self.num_JPUs): self.joint_processing_units.append(Joint_processing_unit(lq_dim=lq_dim, sq_dim=sq_dim, dropout=dropout)) - if device == 'gpu': + if device == 'cuda': self.joint_processing_units[i] = self.joint_processing_units[i].cuda() self.joint_processing_units = nn.ModuleList(self.joint_processing_units) - if self.use_fmod: - q_fmod_dims = [180, 180] - self.q_fmod_layers = nn.Sequential( - nn.Linear(app_input_dim, q_fmod_dims[0]), + if self.use_app_feats: + q_app_dims = [180, 180] + self.q_app_layers = nn.Sequential( + nn.Linear(app_input_dim, q_app_dims[0]), nn.GELU(), nn.Dropout(dropout * 0.25), - nn.LayerNorm(q_fmod_dims[0], eps=1e-6), - nn.Linear(q_fmod_dims[0], q_fmod_dims[1]), + nn.LayerNorm(q_app_dims[0], eps=1e-6), + nn.Linear(q_app_dims[0], q_app_dims[1]), nn.GELU(), nn.Dropout(dropout * 0.25), # nn.LayerNorm(q_fmod_dims[1], eps=1e-6) @@ -68,9 +68,9 @@ def __init__(self, dropout=0.01, use_fmod=True, app_input_dim=315, geom_input_di q_final_in_dim = q_geom_dims[-1] k_final_in_dim = k_geom_dims[-1] - if self.use_fmod: - q_final_in_dim = q_geom_dims[-1] + q_fmod_dims[-1] - k_final_in_dim = k_geom_dims[-1] + q_fmod_dims[-1] + if self.use_app_feats: + q_final_in_dim = q_geom_dims[-1] + q_app_dims[-1] + k_final_in_dim = k_geom_dims[-1] + q_app_dims[-1] self.q_full_layers = nn.Sequential( nn.LayerNorm(q_final_in_dim, eps=1e-6), @@ -96,17 +96,17 @@ def __init__(self, dropout=0.01, use_fmod=True, app_input_dim=315, geom_input_di nn.Sigmoid() ) - def forward(self, q_geom_feats=None, k_geom_feats=None, msk=None, fmod_feats=None): + def forward(self, q_geom_feats=None, k_geom_feats=None, msk=None, app_feats=None): q_feats = self.q_geom_layers(q_geom_feats) k_feats = self.k_geom_layers(k_geom_feats) - if self.use_fmod and fmod_feats is not None: - fmod_feats = self.q_fmod_layers(fmod_feats) - q_feats = torch.cat((q_feats, fmod_feats), dim=2) - k_feats = torch.cat((k_feats, fmod_feats.transpose(0, 1).repeat(k_feats.shape[1], 1, 1)), dim=2) + if self.use_app_feats and app_feats is not None: + app_feats = self.q_app_layers(app_feats) + q_feats = torch.cat((q_feats, app_feats), dim=2) + k_feats = torch.cat((k_feats, app_feats.transpose(0, 1).repeat(k_feats.shape[1], 1, 1)), dim=2) - elif fmod_feats is None: - raise UserWarning("FMoD representations not provided.") + elif app_feats is None: + raise UserWarning("Appearance-based representations not provided.") q_feats = self.q_full_layers(q_feats) k_feats = self.k_full_layers(k_feats) for i in range(self.num_JPUs): diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py new file mode 100644 index 0000000000..ac6257cff1 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -0,0 +1,923 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import torch +import torch.nn.functional as F +import pickle +import numpy as np +import torchvision +import os +from opendr.engine.learners import Learner +from opendr.engine.constants import OPENDR_SERVER_URL +from urllib.request import urlretrieve +import torch.nn as nn +from tensorboardX import SummaryWriter +import torch.optim as optim +from tqdm import tqdm +import collections +import json +from pycocotools.coco import COCO +from pycocotools.cocoeval import COCOeval +import sys +from opendr.engine.target import BoundingBox, BoundingBoxList +from opendr.engine.data import Image +from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet +from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.fmod import FMoD +from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.nms_dataset import Dataset_NMS +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom + + +class Seq2SeqNMSLearner(Learner, NMSCustom): + def __init__(self, lr=0.0001, lr_schedule='', checkpoint_after_iter=1, checkpoint_load_iter=0, + experiment_name='default', temp_path='temp', device='cuda', app_feats='fmod', + fmod_map_type='EDGEMAP_B', fmod_map_bin=True, dropout=0.02, fmod_roi_pooling_dim=160, + fmod_map_res_dim=800, fmod_pyramid_lvl=3, lq_dim=256, sq_dim=128, app_input_dim=None, + num_JPUs=4, pretrained_demo_model=None, log_after=500, iou_filtering=None, fmod_init_path=None): + super(Seq2SeqNMSLearner, self).__init__(lr=lr, batch_size=1, lr_schedule=lr_schedule, + checkpoint_after_iter=checkpoint_after_iter, + checkpoint_load_iter=checkpoint_load_iter, + temp_path=temp_path, device=device, backbone='default') + self.app_feats = app_feats + self.use_app_feats = False + if self.app_feats is not None: + self.use_app_feats = True + if self.app_feats == 'fmod': + self.fmod_normalization = None + self.fmod_map_type = fmod_map_type + self.fmod_roi_pooling_dim = [fmod_roi_pooling_dim, fmod_roi_pooling_dim] + self.fmod_map_res_dim = fmod_map_res_dim + self.fmod_pyramid_lvl = fmod_pyramid_lvl + self.fmod_feats_dim = 0 + for i in range(0, self.fmod_pyramid_lvl): + self.fmod_feats_dim = self.fmod_feats_dim + 15 * (pow(4, i)) + self.fmod_map_bin = fmod_map_bin + self.app_input_dim = self.fmod_feats_dim + elif self.app_feats == 'zeros' or self.app_feats == 'custom': + if app_input_dim is None: + raise Exception("The dimension of the input appearance-based features is not provided...") + else: + self.app_input_dim = app_input_dim + if self.app_feats == 'custom': + raise AttributeError("Custom appearance-based features are not yet supported.") + self.geom_input_dim = 14 + self.lq_dim = lq_dim + self.sq_dim = sq_dim + self.dropout = dropout + self.num_JPUs = num_JPUs + self.parent_dir = temp_path + if not os.path.isdir(self.parent_dir): + os.mkdir(self.parent_dir) + self.experiment_name = experiment_name + if not os.path.isdir(os.path.join(self.parent_dir, self.experiment_name)): + os.mkdir(os.path.join(self.parent_dir, self.experiment_name)) + self.pretrained_demo_model = pretrained_demo_model + self.checkpoint_load_iter = checkpoint_load_iter + self.log_after = log_after + self.iou_filtering = iou_filtering + self.classes = None + self.class_ids = None + self.device = device + self.fMoD = None + if self.app_feats == 'fmod': + self.fMoD = FMoD(roi_pooling_dim=self.fmod_roi_pooling_dim, pyramid_depth=self.fmod_pyramid_lvl, + resize_dim=self.fmod_map_res_dim, + map_type=self.fmod_map_type, map_bin=self.fmod_map_bin, device=self.device) + if fmod_init_path is not None: + fmod_mean_std = load_FMoD_init(fmod_init_path) + self.fMoD.set_mean_std(mean_values=fmod_mean_std['mean'], std_values=fmod_mean_std['std']) + + def fit(self, dataset, val_dataset=None, epochs=None, logging_path='', logging_flush_secs=30, silent=True, + verbose=True, nms_gt_iou=0.5, boxes_sorted=False, max_dt_boxes=400, datasets_folder='./datasets', + use_ssd=False): + + dataset_nms = Dataset_NMS(path=datasets_folder, dataset_name=dataset, split='train', use_ssd=use_ssd) + if self.classes is None: + self.classes = dataset_nms.classes + self.class_ids = dataset_nms.class_ids + + if logging_path != '' and logging_path is not None: + logging = True + file_writer = SummaryWriter(logging_path, flush_secs=logging_flush_secs) + else: + logging = False + file_writer = None + + if self.model is None: + self.init_model() + checkpoints_folder = os.path.join(self.parent_dir, self.experiment_name, 'checkpoints') + if self.checkpoint_after_iter != 0 and not os.path.exists(checkpoints_folder): + os.makedirs(checkpoints_folder) + + if self.pretrained_demo_model is not None: + self.download(mode="weights", verbose=verbose and not silent) + weights_path = None + if self.pretrained_demo_model == 'PETS': + weights_path = os.path.join(self.parent_dir, "seq2seq_pets.pth.tar") + self.checkpoint_load_iter = '?' + elif self.pretrained_demo_model == 'COCO': + weights_path = os.path.join(self.parent_dir, "seq2seq_coco.pth.tar") + self.checkpoint_load_iter = '?' + elif self.pretrained_demo_model == 'CrownHuman': + weights_path = os.path.join(self.parent_dir, "seq2seq_crowdhuman.pth.tar") + self.checkpoint_load_iter = '?' + self.load(path=weights_path, verbose=verbose) + elif self.checkpoint_load_iter != 0: + checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) + checkpoint_full_path = os.path.join(checkpoints_folder, checkpoint_name) + self.load(checkpoint_full_path) + + if not silent and verbose: + print("Model trainable parameters:", self.count_parameters()) + + self.model.train() + if self.device == 'cuda': + self.model = self.model.cuda() + + if epochs is None: + raise ValueError("Training epochs not specified") + elif epochs <= self.checkpoint_load_iter: + raise ValueError("Training epochs are less than those of the loaded model") + + if self.app_feats == 'fmod': + fmod_mean_std = load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, + fmod_pyramid_lvl=self.fmod_pyramid_lvl, + datasets_folder=datasets_folder, verbose=verbose) + self.fMoD.set_mean_std(mean_values=fmod_mean_std['mean'], std_values=fmod_mean_std['std']) + + start_epoch = 0 + drop_after_epoch = [4, 6] + + train_ids = np.arange(len(dataset_nms.src_data)) + total_loss_iter = 0 + total_loss_epoch = 0 + optimizer = optim.Adam(self.model.parameters(), lr=self.lr, betas=(0.9, 0.99), eps=1e-9) # HERE + scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=drop_after_epoch, gamma=0.1) + + if self.checkpoint_load_iter != 0: + checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) + checkpoint_full_path = os.path.join(checkpoints_folder, checkpoint_name) + self.load(checkpoint_full_path) + + num_iter = 0 + training_weights = compute_class_weights(pos_weights=[0.9, 0.1], max_dets=max_dt_boxes, dataset_nms=dataset_nms) + # Single class NMS only. + class_index = 1 + for epoch in range(start_epoch, epochs): + pbar = None + if not silent: + pbarDesc = "Epoch #" + str(epoch) + " progress" + pbar = tqdm(desc=pbarDesc, total=len(train_ids)) + np.random.shuffle(train_ids) + for sample_id in train_ids: + image_fln = dataset_nms.src_data[sample_id]['filename'] + loss = torch.tensor([0.0], requires_grad=True) + if self.device == 'cuda': + loss = loss.cuda() + if len(dataset_nms.src_data[sample_id]['dt_boxes'][class_index]) > 0: + dt_boxes = torch.tensor( + dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 0:4]).float() + dt_scores = torch.tensor(dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 4]).float() + if not boxes_sorted: + dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) + dt_boxes = dt_boxes[dt_scores_ids] + else: + continue + gt_boxes = torch.tensor([]).float() + if len(dataset_nms.src_data[sample_id]['gt_boxes'][class_index]) > 0: + gt_boxes = torch.tensor(dataset_nms.src_data[sample_id]['gt_boxes'][class_index]).float() + image_path = os.path.join(datasets_folder, dataset, image_fln) + img_res = dataset_nms.src_data[sample_id]['resolution'][::-1] + + if self.device == "cuda": + dt_boxes = dt_boxes.cuda() + dt_scores = dt_scores.cuda() + gt_boxes = gt_boxes.cuda() + + val_ids = torch.logical_and((dt_boxes[:, 2] - dt_boxes[:, 0]) > 4, + (dt_boxes[:, 3] - dt_boxes[:, 1]) > 4) + dt_boxes = dt_boxes[val_ids, :] + dt_scores = dt_scores[val_ids] + + dt_boxes, dt_scores = drop_dets(dt_boxes, dt_scores) + if dt_boxes.shape[0] < 1: + continue + if self.iou_filtering is not None and 1.0 > self.iou_filtering > 0: + dt_boxes, dt_scores = apply_torchNMS(boxes=dt_boxes, scores=dt_scores, + iou_thres=self.iou_filtering) + + dt_boxes = dt_boxes[:max_dt_boxes] + dt_scores = dt_scores[:max_dt_boxes] + app_feats = None + if self.app_feats == 'fmod': + img = Image.open(image_path) + img = img.convert(format='channels_last', channel_order='bgr') + self.fMoD.extract_maps(img=img, augm=True) + app_feats = self.fMoD.extract_FMoD_feats(dt_boxes) + app_feats = torch.unsqueeze(app_feats, dim=1) + elif self.app_feats == 'zeros': + app_feats = torch.zeros([dt_boxes.shape[0], self.app_input_dim]) + if self.device == 'cuda': + app_feats = app_feats.cuda() + elif self.app_feats == 'custom': + raise AttributeError("Custom appearance-based features are not yet supported.") + + msk = compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) + q_geom_feats, k_geom_feats = compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, + resolution=img_res) + + optimizer.zero_grad() + preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, + app_feats=app_feats) + preds = torch.clamp(preds, 0.001, 1 - 0.001) + labels = matching_module(scores=preds, dt_boxes=dt_boxes, gt_boxes=gt_boxes, + iou_thres=nms_gt_iou) + + # weights = (2.92 * labels + 0.932 * (1 - labels)).cuda() + weights = (training_weights[class_index][1] * labels + training_weights[class_index][0] * ( + 1 - labels)).cuda() + + e = torch.distributions.uniform.Uniform(0.02, 0.0205).sample([labels.shape[0], 1]) + if self.device == 'cuda': + e = e.cuda() + labels = labels * (1 - e) + (1 - labels) * e + ce_loss = F.binary_cross_entropy(preds, labels, reduction="none") + loss = loss + (ce_loss * weights).sum() + total_loss_iter = total_loss_iter + loss + total_loss_epoch = total_loss_epoch + loss + loss.backward() + optimizer.step() + num_iter = num_iter + 1 + if self.log_after != 0 and num_iter % self.log_after == 0: + if logging: + file_writer.add_scalar(tag="cross_entropy_loss", + scalar_value=total_loss_iter / self.log_after, + global_step=num_iter) + if verbose: + print(''.join(['\nEpoch: {}', + ' Iter: {}, cross_entropy_loss: {}']).format(epoch, num_iter, + total_loss_iter / self.log_after)) + total_loss_iter = 0 + if not silent: + pbar.update(1) + if not silent: + pbar.close() + if verbose: + print(''.join(['Epoch: {}', + ' cross_entropy_loss: {}\n']).format(epoch, + total_loss_epoch / len(train_ids))) + if self.checkpoint_after_iter != 0 and epoch % self.checkpoint_after_iter == self.checkpoint_after_iter - 1: + snapshot_name = '{}/checkpoint_epoch_{}'.format(checkpoints_folder, epoch) + # Save checkpoint with full information for training state + self.save(path=snapshot_name, optimizer=optimizer, scheduler=scheduler, + current_epoch=epoch, max_dt_boxes=max_dt_boxes) + total_loss_epoch = 0 + scheduler.step() + if logging: + file_writer.close() + # if not silent and verbose: + # print("Model trainable parameters:", self.count_parameters()) + + def eval(self, dataset, verbose=True, split='test', boxes_sorted=False, max_dt_boxes=400, eval_folder=None, + use_ssd=False, datasets_folder='./datasets'): + + # Load dataset + dataset_nms = Dataset_NMS(path=datasets_folder, dataset_name=dataset, split=split, use_ssd=use_ssd) + + if self.classes is None: + self.classes = dataset_nms.classes + self.class_ids = dataset_nms.class_ids + + annotations_filename = str.lower(dataset) + '_' + split + '.json' + + if eval_folder is None: + eval_folder = os.path.join(self.parent_dir, self.experiment_name, 'eval') + if not os.path.isdir(eval_folder): + os.mkdir(eval_folder) + output_file = os.path.join(eval_folder, 'detections.json') + + # Model initialization if needed + if self.model is None and self.checkpoint_load_iter != 0: + # No model loaded, initializing new + self.init_model() + checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) + checkpoint_folder = os.path.join(self.parent_dir, self.experiment_name, 'checkpoints') + checkpoint_full_path = os.path.join(checkpoint_folder, checkpoint_name) + self.load(path=checkpoint_full_path, verbose=verbose) + + elif self.model is None: + raise AttributeError("self.model is None. Please load a model or set checkpoint_load_iter.") + + if self.app_feats == 'fmod' and (self.fMoD.mean is None or self.fMoD.std is None): + fmod_mean_std = load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, + fmod_pyramid_lvl=self.fmod_pyramid_lvl, + datasets_folder=datasets_folder, verbose=verbose) + self.fMoD.set_mean_std(mean_values=fmod_mean_std['mean'], std_values=fmod_mean_std['std']) + + self.model = self.model.eval() # Change model state to evaluation + if self.device == "cuda": + self.model = self.model.cuda() + + # Change model state to evaluation + self.model = self.model.eval() + if self.device == "cuda": + self.model = self.model.cuda() + + train_ids = np.arange(len(dataset_nms.src_data)) + nms_results = [] + pbar_eval = None + if verbose: + pbarDesc = "Evaluation progress" + pbar_eval = tqdm(desc=pbarDesc, total=len(train_ids)) + for sample_id in train_ids: + image_fln = dataset_nms.src_data[sample_id]['filename'] + + image_path = os.path.join(datasets_folder, dataset, image_fln) + img_res = dataset_nms.src_data[sample_id]['resolution'][::-1] + # Single class NMS only. + class_index = 1 + if len(dataset_nms.src_data[sample_id]['dt_boxes'][class_index]) > 0: + dt_boxes = torch.tensor(dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 0:4]).float() + dt_scores = torch.tensor(dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 4]).float() + if not boxes_sorted: + dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) + dt_boxes = dt_boxes[dt_scores_ids] + else: + continue + + if self.device == "cuda": + dt_boxes = dt_boxes.cuda() + dt_scores = dt_scores.cuda() + + val_ids = torch.logical_and((dt_boxes[:, 2] - dt_boxes[:, 0]) > 4, + (dt_boxes[:, 3] - dt_boxes[:, 1]) > 4) + dt_boxes = dt_boxes[val_ids, :] + dt_scores = dt_scores[val_ids] + + if self.iou_filtering is not None and 1.0 > self.iou_filtering > 0: + dt_boxes, dt_scores = apply_torchNMS(boxes=dt_boxes, scores=dt_scores, iou_thres=self.iou_filtering) + + dt_boxes = dt_boxes[:max_dt_boxes] + dt_scores = dt_scores[:max_dt_boxes] + app_feats = None + if self.app_feats == 'fmod': + img = Image.open(image_path) + img = img.convert(format='channels_last', channel_order='bgr') + self.fMoD.extract_maps(img=img, augm=True) + app_feats = self.fMoD.extract_FMoD_feats(dt_boxes) + app_feats = torch.unsqueeze(app_feats, dim=1) + elif self.app_feats == 'zeros': + app_feats = torch.zeros([dt_boxes.shape[0], self.app_input_dim]) + if self.device == 'cuda': + app_feats = app_feats.cuda() + elif self.app_feats == 'custom': + raise AttributeError("Custom appearance-based features are not yet supported.") + msk = compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) + q_geom_feats, k_geom_feats = compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, + resolution=img_res) + with torch.no_grad(): + preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, + app_feats=app_feats) + bboxes = dt_boxes.cpu().numpy().astype('float64') + for j in range(len(preds)): + nms_results.append({ + 'image_id': dataset_nms.src_data[sample_id]['id'], + 'bbox': [bboxes[j][0], bboxes[j][1], bboxes[j][2] - bboxes[j][0], bboxes[j][3] - bboxes[j][1]], + 'category_id': class_index, + 'score': np.float64(preds[j]) + }) + pbar_eval.update(1) + pbar_eval.close() + if verbose: + print('Writing results json to {}'.format(output_file)) + with open(output_file, 'w') as fid: + json.dump(nms_results, fid, indent=2) + eval_result = run_coco_eval(gt_file_path=os.path.join(dataset_nms.path, 'annotations', annotations_filename), + dt_file_path=output_file, only_classes=[1], + verbose=verbose, max_dets=[max_dt_boxes]) + for i in range(len(eval_result)): + print('Evaluation results (num_dets={})'.format(str(eval_result[i][1]))) + print(eval_result[i][0][0][1]) + print(eval_result[i][0][1][1]) + print(eval_result[i][0][2][1]) + print(eval_result[i][0][3][1]) + print('\n') + + def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoch=None, max_dt_boxes=800): + """ + Method for saving the current model in the path provided + :param path: path for the model to be saved + :type path: str + :param verbose: whether to print a success message or not, defaults to False + :type verbose: bool, optional + :param optimizer: the optimizer used for training + :type optimizer: Optimizer PyTorch object + :param scheduler: the scheduler used for training + :type scheduler: Scheduler PyTorch object + :param current_epoch: the current epoch id + :type current_epoch: int + """ + path = path.split('.')[0] + custom_dict = {'state_dict': self.model.state_dict(), 'optimizer': optimizer.state_dict(), + 'scheduler': scheduler.state_dict(), 'current_epoch': current_epoch} + torch.save(custom_dict, path + '.pth') + + metadata = {"model_paths": [os.path.basename(path) + '.pth'], "framework": "pytorch", "has_data": False, + "inference_params": {}, "optimized": False, "optimizer_info": {}, "backbone": {}, + "format": "pth", "classes": self.classes, "app_feats": self.app_feats, + "lq_dim": self.lq_dim, "sq_dim": self.sq_dim, "num_JPUs": self.num_JPUs, + "geom_input_dim": self.geom_input_dim, "app_input_dim": self.app_input_dim, + "max_dt_boxes": max_dt_boxes} + if self.app_feats == 'fmod': + metadata["fmod_map_type"] = self.fmod_map_type + metadata["fmod_map_bin"] = self.fmod_map_bin + metadata["fmod_roi_pooling_dim"] = self.fmod_roi_pooling_dim + metadata["fmod_map_res_dim"] = self.fmod_map_res_dim + metadata["fmod_pyramid_lvl"] = self.fmod_pyramid_lvl + + with open(path + '.json', 'w', encoding='utf-8') as f: + json.dump(metadata, f, ensure_ascii=False, indent=4) + if verbose: + print("Saved Pytorch model.") + + def init_model(self): + if self.model is None: + self.model = Seq2SeqNet(dropout=self.dropout, use_app_feats=self.use_app_feats, + app_input_dim=self.app_input_dim, + geom_input_dim=self.geom_input_dim, lq_dim=self.lq_dim, sq_dim=self.sq_dim, + num_JPUs=self.num_JPUs, device=self.device) + for p in self.model.parameters(): + if p.dim() > 1: + nn.init.xavier_uniform_(p) + else: + raise UserWarning("Tried to initialize model while model is already initialized.") + + def load(self, path, verbose=False): + """ + Loads the model from inside the path provided, based on the metadata .json file included + :param path: path of the checkpoint file was saved + :type path: str + :param verbose: whether to print success message or not, defaults to 'False' + :type verbose: bool, optional + """ + model_name = os.path.basename(os.path.normpath(path)).split('.')[0] + dir_path = os.path.dirname(os.path.normpath(path)) + + if verbose: + print("Model name:", model_name, "-->", os.path.join(dir_path, model_name + ".json")) + with open(os.path.join(dir_path, model_name + ".json")) as f: + metadata = json.load(f) + pth_path = os.path.join(dir_path, metadata["model_paths"][0]) + if verbose: + print("Loading checkpoint:", pth_path) + try: + checkpoint = torch.load(pth_path, map_location=torch.device(self.device)) + except FileNotFoundError as e: + e.strerror = "File " + pth_path + "not found." + raise e + + self.assign_params(metadata=metadata, verbose=verbose) + self.init_model() + self.load_state(checkpoint) + if self.device == 'cuda': + self.model = self.model.cuda() + if verbose: + print("Loaded parameters and metadata.") + return True + + def assign_params(self, metadata, verbose): + + if verbose and self.geom_input_dim is not None and self.geom_input_dim != metadata["geom_input_dim"]: + print("Incompatible value for the attribute \"geom_input_dim\". It is now set to: " + + str(metadata["geom_input_dim"])) + self.geom_input_dim = metadata["geom_input_dim"] + if verbose and self.app_input_dim is not None and self.app_input_dim != metadata["app_input_dim"]: + print("Incompatible value for the attribute \"app_input_dim\". It is now set to: " + + str(metadata["app_input_dim"])) + self.app_input_dim = metadata["app_input_dim"] + if verbose and self.app_feats != metadata["app_feats"]: + print("Incompatible value for the attribute \"app_feats\". It is now set to: " + + str(metadata["app_feats"])) + self.app_feats = metadata["app_feats"] + if verbose and self.fmod_map_type is not None and self.fmod_map_type != metadata["fmod_map_type"]: + print("Incompatible value for the attribute \"fmod_map_type\". It is now set to: " + + str(metadata["fmod_map_type"])) + self.fmod_map_type = metadata["fmod_map_type"] + if verbose and self.fmod_map_bin is not None and self.fmod_map_bin != metadata["fmod_map_bin"]: + print("Incompatible value for the attribute \"fmod_map_bin\". It is now set to: " + + str(metadata["fmod_map_bin"])) + self.fmod_map_bin = metadata["fmod_map_bin"] + if verbose and self.fmod_roi_pooling_dim is not None and \ + self.fmod_roi_pooling_dim != metadata["fmod_roi_pooling_dim"]: + print("Incompatible value for the attribute \"fmod_roi_pooling_dim\". It is now set to: " + + str(metadata["fmod_roi_pooling_dim"])) + self.fmod_roi_pooling_dim = metadata["fmod_roi_pooling_dim"] + if verbose and self.fmod_map_res_dim is not None and \ + self.fmod_map_res_dim != metadata["fmod_map_res_dim"]: + print("Incompatible value for the attribute \"fmod_map_res_dim\". It is now set to: " + + str(metadata["fmod_map_res_dim"])) + self.fmod_map_res_dim = metadata["fmod_map_res_dim"] + if verbose and self.fmod_pyramid_lvl is not None and \ + self.fmod_pyramid_lvl != metadata["fmod_pyramid_lvl"]: + print("Incompatible value for the attribute \"fmod_pyramid_lvl\". It is now set to: " + + str(metadata["fmod_pyramid_lvl"])) + self.fmod_pyramid_lvl = metadata["fmod_pyramid_lvl"] + if verbose and self.lq_dim is not None and \ + self.lq_dim != metadata["lq_dim"]: + print("Incompatible value for the attribute \"lq_dim\". It is now set to: " + + str(metadata["lq_dim"])) + self.lq_dim = metadata["lq_dim"] + if verbose and self.sq_dim is not None and self.sq_dim != metadata["sq_dim"]: + print("Incompatible value for the attribute \"sq_dim\". It is now set to: " + + str(metadata["sq_dim"])) + self.sq_dim = metadata["sq_dim"] + if verbose and self.num_JPUs is not None and self.num_JPUs != metadata["num_JPUs"]: + print("Incompatible value for the attribute \"num_JPUs\". It is now set to: " + + str(metadata["num_JPUs"])) + self.num_JPUs = metadata["num_JPUs"] + if verbose and 'max_dt_boxes' in metadata: + print('Model is trained with as ' + str(metadata['max_dt_boxes']) + 'its maximum number of detections.') + + def load_state(self, checkpoint=None): + if checkpoint is None: + for p in self.model.parameters(): + if p.dim() > 1: + nn.init.xavier_uniform_(p) + else: + try: + source_state = checkpoint['state_dict'] + except KeyError: + source_state = checkpoint + target_state = self.model.state_dict() + new_target_state = collections.OrderedDict() + for target_key, target_value in target_state.items(): + if target_key in source_state and source_state[target_key].size() == target_state[target_key].size(): + new_target_state[target_key] = source_state[target_key] + else: + new_target_state[target_key] = target_state[target_key] + # print('[WARNING] Not found pre-trained parameters for {}'.format(target_key)) + + self.model.load_state_dict(new_target_state) + + def count_parameters(self): + """ + Returns the number of the model's trainable parameters. + :return: number of trainable parameters + :rtype: int + """ + if self.model is None: + raise UserWarning("Model is not initialized, can't count trainable parameters.") + return sum(p.numel() for p in self.model.parameters() if p.requires_grad) + + def download(self, path=None, mode="pretrained", verbose=False, + url=OPENDR_SERVER_URL + "perception/pose_estimation/lightweight_open_pose/"): + print('ToDo') + + def infer(self, boxes=None, scores=None, boxes_sorted=False, max_dt_boxes=1200, img_res=None, threshold=0.1): + bounding_boxes = BoundingBoxList([]) + if scores.shape[0] == 0: + return bounding_boxes + if scores.shape[1]>1: + raise ValueError('Multi-class NMS is not supported in Seq2Seq-NMS yet.') + if boxes.shape[0] != scores.shape[0]: + raise ValueError('Scores and boxes must have the same size in dim 0.') + if self.device == "cuda": + boxes = boxes.cuda() + scores = scores.cuda() + + scores = scores.squeeze(-1) + keep_ids = torch.where(scores > 0.05)[0] + scores = scores[keep_ids] + boxes = boxes[keep_ids, :] + if not boxes_sorted: + scores, scores_ids = torch.sort(scores, dim=0, descending=True) + boxes = boxes[scores_ids] + + + val_ids = torch.logical_and((boxes[:, 2] - boxes[:, 0]) > 4, + (boxes[:, 3] - boxes[:, 1]) > 4) + boxes = boxes[val_ids, :] + scores = scores[val_ids] + + if self.iou_filtering is not None and 1.0 > self.iou_filtering > 0: + boxes, scores = apply_torchNMS(boxes=boxes, scores=scores, iou_thres=self.iou_filtering) + + boxes = boxes[:max_dt_boxes] + scores = scores[:max_dt_boxes] + app_feats = None + + if self.app_feats == 'fmod': + app_feats = self.fMoD.extract_FMoD_feats(boxes) + app_feats = torch.unsqueeze(app_feats, dim=1) + elif self.app_feats == 'zeros': + app_feats = torch.zeros([boxes.shape[0], self.app_input_dim]) + if self.device == 'cuda': + app_feats = app_feats.cuda() + elif self.app_feats == 'custom': + raise AttributeError("Custom appearance-based features are not yet supported.") + + msk = compute_mask(boxes, iou_thres=0.2, extra=0.1) + q_geom_feats, k_geom_feats = compute_geometrical_feats(boxes=boxes, scores=scores, + resolution=img_res) + + with torch.no_grad(): + preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, + app_feats=app_feats) + + mask = torch.where(preds > threshold)[0] + if mask.size == 0: + return BoundingBoxList([]) + preds = preds[mask].cpu().detach().numpy() + boxes = boxes[mask, :].cpu().numpy() + + for idx, box in enumerate(boxes): + bbox = BoundingBox(left=box[0], top=box[1], + width=box[2] - box[0], + height=box[3] - box[1], + name=0, + score=preds[idx]) + bounding_boxes.data.append(bbox) + return bounding_boxes, [boxes, np.zeros(scores.shape[0]), preds] + + def optimize(self, **kwargs): + """This method is not used in this implementation.""" + raise NotImplementedError + + def reset(self): + """This method is not used in this implementation.""" + return NotImplementedError + + def run_nms(self, boxes=None, scores=None, img=None, threshold=0.2, boxes_sorted=False, top_k=400): + + if self.app_feats == 'fmod': + if not isinstance(img, Image): + img = Image(img) + _img = img.convert("channels_last", "rgb") + self.fMoD.extract_maps(img=_img, augm=False) + + if isinstance(boxes, np.ndarray): + boxes = torch.tensor(boxes, device=self.device) + elif torch.is_tensor(boxes): + if self.device == 'cpu': + boxes = boxes.cpu() + elif self.device == 'cuda': + boxes = boxes.cuda() + + if isinstance(scores, np.ndarray): + scores = torch.tensor(scores, device=self.device) + elif torch.is_tensor(scores): + if self.device == 'cpu': + scores = scores.cpu() + elif self.device == 'cuda': + scores = scores.cuda() + boxes = self.infer(boxes=boxes, scores=scores, boxes_sorted=boxes_sorted, max_dt_boxes=top_k, + img_res=img.opencv().shape[::-1][1:]) + return boxes + # draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) + + + +def apply_torchNMS(boxes, scores, iou_thres): + ids_nms = torchvision.ops.nms(boxes, scores, iou_thres) + scores = scores[ids_nms] + boxes = boxes[ids_nms] + return boxes, scores + + +def compute_mask(boxes=None, iou_thres=0.2, extra=0.1): + relations = filter_iou_boxes(boxes, iou_thres=iou_thres) + mask1 = torch.tril(relations).float() + mask2 = extra * torch.triu(relations, diagonal=1).float() + mask = mask1 + mask2 + return mask + + +def filter_iou_boxes(boxes=None, iou_thres=0.2): + ious = bb_intersection_over_union(boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1), + boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1)) + ids_boxes = ious >= iou_thres + return ids_boxes + + +def bb_intersection_over_union(boxAs=None, boxBs=None): + xA = torch.maximum(boxAs[:, :, 0], boxBs[:, :, 0]) + yA = torch.maximum(boxAs[:, :, 1], boxBs[:, :, 1]) + xB = torch.minimum(boxAs[:, :, 2], boxBs[:, :, 2]) + yB = torch.minimum(boxAs[:, :, 3], boxBs[:, :, 3]) + interAreas = torch.maximum(torch.zeros_like(xB), xB - xA + 1) * torch.maximum(torch.zeros_like(yB), yB - yA + 1) + boxAAreas = (boxAs[:, :, 2] - boxAs[:, :, 0] + 1) * (boxAs[:, :, 3] - boxAs[:, :, 1] + 1) + boxBAreas = (boxBs[:, :, 2] - boxBs[:, :, 0] + 1) * (boxBs[:, :, 3] - boxBs[:, :, 1] + 1) + ious = interAreas / (boxAAreas + boxBAreas - interAreas) + return ious + + +def compute_geometrical_feats(boxes, scores, resolution): + boxBs = boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1) + boxAs = boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1) + scoresBs = scores.unsqueeze(0).unsqueeze(-1).repeat(scores.shape[0], 1, 1) + scoresAs = scores.unsqueeze(1).unsqueeze(1).repeat(1, scores.shape[0], 1) + + scale_div = [resolution[0] / 20, resolution[1] / 20] + dx = ((boxBs[:, :, 0] - boxAs[:, :, 0] + boxBs[:, :, 2] - boxAs[:, :, 2]) / 2).unsqueeze(-1) + dy = ((boxBs[:, :, 1] - boxAs[:, :, 1] + boxBs[:, :, 3] - boxAs[:, :, 3]) / 2).unsqueeze(-1) + dxy = dx * dx + dy * dy + dxy = dxy / (scale_div[0] * scale_div[0] + scale_div[1] * scale_div[1]) + dx = (dx / scale_div[0]) + dy = (dy / scale_div[1]) + sx = boxBs[:, :, 2] - boxBs[:, :, 0] + sx_1 = (sx / (boxAs[:, :, 2] - boxAs[:, :, 0])).unsqueeze(-1) + sx_2 = (sx / scale_div[0]).unsqueeze(-1) + sy = boxBs[:, :, 3] - boxBs[:, :, 1] + sy_1 = (sy / (boxAs[:, :, 3] - boxAs[:, :, 1])).unsqueeze(-1) + sy_2 = (sy / scale_div[1]).unsqueeze(-1) + scl = (boxBs[:, :, 2] - boxBs[:, :, 0]) * (boxBs[:, :, 3] - boxBs[:, :, 1]) + scl_1 = (scl / ((boxAs[:, :, 2] - boxAs[:, :, 0]) * (boxAs[:, :, 3] - boxAs[:, :, 1]))).unsqueeze(-1) + scl_2 = (scl / (scale_div[0] * scale_div[1])).unsqueeze(-1) + del scl + + scr_1 = 5 * scoresBs + scr_2 = scr_1 - 5 * scoresAs + + sr_1 = torch.unsqueeze((boxBs[:, :, 3] - boxBs[:, :, 1]) / (boxBs[:, :, 2] - boxBs[:, :, 0]), dim=-1) + sr_2 = torch.unsqueeze(((boxBs[:, :, 3] - boxBs[:, :, 1]) / (boxBs[:, :, 2] - boxBs[:, :, 0])) / ( + (boxAs[:, :, 3] - boxAs[:, :, 1]) / (boxAs[:, :, 2] - boxAs[:, :, 0])), dim=-1) + + ious = 5 * (bb_intersection_over_union(boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1), + boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1))).unsqueeze(-1) + enc_vers_all = torch.cat((dx, dy, dxy, sx_1, sx_2, sy_1, sy_2, ious, scl_1, scl_2, scr_1, scr_2, sr_1, sr_2), dim=2) + enc_vers = enc_vers_all.diagonal(dim1=0, dim2=1).transpose(0, 1).unsqueeze(1) + return enc_vers, enc_vers_all + + +def matching_module(scores, dt_boxes, gt_boxes, iou_thres, device='cuda'): + sorted_indices = torch.argsort(-scores, dim=0) + labels = torch.zeros(len(dt_boxes)) + if device == 'cuda': + labels = labels.cuda() + if gt_boxes.shape[0] == 0: + return labels.unsqueeze(-1) + assigned_GT = -torch.ones(len(gt_boxes)) + r = torch.tensor([-1, -1, -1, -1]).float().unsqueeze(0).unsqueeze(0) + if device == 'cuda': + r = r.cuda() + for s in sorted_indices: + gt_boxes_c = gt_boxes.clone().unsqueeze(0) + gt_boxes_c[0, assigned_GT > -1, :] = r + ious = bb_intersection_over_union(boxAs=dt_boxes[s].clone().unsqueeze(0), boxBs=gt_boxes_c) + annot_iou, annot_box_id = torch.sort(ious.squeeze(), descending=True) + if annot_box_id.ndim > 0: + annot_box_id = annot_box_id[0] + annot_iou = annot_iou[0] + if annot_iou > iou_thres: + assigned_GT[annot_box_id] = s + labels[s] = 1 + return labels.unsqueeze(-1) + + +def run_coco_eval(dt_file_path=None, gt_file_path=None, only_classes=None, max_dets=None, + verbose=False): + if max_dets is None: + max_dets = [200, 400, 600, 800, 1000, 1200] + results = [] + sys.stdout = open(os.devnull, 'w') + for i in range(len(max_dets)): + coco = COCO(gt_file_path) + coco_dt = coco.loadRes(dt_file_path) + cocoEval = COCOeval(coco, coco_dt, 'bbox') + cocoEval.params.iouType = 'bbox' + cocoEval.params.useCats = True + cocoEval.params.catIds = only_classes + cocoEval.params.maxDets = [max_dets[i]] + cocoEval.evaluate() + results.append([summarize_nms(coco_eval=cocoEval, maxDets=max_dets[i]), max_dets[i]]) + # print(results[i]) + del cocoEval, coco_dt, coco + sys.stdout = sys.__stdout__ + return results + + +def summarize_nms(coco_eval=None, maxDets=100): + def summarize(ap=1, iouThr=None, areaRng='all', maxDets=100): + p = coco_eval.params + iStr = ' {:<18} {} @[ IoU={:<9} | area={:>6s} | maxDets={:>3d} ] = {:0.3f}' + titleStr = 'Average Precision' if ap == 1 else 'Average Recall' + typeStr = '(AP)' if ap == 1 else '(AR)' + iouStr = '{:0.2f}:{:0.2f}'.format(p.iouThrs[0], p.iouThrs[-1]) \ + if iouThr is None else '{:0.2f}'.format(iouThr) + aind = [i for i, aRng in enumerate(p.areaRngLbl) if aRng == areaRng] + mind = [i for i, mDet in enumerate(p.maxDets) if mDet == maxDets] + if ap == 1: + # dimension of precision: [TxRxKxAxM] + s = coco_eval.eval['precision'] + # IoU + if iouThr is not None: + t = np.where(iouThr == p.iouThrs)[0] + s = s[t] + s = s[:, :, :, aind, mind] + else: + # dimension of recall: [TxKxAxM] + s = coco_eval.eval['recall'] + if iouThr is not None: + t = np.where(iouThr == p.iouThrs)[0] + s = s[t] + s = s[:, :, aind, mind] + if len(s[s > -1]) == 0: + mean_s = -1 + else: + mean_s = np.mean(s[s > -1]) + stat_str = iStr.format(titleStr, typeStr, iouStr, areaRng, maxDets, mean_s) + return [mean_s, stat_str] + + def summarizeDets(): + stats = [] + stat, stat_str = summarize(1, maxDets=maxDets) + stats.append([stat, stat_str]) + stat, stat_str = summarize(1, iouThr=.5, maxDets=maxDets) + stats.append([stat, stat_str]) + stat, stat_str = summarize(1, iouThr=.75, maxDets=maxDets) + stats.append([stat, stat_str]) + stat, stat_str = summarize(0, maxDets=maxDets) + stats.append([stat, stat_str]) + return stats + + coco_eval.accumulate() + summarized = summarizeDets() + return summarized + + +def drop_dets(boxes, scores, keep_ratio=0.85): + ids = np.arange(len(boxes)) + np.random.shuffle(ids) + ids_keep = ids[0:int(len(boxes) * keep_ratio)] + boxes_new = boxes[ids_keep, :] + scores_new = scores[ids_keep] + return boxes_new, scores_new + + +def load_FMoD_init_from_dataset(dataset=None, map_type='edgemap', fmod_pyramid_lvl=3, datasets_folder='./datasets', + map_bin=True, verbose=False): + fmod_dir = os.path.join(datasets_folder, dataset, 'FMoD') + if not os.path.exists(fmod_dir): + os.makedirs(fmod_dir, exist_ok=True) + map_type_c = map_type + if map_bin: + map_type_c = map_type_c + '_B' + fmod_filename = dataset + '_' + map_type_c + '_' + str(fmod_pyramid_lvl) + '.pkl' + fmod_filename = fmod_filename.lower() + fmod_stats = None + if not os.path.exists(os.path.join(fmod_dir, fmod_filename)): + file_url = os.path.join(OPENDR_SERVER_URL + 'perception/non-maximum_suppression/FMoD', fmod_filename) + try: + urlretrieve(file_url, os.path.join(fmod_dir, fmod_filename)) + except: + if verbose: + print('Normalization files not found on FTP server. Normalization will be performed setting \u03BC = ' + '0 and \u03C3 = 1.') + fmod_feats_dim = 0 + for i in range(0, fmod_pyramid_lvl): + fmod_feats_dim = fmod_feats_dim + 15 * (pow(4, i)) + return {'mean': np.zeros(fmod_feats_dim), 'std': np.ones(fmod_feats_dim)} + fmod_stats = load_FMoD_init(os.path.join(fmod_dir, fmod_filename)) + + return fmod_stats + + +def load_FMoD_init(path=None): + try: + with open(path, 'rb') as fp: + fmod_stats = pickle.load(fp) + map_type = list(fmod_stats.keys())[0] + fmod_stats = fmod_stats[map_type] + except EnvironmentError as e: + e.strerror = 'FMoD initialization .pkl file not found' + raise e + return fmod_stats + + +def compute_class_weights(pos_weights, max_dets=400, dataset_nms=None): + num_pos = np.ones([len(dataset_nms.classes), 1]) + num_bg = np.ones([len(dataset_nms.classes), 1]) + weights = np.zeros([len(dataset_nms.classes), 2]) + for i in range(len(dataset_nms.src_data)): + for cls_index in range(len(dataset_nms.classes)): + num_pos[cls_index] = num_pos[cls_index] + \ + min(max_dets, len(dataset_nms.src_data[i]['gt_boxes'][cls_index])) + num_bg[cls_index] = num_bg[cls_index] + max(0, min(max_dets, + len(dataset_nms.src_data[i]['dt_boxes'][cls_index])) - + min(max_dets, + len(dataset_nms.src_data[i]['gt_boxes'][cls_index]))) + for class_index in range(len(dataset_nms.classes)): + weights[class_index, 0] = (1 - pos_weights[class_index]) * (num_pos[class_index] + + num_bg[class_index]) / num_bg[class_index] + weights[class_index, 1] = pos_weights[class_index] * (num_pos[class_index] + + num_bg[class_index]) / num_pos[class_index] + return weights From 806d72623e06e71b4015321aef83dfc9e2844ac2 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 13:07:52 +0200 Subject: [PATCH 037/374] Delete nms_dataset.py --- .../nms/seq2seq_nms/algorithm/nms_dataset.py | 473 ------------------ 1 file changed, 473 deletions(-) delete mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/nms_dataset.py diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/nms_dataset.py deleted file mode 100644 index 325a6f9009..0000000000 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/nms_dataset.py +++ /dev/null @@ -1,473 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from opendr.engine.datasets import Dataset -import os -from urllib.request import urlretrieve -import ssl -import time -from zipfile import ZipFile -import tarfile -import gdown -import shutil -import pickle -import numpy as np -import math -from tqdm import tqdm -from opendr.perception.object_detection_2d import SingleShotDetectorLearner -from opendr.engine.data import Image -from opendr.perception.object_detection_2d.datasets.transforms import BoundingBoxListToNumpyArray -import json -from pycocotools.coco import COCO - - -class Dataset_NMS(Dataset): - def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, device='cuda'): - super().__init__() - available_dataset = ['COCO', 'PETS', 'CrowdHuman'] - self.dataset_sets = {'train': None, - 'val': None, - 'test': None} - if dataset_name not in available_dataset: - except_str = 'Unsupported dataset: ' + dataset_name + '. Currently available are:' - for j in range(len(available_dataset)): - except_str = except_str + ' \'' + available_dataset[j] + '\'' - if j < len(available_dataset) - 1: - except_str = except_str + ',' - except_str = except_str + '.' - raise ValueError(except_str) - - ssl._create_default_https_context = ssl._create_unverified_context - self.dataset_name = dataset_name - self.split = split - # self.__prepare_dataset() - self.path = os.path.join(path, dataset_name) - self.src_data = [] - if self.dataset_name == "PETS": - self.detector = 'JPD' - self.detector_type = 'default' - if use_ssd: - self.detector = 'SSD' - self.detector_type = 'custom' - - self.dataset_sets['train'] = 'train' - self.dataset_sets['val'] = 'val' - self.dataset_sets['test'] = 'test' - if self.dataset_sets[self.split] is None: - raise ValueError(self.split + ' split is not available...') - - if not os.path.exists(os.path.join(self.path, 'images/S1/L1')): - self.download( - 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S1_L1.tar.bz2', - download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) - if not os.path.exists(os.path.join(self.path, 'images/S1/L2')): - self.download( - 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S1_L2.tar.bz2', - download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) - if not os.path.exists(os.path.join(self.path, 'images/S2/L1')): - self.download( - 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L1.tar.bz2', - download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) - if not os.path.exists(os.path.join(self.path, 'images/S2/L2')): - self.download( - 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L2.tar.bz2', - download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) - if not os.path.exists(os.path.join(self.path, 'images/S2/L3')): - self.download( - 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L3.tar.bz2', - download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) - if not os.path.exists(os.path.join(self.path, 'images/S3/Multiple_Flow')): - self.download( - 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S3_MF.tar.bz2', - download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) - if not os.path.exists( - os.path.join(self.path, 'annotations', 'pets_' + self.dataset_sets[self.split] + '.json')): - self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_annotations_json.zip', - download_path=os.path.join(self.path, 'annotations'), file_format="zip", - create_dir=True) - pkl_filename = os.path.join(self.path, - 'data_' + self.detector + '_' + self.dataset_sets[self.split] + '_pets.pkl') - if not os.path.exists(pkl_filename): - ssd = None - if use_ssd: - ssd = SingleShotDetectorLearner(device=device) - ssd.download(".", mode="pretrained") - ssd.load("./ssd_default_person", verbose=True) - if not os.path.exists( - os.path.join(self.path, 'detections', - 'PETS-' + self.dataset_sets[self.split] + '_siyudpm_dets.idl')): - self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_detections.zip', - download_path=os.path.join(self.path, 'detections'), file_format="zip", - create_dir=True) - if not os.path.exists( - os.path.join(self.path, 'annotations', 'PETS-' + self.dataset_sets[self.split] + '.idl')): - self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_annotations.zip', - download_path=os.path.join(self.path, 'annotations'), file_format="zip", - create_dir=True) - with open(os.path.join(self.path, 'annotations', - 'PETS-' + self.dataset_sets[self.split] + '.idl')) as fp_gt: - fp_dt = None - if self.detector_type == 'default': - fp_dt = open(os.path.join(self.path, 'detections', - 'PETS-' + self.dataset_sets[self.split] + '_siyudpm_dets.idl')) - print('Preparing PETS ' + self.dataset_sets[self.split] + ' set...') - current_id = 0 - number_samples = 1696 - if self.split == 'val': - current_id = 1696 - number_samples = 240 - elif self.split == 'test': - current_id = 1936 - number_samples = 436 - pbarDesc = "Overall progress" - pbar = tqdm(desc=pbarDesc, total=number_samples) - if self.detector_type == 'default': - line_dt = fp_dt.readline() - line_gt = fp_gt.readline() - while line_gt: - remove_strings = ['PETS09-', '\"', ':', '(', ')', ',', '', ';'] - data_gt = line_gt.replace(':', ' ') - for j in range(len(remove_strings)): - data_gt = data_gt.replace(remove_strings[j], '') - data_gt = data_gt.split() - filename_gt = data_gt[0][0:2] + '/' + data_gt[0][2:] - if filename_gt[0:6] == 'S2/L1/': - filename_gt = filename_gt.replace('img/00', 'Time_12-34/View_001/frame_') - num = int(filename_gt[-8:-4]) - 1 - filename_gt = filename_gt[:-8] + str(num).zfill(4) + '.jpg' - if filename_gt[0:6] == 'S2/L2/': - filename_gt = filename_gt.replace('img/00', 'Time_14-55/View_001/frame_') - num = int(filename_gt[-8:-4]) - 1 - filename_gt = filename_gt[:-8] + str(num).zfill(4) + '.jpg' - if filename_gt[0:2] == 'S3': - filename_gt = filename_gt.replace('_MF', 'Multiple_Flow') - - if self.detector_type == 'default': - data_dt = line_dt.replace(':', ' ') - for j in range(len(remove_strings)): - data_dt = data_dt.replace(remove_strings[j], '') - data_dt = data_dt.split() - filename_dt = data_dt[0][0:2] + '/' + data_dt[0][2:] - if filename_dt[0:6] == 'S2/L1/': - filename_dt = filename_dt.replace('img/00', 'Time_12-34/View_001/frame_') - num = int(filename_dt[-8:-4]) - 1 - filename_dt = filename_dt[:-8] + str(num).zfill(4) + '.jpg' - if filename_dt[0:6] == 'S2/L2/': - filename_dt = filename_dt.replace('img/00', 'Time_14-55/View_001/frame_') - num = int(filename_dt[-8:-4]) - 1 - filename_dt = filename_dt[:-8] + str(num).zfill(4) + '.jpg' - if filename_dt[0:2] == 'S3': - filename_dt = filename_dt.replace('_MF', 'Multiple_Flow') - if filename_gt != filename_dt: - raise ValueError('Errors in files...') - - img = Image.open(os.path.join(self.path, 'images/', filename_gt)) - - dt_boxes = [] - if self.detector_type == 'default': - for i in range(1, (len(data_dt)), 5): - dt_box = np.array((float(data_dt[i]), float(data_dt[i + 1]), float(data_dt[i + 2]), - float(data_dt[i + 3]), 1 / (1 + math.exp(- float(data_dt[i + 4]))))) - dt_boxes.append(dt_box) - else: - bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, - nms_topk=6000, post_nms=6000) - bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) - bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] - bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] - bboxes_list = bboxes_list[:5000, :] - for b in range(len(bboxes_list)): - dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], - bboxes_list[b, 3], bboxes_list[b, 4][0]])) - gt_boxes = [] - for i in range(1, (len(data_gt)), 5): - gt_box = np.array((float(data_gt[i]), float(data_gt[i + 1]), float(data_gt[i + 2]), - float(data_gt[i + 3]))) - gt_boxes.append(gt_box) - self.src_data.append({ - 'id': current_id, - 'filename': os.path.join('images', filename_gt), - 'resolution': img.opencv().shape[0:2][::-1], - 'gt_boxes': [np.asarray([]), np.asarray(gt_boxes)], - 'dt_boxes': [np.asarray([]), np.asarray(dt_boxes)] - }) - current_id = current_id + 1 - pbar.update(1) - if self.detector_type == 'default': - line_dt = fp_dt.readline() - line_gt = fp_gt.readline() - pbar.close() - if self.detector_type == 'default': - fp_dt.close() - with open(pkl_filename, 'wb') as handle: - pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) - else: - with open(pkl_filename, 'rb') as fp_pkl: - self.src_data = pickle.load(fp_pkl) - - self.classes = ['background', 'human'] - self.class_ids = [-1, 1] - - elif self.dataset_name == "CrowdHuman": - splits = ['train', 'val'] - if self.split not in splits: - raise ValueError(self.split + ' split is not available...') - self.detector = 'YOLOv4' - self.detector_type = 'default' - if use_ssd: - self.detector = 'SSD' - self.detector_type = 'custom' - if not os.path.exists(os.path.join(self.path, 'images/train')): - os.makedirs(os.path.join(self.path, 'images/train'), exist_ok=True) - urls = ['https://drive.google.com/file/d/134QOvaatwKdy0iIeNqA_p-xkAhkV4F8Y/view?usp=sharing', - 'https://drive.google.com/u/0/uc?id=17evzPh7gc1JBNvnW1ENXLy5Kr4Q_Nnla', - 'https://drive.google.com/u/0/uc?id=1tdp0UCgxrqy1B6p8LkR-Iy0aIJ8l4fJW'] - outputs = [os.path.join(self.path, 'CrowdHuman_train01.zip'), 'CrowdHuman_train02.zip', - 'CrowdHuman_train03.zip'] - for i in range(0, len(urls)): - gdown.download(urls[i], outputs[i], quiet=False) - zip_path = os.path.join('.', outputs[i]) - with ZipFile(zip_path, 'r') as zip_ref: - download_path = os.path.join(self.path, 'images', 'train') - zip_ref.extractall(download_path) - os.remove(zip_path) - - if not os.path.exists(os.path.join(self.path, 'images/val')): - os.makedirs(os.path.join(self.path, 'images/val'), exist_ok=True) - url = 'https://drive.google.com/u/0/uc?id=18jFI789CoHTppQ7vmRSFEdnGaSQZ4YzO' - output = 'CrowdHuman_val.zip' - gdown.download(url, output, quiet=False) - zip_path = os.path.join('.', output) - with ZipFile(zip_path, 'r') as zip_ref: - download_path = os.path.join(self.path, 'images', 'val') - zip_ref.extractall(download_path) - os.remove(zip_path) - - if not os.path.exists( - os.path.join(self.path, 'data_' + self.detector + '_' + self.split + '_crowdhuman.pkl')): - # Download detections from FTP server - ssd = None - if use_ssd: - ssd = SingleShotDetectorLearner(device=device) - ssd.download(".", mode="pretrained") - ssd.load("./ssd_default_person", verbose=True) - - # Download annotations from official CrowdHuman GoogleDrive repo - if not os.path.exists(os.path.join(self.path, 'annotations', 'annotation_' + self.split + '.odgt')): - os.makedirs(os.path.join(self.path, 'annotations'), exist_ok=True) - url = None - if self.split == 'train': - url = 'https://drive.google.com/u/0/uc?id=1UUTea5mYqvlUObsC1Z8CFldHJAtLtMX3&export=download' - elif self.split == 'val': - url = 'https://drive.google.com/u/0/uc?id=10WIRwu8ju8GRLuCkZ_vT6hnNxs5ptwoL&export=download' - output = 'annotation_' + self.split + '.odgt' - gdown.download(url, output, quiet=False) - shutil.move(os.path.join('.', output), - os.path.join('.', 'datasets', 'CrowdHuman', 'annotations', self.split)) - - with open(os.path.join(self.path, 'annotations', 'annotation_' + self.split + '.odgt')) as fp_gt: - data_dt = None - if self.detector_type == 'default': - fp_dt = open( - os.path.join(self.path, 'detections', 'det_data_' + self.split + '_crowdhuman.pkl'), 'rb') - data_dt = pickle.load(fp_dt) - line = fp_gt.readline() - i = 0 - while line: - annotations = json.loads(line) - img = Image.open(os.path.join(self.path, 'images/' + self.split, annotations['ID'] + '.jpg')) - dt_boxes = [] - if self.detector_type == 'default' and data_dt[i]['id'] != annotations['ID']: - continue - elif self.detector_type == 'default': - dt_boxes = data_dt[i]['dt_boxes'] - elif self.detector_type == 'custom' and self.detector == 'SSD': - bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, - nms_topk=10000, post_nms=10000) - bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) - bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] - bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] - bboxes_list = bboxes_list[:8000, :] - for b in range(len(bboxes_list)): - dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], - bboxes_list[b, 3], bboxes_list[b, 4][0]])) - gt_boxes = [] - for j in range(len(annotations['gtboxes'])): - if annotations['gtboxes'][j]['tag'] == 'person': - gt_box = annotations['gtboxes'][j]['fbox'] - gt_box[2] = gt_box[2] + gt_box[0] - gt_box[3] = gt_box[3] + gt_box[1] - gt_boxes.append(gt_box) - self.src_data.append({ - 'id': annotations['ID'], - 'filename': annotations['ID'] + '.jpg', - 'resolution': img.opencv().shape[0:2][::-1], - 'gt_boxes': [np.asarray([]), np.asarray(gt_boxes)], - 'dt_boxes': [np.asarray([]), np.asarray(dt_boxes)] - }) - line = fp_gt.readline() - i = i + 1 - with open(os.path.join(self.path, 'data_' + self.split + '_crowdhuman.pkl'), 'wb') as handle: - pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) - else: - with open(os.path.join(self.path, 'data_' + self.split + '_crowdhuman.pkl'), 'rb') as fp_dt: - self.src_data = pickle.load(fp_dt) - elif self.dataset_name == "COCO": - self.dataset_sets['train'] = 'train' - self.dataset_sets['val'] = 'minival' - self.dataset_sets['test'] = 'valminusminival' - imgs_split = None - if self.dataset_sets[self.split] is None: - raise ValueError(self.split + ' split is not available...') - elif self.dataset_sets[self.split] == 'train': - imgs_split = 'train2014' - else: - imgs_split = 'val2014' - self.detector = 'YOLOv4' - self.detector_type = 'default' - ssd = None - if use_ssd: - self.detector = 'SSD' - self.detector_type = 'custom' - ssd = SingleShotDetectorLearner(device=device) - ssd.download(".", mode="pretrained") - ssd.load("./ssd_default_person", verbose=True) - if not os.path.exists(os.path.join(self.path, imgs_split)): - self.download('http://images.cocodataset.org/zips/' + imgs_split +'.zip', - download_path=os.path.join(self.path), file_format="zip", - create_dir=True) - pkl_filename = os.path.join(self.path, 'data_' + self.detector + '_' + self.dataset_sets[self.split] + '_coco.pkl') - if not os.path.exists(pkl_filename): - if not os.path.exists(os.path.join(self.path, 'annotations', 'instances_' + imgs_split +'.json')): - self.download('http://images.cocodataset.org/annotations/annotations_trainval2014.zip', - download_path=os.path.join(self.path), file_format="zip", create_dir=True) - if not os.path.exists(os.path.join(self.path, 'detections', 'coco_2014_' + self.dataset_sets[self.split]+ '_FRCN_train.pkl')): - self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/coco_2014_FRCN.tar.gz', - download_path=os.path.join(self.path, 'detections'), file_format='tar.gz', - create_dir=True) - with open(os.path.join(self.path, 'detections', - 'coco_2014_' + self.dataset_sets[self.split] + '_FRCN_train.pkl'), 'rb') as f: - dets_default = pickle.load(f, encoding='latin1') - annots = COCO(annotation_file=os.path.join(self.path, 'annotations', 'instances_' + imgs_split + '.json')) - pbarDesc = "Overall progress" - pbar = tqdm(desc=pbarDesc, total=len(dets_default[1])) - for i in range(len(dets_default[1])): - dt_boxes = [] - img_info = annots.loadImgs([dets_default[1][i]])[0] - img = Image.open(os.path.join(self.path, imgs_split, img_info["file_name"])) - if self.detector_type == 'default': - dt_boxes = dets_default[0][1][i] - elif self.detector == 'SSD': - bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, - nms_topk=6000, post_nms=6000) - bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) - if bboxes_list.shape[0]>0: - bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] - if bboxes_list.shape[0] > 0: - bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] - bboxes_list = bboxes_list[:5000, :] - for b in range(len(bboxes_list)): - dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], - bboxes_list[b, 3], bboxes_list[b, 4][0]])) - #if len(dt_boxes) > 0: - # dt_boxes[:, 2] = dt_boxes[:, 0] + dt_boxes[:, 2] - # dt_boxes[:, 3] = dt_boxes[:, 1] + dt_boxes[:, 3] - dt_boxes = np.asarray(dt_boxes) - annots_in_frame = annots.loadAnns(annots.getAnnIds(imgIds=[dets_default[1][i]], iscrowd=False)) - gt_boxes = [] - for j in range(len(annots_in_frame)): - gt_boxes.append(annots_in_frame[j]['bbox']) - gt_boxes = np.asarray(np.asarray(gt_boxes)) - if gt_boxes.shape[0]>0: - gt_boxes[:, 2] = gt_boxes[:, 0] + gt_boxes[:, 2] - gt_boxes[:, 3] = gt_boxes[:, 1] + gt_boxes[:, 3] - self.src_data.append({ - 'id': dets_default[1][i], - 'filename': os.path.join(imgs_split, img_info["file_name"]), - 'resolution': [img_info['width'], img_info['height']], - 'gt_boxes': [np.asarray([]), gt_boxes], - 'dt_boxes': [np.asarray([]), dt_boxes] - }) - pbar.update(1) - pbar.close() - with open(pkl_filename, 'wb') as handle: - pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) - else: - with open(pkl_filename, 'rb') as fp_pkl: - self.src_data = pickle.load(fp_pkl) - self.classes = ['background', 'person'] - self.class_ids = [-1, 1] - @staticmethod - def download( - url, download_path, dataset_sub_path=".", file_format="zip", create_dir=False): - - if create_dir: - os.makedirs(download_path, exist_ok=True) - - print("Downloading dataset from", url, "to", download_path) - - start_time = 0 - last_print = 0 - - def reporthook(count, block_size, total_size): - nonlocal start_time - nonlocal last_print - if count == 0: - start_time = time.time() - last_print = start_time - return - - duration = time.time() - start_time - progress_size = int(count * block_size) - speed = int(progress_size / (1024 * duration)) - if time.time() - last_print >= 1: - last_print = time.time() - print( - "\r%d MB, %d KB/s, %d seconds passed" % - (progress_size / (1024 * 1024), speed, duration), - end='' - ) - - if file_format == "zip": - zip_path = os.path.join(download_path, "dataset.zip") - urlretrieve(url, zip_path, reporthook=reporthook) - print() - print("Extracting data from zip file") - with ZipFile(zip_path, 'r') as zip_ref: - zip_ref.extractall(download_path) - os.remove(zip_path) - elif file_format == "tar.bz2" or file_format == "tar.gz": - tar_path = os.path.join(download_path, "dataset." + file_format) - urlretrieve(url, tar_path, reporthook=reporthook) - print() - - def members(tf): - l = len("Crowd_PETS09/") - for member in tf.getmembers(): - if member.path.startswith("Crowd_PETS09/"): - member.path = member.path[l:] - yield member - - with tarfile.open(tar_path, "r:" + file_format.split('.')[1]) as tar: - if file_format == "tar.bz2": - tar.extractall(path=download_path, members=members(tar)) - else: - tar.extractall(path=download_path) - tar.close() - os.remove(tar_path) - else: - raise ValueError("Unsupported file_format: " + file_format) - - # def __prepare_dataset(self): - # seq_root = os.path.join(self.path, "images/train") - # label_root = os.path.join(self.path, "labels/test") From a04fb6ebea4c9e9d31282a9f91fd32279ffa54f3 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 13:08:24 +0200 Subject: [PATCH 038/374] Add files via upload --- .../nms/utils/nms_dataset.py | 473 ++++++++++++++++++ .../nms/utils/nms_utils.py | 141 ++++++ 2 files changed, 614 insertions(+) create mode 100644 src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py create mode 100644 src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py new file mode 100644 index 0000000000..325a6f9009 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -0,0 +1,473 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +from opendr.engine.datasets import Dataset +import os +from urllib.request import urlretrieve +import ssl +import time +from zipfile import ZipFile +import tarfile +import gdown +import shutil +import pickle +import numpy as np +import math +from tqdm import tqdm +from opendr.perception.object_detection_2d import SingleShotDetectorLearner +from opendr.engine.data import Image +from opendr.perception.object_detection_2d.datasets.transforms import BoundingBoxListToNumpyArray +import json +from pycocotools.coco import COCO + + +class Dataset_NMS(Dataset): + def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, device='cuda'): + super().__init__() + available_dataset = ['COCO', 'PETS', 'CrowdHuman'] + self.dataset_sets = {'train': None, + 'val': None, + 'test': None} + if dataset_name not in available_dataset: + except_str = 'Unsupported dataset: ' + dataset_name + '. Currently available are:' + for j in range(len(available_dataset)): + except_str = except_str + ' \'' + available_dataset[j] + '\'' + if j < len(available_dataset) - 1: + except_str = except_str + ',' + except_str = except_str + '.' + raise ValueError(except_str) + + ssl._create_default_https_context = ssl._create_unverified_context + self.dataset_name = dataset_name + self.split = split + # self.__prepare_dataset() + self.path = os.path.join(path, dataset_name) + self.src_data = [] + if self.dataset_name == "PETS": + self.detector = 'JPD' + self.detector_type = 'default' + if use_ssd: + self.detector = 'SSD' + self.detector_type = 'custom' + + self.dataset_sets['train'] = 'train' + self.dataset_sets['val'] = 'val' + self.dataset_sets['test'] = 'test' + if self.dataset_sets[self.split] is None: + raise ValueError(self.split + ' split is not available...') + + if not os.path.exists(os.path.join(self.path, 'images/S1/L1')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S1_L1.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S1/L2')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S1_L2.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S2/L1')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L1.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S2/L2')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L2.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S2/L3')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L3.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'images/S3/Multiple_Flow')): + self.download( + 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S3_MF.tar.bz2', + download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) + if not os.path.exists( + os.path.join(self.path, 'annotations', 'pets_' + self.dataset_sets[self.split] + '.json')): + self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_annotations_json.zip', + download_path=os.path.join(self.path, 'annotations'), file_format="zip", + create_dir=True) + pkl_filename = os.path.join(self.path, + 'data_' + self.detector + '_' + self.dataset_sets[self.split] + '_pets.pkl') + if not os.path.exists(pkl_filename): + ssd = None + if use_ssd: + ssd = SingleShotDetectorLearner(device=device) + ssd.download(".", mode="pretrained") + ssd.load("./ssd_default_person", verbose=True) + if not os.path.exists( + os.path.join(self.path, 'detections', + 'PETS-' + self.dataset_sets[self.split] + '_siyudpm_dets.idl')): + self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_detections.zip', + download_path=os.path.join(self.path, 'detections'), file_format="zip", + create_dir=True) + if not os.path.exists( + os.path.join(self.path, 'annotations', 'PETS-' + self.dataset_sets[self.split] + '.idl')): + self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_annotations.zip', + download_path=os.path.join(self.path, 'annotations'), file_format="zip", + create_dir=True) + with open(os.path.join(self.path, 'annotations', + 'PETS-' + self.dataset_sets[self.split] + '.idl')) as fp_gt: + fp_dt = None + if self.detector_type == 'default': + fp_dt = open(os.path.join(self.path, 'detections', + 'PETS-' + self.dataset_sets[self.split] + '_siyudpm_dets.idl')) + print('Preparing PETS ' + self.dataset_sets[self.split] + ' set...') + current_id = 0 + number_samples = 1696 + if self.split == 'val': + current_id = 1696 + number_samples = 240 + elif self.split == 'test': + current_id = 1936 + number_samples = 436 + pbarDesc = "Overall progress" + pbar = tqdm(desc=pbarDesc, total=number_samples) + if self.detector_type == 'default': + line_dt = fp_dt.readline() + line_gt = fp_gt.readline() + while line_gt: + remove_strings = ['PETS09-', '\"', ':', '(', ')', ',', '', ';'] + data_gt = line_gt.replace(':', ' ') + for j in range(len(remove_strings)): + data_gt = data_gt.replace(remove_strings[j], '') + data_gt = data_gt.split() + filename_gt = data_gt[0][0:2] + '/' + data_gt[0][2:] + if filename_gt[0:6] == 'S2/L1/': + filename_gt = filename_gt.replace('img/00', 'Time_12-34/View_001/frame_') + num = int(filename_gt[-8:-4]) - 1 + filename_gt = filename_gt[:-8] + str(num).zfill(4) + '.jpg' + if filename_gt[0:6] == 'S2/L2/': + filename_gt = filename_gt.replace('img/00', 'Time_14-55/View_001/frame_') + num = int(filename_gt[-8:-4]) - 1 + filename_gt = filename_gt[:-8] + str(num).zfill(4) + '.jpg' + if filename_gt[0:2] == 'S3': + filename_gt = filename_gt.replace('_MF', 'Multiple_Flow') + + if self.detector_type == 'default': + data_dt = line_dt.replace(':', ' ') + for j in range(len(remove_strings)): + data_dt = data_dt.replace(remove_strings[j], '') + data_dt = data_dt.split() + filename_dt = data_dt[0][0:2] + '/' + data_dt[0][2:] + if filename_dt[0:6] == 'S2/L1/': + filename_dt = filename_dt.replace('img/00', 'Time_12-34/View_001/frame_') + num = int(filename_dt[-8:-4]) - 1 + filename_dt = filename_dt[:-8] + str(num).zfill(4) + '.jpg' + if filename_dt[0:6] == 'S2/L2/': + filename_dt = filename_dt.replace('img/00', 'Time_14-55/View_001/frame_') + num = int(filename_dt[-8:-4]) - 1 + filename_dt = filename_dt[:-8] + str(num).zfill(4) + '.jpg' + if filename_dt[0:2] == 'S3': + filename_dt = filename_dt.replace('_MF', 'Multiple_Flow') + if filename_gt != filename_dt: + raise ValueError('Errors in files...') + + img = Image.open(os.path.join(self.path, 'images/', filename_gt)) + + dt_boxes = [] + if self.detector_type == 'default': + for i in range(1, (len(data_dt)), 5): + dt_box = np.array((float(data_dt[i]), float(data_dt[i + 1]), float(data_dt[i + 2]), + float(data_dt[i + 3]), 1 / (1 + math.exp(- float(data_dt[i + 4]))))) + dt_boxes.append(dt_box) + else: + bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, + nms_topk=6000, post_nms=6000) + bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) + bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] + bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] + bboxes_list = bboxes_list[:5000, :] + for b in range(len(bboxes_list)): + dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], + bboxes_list[b, 3], bboxes_list[b, 4][0]])) + gt_boxes = [] + for i in range(1, (len(data_gt)), 5): + gt_box = np.array((float(data_gt[i]), float(data_gt[i + 1]), float(data_gt[i + 2]), + float(data_gt[i + 3]))) + gt_boxes.append(gt_box) + self.src_data.append({ + 'id': current_id, + 'filename': os.path.join('images', filename_gt), + 'resolution': img.opencv().shape[0:2][::-1], + 'gt_boxes': [np.asarray([]), np.asarray(gt_boxes)], + 'dt_boxes': [np.asarray([]), np.asarray(dt_boxes)] + }) + current_id = current_id + 1 + pbar.update(1) + if self.detector_type == 'default': + line_dt = fp_dt.readline() + line_gt = fp_gt.readline() + pbar.close() + if self.detector_type == 'default': + fp_dt.close() + with open(pkl_filename, 'wb') as handle: + pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) + else: + with open(pkl_filename, 'rb') as fp_pkl: + self.src_data = pickle.load(fp_pkl) + + self.classes = ['background', 'human'] + self.class_ids = [-1, 1] + + elif self.dataset_name == "CrowdHuman": + splits = ['train', 'val'] + if self.split not in splits: + raise ValueError(self.split + ' split is not available...') + self.detector = 'YOLOv4' + self.detector_type = 'default' + if use_ssd: + self.detector = 'SSD' + self.detector_type = 'custom' + if not os.path.exists(os.path.join(self.path, 'images/train')): + os.makedirs(os.path.join(self.path, 'images/train'), exist_ok=True) + urls = ['https://drive.google.com/file/d/134QOvaatwKdy0iIeNqA_p-xkAhkV4F8Y/view?usp=sharing', + 'https://drive.google.com/u/0/uc?id=17evzPh7gc1JBNvnW1ENXLy5Kr4Q_Nnla', + 'https://drive.google.com/u/0/uc?id=1tdp0UCgxrqy1B6p8LkR-Iy0aIJ8l4fJW'] + outputs = [os.path.join(self.path, 'CrowdHuman_train01.zip'), 'CrowdHuman_train02.zip', + 'CrowdHuman_train03.zip'] + for i in range(0, len(urls)): + gdown.download(urls[i], outputs[i], quiet=False) + zip_path = os.path.join('.', outputs[i]) + with ZipFile(zip_path, 'r') as zip_ref: + download_path = os.path.join(self.path, 'images', 'train') + zip_ref.extractall(download_path) + os.remove(zip_path) + + if not os.path.exists(os.path.join(self.path, 'images/val')): + os.makedirs(os.path.join(self.path, 'images/val'), exist_ok=True) + url = 'https://drive.google.com/u/0/uc?id=18jFI789CoHTppQ7vmRSFEdnGaSQZ4YzO' + output = 'CrowdHuman_val.zip' + gdown.download(url, output, quiet=False) + zip_path = os.path.join('.', output) + with ZipFile(zip_path, 'r') as zip_ref: + download_path = os.path.join(self.path, 'images', 'val') + zip_ref.extractall(download_path) + os.remove(zip_path) + + if not os.path.exists( + os.path.join(self.path, 'data_' + self.detector + '_' + self.split + '_crowdhuman.pkl')): + # Download detections from FTP server + ssd = None + if use_ssd: + ssd = SingleShotDetectorLearner(device=device) + ssd.download(".", mode="pretrained") + ssd.load("./ssd_default_person", verbose=True) + + # Download annotations from official CrowdHuman GoogleDrive repo + if not os.path.exists(os.path.join(self.path, 'annotations', 'annotation_' + self.split + '.odgt')): + os.makedirs(os.path.join(self.path, 'annotations'), exist_ok=True) + url = None + if self.split == 'train': + url = 'https://drive.google.com/u/0/uc?id=1UUTea5mYqvlUObsC1Z8CFldHJAtLtMX3&export=download' + elif self.split == 'val': + url = 'https://drive.google.com/u/0/uc?id=10WIRwu8ju8GRLuCkZ_vT6hnNxs5ptwoL&export=download' + output = 'annotation_' + self.split + '.odgt' + gdown.download(url, output, quiet=False) + shutil.move(os.path.join('.', output), + os.path.join('.', 'datasets', 'CrowdHuman', 'annotations', self.split)) + + with open(os.path.join(self.path, 'annotations', 'annotation_' + self.split + '.odgt')) as fp_gt: + data_dt = None + if self.detector_type == 'default': + fp_dt = open( + os.path.join(self.path, 'detections', 'det_data_' + self.split + '_crowdhuman.pkl'), 'rb') + data_dt = pickle.load(fp_dt) + line = fp_gt.readline() + i = 0 + while line: + annotations = json.loads(line) + img = Image.open(os.path.join(self.path, 'images/' + self.split, annotations['ID'] + '.jpg')) + dt_boxes = [] + if self.detector_type == 'default' and data_dt[i]['id'] != annotations['ID']: + continue + elif self.detector_type == 'default': + dt_boxes = data_dt[i]['dt_boxes'] + elif self.detector_type == 'custom' and self.detector == 'SSD': + bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, + nms_topk=10000, post_nms=10000) + bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) + bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] + bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] + bboxes_list = bboxes_list[:8000, :] + for b in range(len(bboxes_list)): + dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], + bboxes_list[b, 3], bboxes_list[b, 4][0]])) + gt_boxes = [] + for j in range(len(annotations['gtboxes'])): + if annotations['gtboxes'][j]['tag'] == 'person': + gt_box = annotations['gtboxes'][j]['fbox'] + gt_box[2] = gt_box[2] + gt_box[0] + gt_box[3] = gt_box[3] + gt_box[1] + gt_boxes.append(gt_box) + self.src_data.append({ + 'id': annotations['ID'], + 'filename': annotations['ID'] + '.jpg', + 'resolution': img.opencv().shape[0:2][::-1], + 'gt_boxes': [np.asarray([]), np.asarray(gt_boxes)], + 'dt_boxes': [np.asarray([]), np.asarray(dt_boxes)] + }) + line = fp_gt.readline() + i = i + 1 + with open(os.path.join(self.path, 'data_' + self.split + '_crowdhuman.pkl'), 'wb') as handle: + pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) + else: + with open(os.path.join(self.path, 'data_' + self.split + '_crowdhuman.pkl'), 'rb') as fp_dt: + self.src_data = pickle.load(fp_dt) + elif self.dataset_name == "COCO": + self.dataset_sets['train'] = 'train' + self.dataset_sets['val'] = 'minival' + self.dataset_sets['test'] = 'valminusminival' + imgs_split = None + if self.dataset_sets[self.split] is None: + raise ValueError(self.split + ' split is not available...') + elif self.dataset_sets[self.split] == 'train': + imgs_split = 'train2014' + else: + imgs_split = 'val2014' + self.detector = 'YOLOv4' + self.detector_type = 'default' + ssd = None + if use_ssd: + self.detector = 'SSD' + self.detector_type = 'custom' + ssd = SingleShotDetectorLearner(device=device) + ssd.download(".", mode="pretrained") + ssd.load("./ssd_default_person", verbose=True) + if not os.path.exists(os.path.join(self.path, imgs_split)): + self.download('http://images.cocodataset.org/zips/' + imgs_split +'.zip', + download_path=os.path.join(self.path), file_format="zip", + create_dir=True) + pkl_filename = os.path.join(self.path, 'data_' + self.detector + '_' + self.dataset_sets[self.split] + '_coco.pkl') + if not os.path.exists(pkl_filename): + if not os.path.exists(os.path.join(self.path, 'annotations', 'instances_' + imgs_split +'.json')): + self.download('http://images.cocodataset.org/annotations/annotations_trainval2014.zip', + download_path=os.path.join(self.path), file_format="zip", create_dir=True) + if not os.path.exists(os.path.join(self.path, 'detections', 'coco_2014_' + self.dataset_sets[self.split]+ '_FRCN_train.pkl')): + self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/coco_2014_FRCN.tar.gz', + download_path=os.path.join(self.path, 'detections'), file_format='tar.gz', + create_dir=True) + with open(os.path.join(self.path, 'detections', + 'coco_2014_' + self.dataset_sets[self.split] + '_FRCN_train.pkl'), 'rb') as f: + dets_default = pickle.load(f, encoding='latin1') + annots = COCO(annotation_file=os.path.join(self.path, 'annotations', 'instances_' + imgs_split + '.json')) + pbarDesc = "Overall progress" + pbar = tqdm(desc=pbarDesc, total=len(dets_default[1])) + for i in range(len(dets_default[1])): + dt_boxes = [] + img_info = annots.loadImgs([dets_default[1][i]])[0] + img = Image.open(os.path.join(self.path, imgs_split, img_info["file_name"])) + if self.detector_type == 'default': + dt_boxes = dets_default[0][1][i] + elif self.detector == 'SSD': + bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, + nms_topk=6000, post_nms=6000) + bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) + if bboxes_list.shape[0]>0: + bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] + if bboxes_list.shape[0] > 0: + bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] + bboxes_list = bboxes_list[:5000, :] + for b in range(len(bboxes_list)): + dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], + bboxes_list[b, 3], bboxes_list[b, 4][0]])) + #if len(dt_boxes) > 0: + # dt_boxes[:, 2] = dt_boxes[:, 0] + dt_boxes[:, 2] + # dt_boxes[:, 3] = dt_boxes[:, 1] + dt_boxes[:, 3] + dt_boxes = np.asarray(dt_boxes) + annots_in_frame = annots.loadAnns(annots.getAnnIds(imgIds=[dets_default[1][i]], iscrowd=False)) + gt_boxes = [] + for j in range(len(annots_in_frame)): + gt_boxes.append(annots_in_frame[j]['bbox']) + gt_boxes = np.asarray(np.asarray(gt_boxes)) + if gt_boxes.shape[0]>0: + gt_boxes[:, 2] = gt_boxes[:, 0] + gt_boxes[:, 2] + gt_boxes[:, 3] = gt_boxes[:, 1] + gt_boxes[:, 3] + self.src_data.append({ + 'id': dets_default[1][i], + 'filename': os.path.join(imgs_split, img_info["file_name"]), + 'resolution': [img_info['width'], img_info['height']], + 'gt_boxes': [np.asarray([]), gt_boxes], + 'dt_boxes': [np.asarray([]), dt_boxes] + }) + pbar.update(1) + pbar.close() + with open(pkl_filename, 'wb') as handle: + pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) + else: + with open(pkl_filename, 'rb') as fp_pkl: + self.src_data = pickle.load(fp_pkl) + self.classes = ['background', 'person'] + self.class_ids = [-1, 1] + @staticmethod + def download( + url, download_path, dataset_sub_path=".", file_format="zip", create_dir=False): + + if create_dir: + os.makedirs(download_path, exist_ok=True) + + print("Downloading dataset from", url, "to", download_path) + + start_time = 0 + last_print = 0 + + def reporthook(count, block_size, total_size): + nonlocal start_time + nonlocal last_print + if count == 0: + start_time = time.time() + last_print = start_time + return + + duration = time.time() - start_time + progress_size = int(count * block_size) + speed = int(progress_size / (1024 * duration)) + if time.time() - last_print >= 1: + last_print = time.time() + print( + "\r%d MB, %d KB/s, %d seconds passed" % + (progress_size / (1024 * 1024), speed, duration), + end='' + ) + + if file_format == "zip": + zip_path = os.path.join(download_path, "dataset.zip") + urlretrieve(url, zip_path, reporthook=reporthook) + print() + print("Extracting data from zip file") + with ZipFile(zip_path, 'r') as zip_ref: + zip_ref.extractall(download_path) + os.remove(zip_path) + elif file_format == "tar.bz2" or file_format == "tar.gz": + tar_path = os.path.join(download_path, "dataset." + file_format) + urlretrieve(url, tar_path, reporthook=reporthook) + print() + + def members(tf): + l = len("Crowd_PETS09/") + for member in tf.getmembers(): + if member.path.startswith("Crowd_PETS09/"): + member.path = member.path[l:] + yield member + + with tarfile.open(tar_path, "r:" + file_format.split('.')[1]) as tar: + if file_format == "tar.bz2": + tar.extractall(path=download_path, members=members(tar)) + else: + tar.extractall(path=download_path) + tar.close() + os.remove(tar_path) + else: + raise ValueError("Unsupported file_format: " + file_format) + + # def __prepare_dataset(self): + # seq_root = os.path.join(self.path, "images/train") + # label_root = os.path.join(self.path, "labels/test") diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py new file mode 100644 index 0000000000..f3a7e01110 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py @@ -0,0 +1,141 @@ +import torch + + +def jaccard(box_a, box_b, iscrowd: bool = False): + """Compute the jaccard overlap of two sets of boxes. The jaccard overlap + is simply the intersection over union of two boxes. Here we operate on + ground truth boxes and default boxes. If iscrowd=True, put the crowd in box_b. + E.g.: + A ∩ B / A ∪ B = A ∩ B / (area(A) + area(B) - A ∩ B) + Args: + box_a: (tensor) Ground truth bounding boxes, Shape: [num_objects,4] + box_b: (tensor) Prior boxes from priorbox layers, Shape: [num_priors,4] + Return: + jaccard overlap: (tensor) Shape: [box_a.size(0), box_b.size(0)] + """ + use_batch = True + if box_a.dim() == 2: + use_batch = False + box_a = box_a[None, ...] + box_b = box_b[None, ...] + + inter = intersect(box_a, box_b) + area_a = ((box_a[:, :, 2] - box_a[:, :, 0]) * + (box_a[:, :, 3] - box_a[:, :, 1])).unsqueeze(2).expand_as(inter) # [A,B] + area_b = ((box_b[:, :, 2] - box_b[:, :, 0]) * + (box_b[:, :, 3] - box_b[:, :, 1])).unsqueeze(1).expand_as(inter) # [A,B] + union = area_a + area_b - inter + + out = inter / area_a if iscrowd else inter / union + return out if use_batch else out.squeeze(0) + + +def intersect(box_a, box_b): + """ We resize both tensors to [A,B,2] without new malloc: + [A,2] -> [A,1,2] -> [A,B,2] + [B,2] -> [1,B,2] -> [A,B,2] + Then we compute the area of intersect between box_a and box_b. + Args: + box_a: (tensor) bounding boxes, Shape: [n,A,4]. + box_b: (tensor) bounding boxes, Shape: [n,B,4]. + Return: + (tensor) intersection area, Shape: [n,A,B]. + """ + n = box_a.size(0) + A = box_a.size(1) + B = box_b.size(1) + max_xy = torch.min(box_a[:, :, 2:].unsqueeze(2).expand(n, A, B, 2), + box_b[:, :, 2:].unsqueeze(1).expand(n, A, B, 2)) + min_xy = torch.max(box_a[:, :, :2].unsqueeze(2).expand(n, A, B, 2), + box_b[:, :, :2].unsqueeze(1).expand(n, A, B, 2)) + return torch.clamp(max_xy - min_xy, min=0).prod(3) # inter + + +def diou(box_a, box_b, iscrowd: bool = False): + """Compute the jaccard overlap of two sets of boxes. The jaccard overlap + is simply the intersection over union of two boxes. Here we operate on + ground truth boxes and default boxes. If iscrowd=True, put the crowd in box_b. + E.g.: + A ∩ B / A ∪ B = A ∩ B / (area(A) + area(B) - A ∩ B) + Args: + box_a: (tensor) Ground truth bounding boxes, Shape: [num_objects,4] + box_b: (tensor) Prior boxes from priorbox layers, Shape: [num_priors,4] + Return: + jaccard overlap: (tensor) Shape: [box_a.size(0), box_b.size(0)] + """ + use_batch = True + if box_a.dim() == 2: + use_batch = False + box_a = box_a[None, ...] + box_b = box_b[None, ...] + + inter = intersect(box_a, box_b) + area_a = ((box_a[:, :, 2] - box_a[:, :, 0]) * + (box_a[:, :, 3] - box_a[:, :, 1])).unsqueeze(2).expand_as(inter) # [A,B] + area_b = ((box_b[:, :, 2] - box_b[:, :, 0]) * + (box_b[:, :, 3] - box_b[:, :, 1])).unsqueeze(1).expand_as(inter) # [A,B] + union = area_a + area_b - inter + x1 = ((box_a[:, :, 2] + box_a[:, :, 0]) / 2).unsqueeze(2).expand_as(inter) + y1 = ((box_a[:, :, 3] + box_a[:, :, 1]) / 2).unsqueeze(2).expand_as(inter) + x2 = ((box_b[:, :, 2] + box_b[:, :, 0]) / 2).unsqueeze(1).expand_as(inter) + y2 = ((box_b[:, :, 3] + box_b[:, :, 1]) / 2).unsqueeze(1).expand_as(inter) + + t1 = box_a[:, :, 1].unsqueeze(2).expand_as(inter) + b1 = box_a[:, :, 3].unsqueeze(2).expand_as(inter) + l1 = box_a[:, :, 0].unsqueeze(2).expand_as(inter) + r1 = box_a[:, :, 2].unsqueeze(2).expand_as(inter) + + t2 = box_b[:, :, 1].unsqueeze(1).expand_as(inter) + b2 = box_b[:, :, 3].unsqueeze(1).expand_as(inter) + l2 = box_b[:, :, 0].unsqueeze(1).expand_as(inter) + r2 = box_b[:, :, 2].unsqueeze(1).expand_as(inter) + cr = torch.max(r1, r2) + cl = torch.min(l1, l2) + ct = torch.min(t1, t2) + cb = torch.max(b1, b2) + D = (((x2 - x1) ** 2 + (y2 - y1) ** 2) / ((cr - cl) ** 2 + (cb - ct) ** 2 + 1e-7)) + out = inter / area_a if iscrowd else inter / union - D ** 0.9 + return out if use_batch else out.squeeze(0) + + +def distance(box_a, box_b, iscrowd: bool = False): + """Compute the jaccard overlap of two sets of boxes. The jaccard overlap + is simply the intersection over union of two boxes. Here we operate on + ground truth boxes and default boxes. If iscrowd=True, put the crowd in box_b. + E.g.: + A ∩ B / A ∪ B = A ∩ B / (area(A) + area(B) - A ∩ B) + Args: + box_a: (tensor) Ground truth bounding boxes, Shape: [num_objects,4] + box_b: (tensor) Prior boxes from priorbox layers, Shape: [num_priors,4] + Return: + jaccard overlap: (tensor) Shape: [box_a.size(0), box_b.size(0)] + """ + use_batch = True + if box_a.dim() == 2: + use_batch = False + box_a = box_a[None, ...] + box_b = box_b[None, ...] + + inter = intersect(box_a, box_b) + x1 = ((box_a[:, :, 2] + box_a[:, :, 0]) / 2).unsqueeze(2).expand_as(inter) + y1 = ((box_a[:, :, 3] + box_a[:, :, 1]) / 2).unsqueeze(2).expand_as(inter) + x2 = ((box_b[:, :, 2] + box_b[:, :, 0]) / 2).unsqueeze(1).expand_as(inter) + y2 = ((box_b[:, :, 3] + box_b[:, :, 1]) / 2).unsqueeze(1).expand_as(inter) + + t1 = box_a[:, :, 1].unsqueeze(2).expand_as(inter) + b1 = box_a[:, :, 3].unsqueeze(2).expand_as(inter) + l1 = box_a[:, :, 0].unsqueeze(2).expand_as(inter) + r1 = box_a[:, :, 2].unsqueeze(2).expand_as(inter) + + t2 = box_b[:, :, 1].unsqueeze(1).expand_as(inter) + b2 = box_b[:, :, 3].unsqueeze(1).expand_as(inter) + l2 = box_b[:, :, 0].unsqueeze(1).expand_as(inter) + r2 = box_b[:, :, 2].unsqueeze(1).expand_as(inter) + + cr = torch.max(r1, r2) + cl = torch.min(l1, l2) + ct = torch.min(t1, t2) + cb = torch.max(b1, b2) + D = (((x2 - x1) ** 2 + (y2 - y1) ** 2) / ((cr - cl) ** 2 + (cb - ct) ** 2 + 1e-7)) ** 0.6 + out = D if iscrowd else D + return out if use_batch else out.squeeze(0) From b8dcef6284c7e689fb40e47cb262818c3f08ba9c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 16:04:09 +0200 Subject: [PATCH 039/374] Add files via upload --- .../object-detection-2d-nms-seq2seq_nms.md | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 docs/reference/object-detection-2d-nms-seq2seq_nms.md diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md new file mode 100644 index 0000000000..fa3da0d610 --- /dev/null +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -0,0 +1,51 @@ +## Seq2Seq-NMS module + +The *seq2seq-nms* module contains the *Seq2SeqNMSLearner* class, which inherits from the abstract class *Learner*. + +### Class Seq2SeqNMSLearner +Bases: `engine.learners.Learner` + + +It can be used to perform single-class non-maximum suppression on images (inference) as well as training new seq2seq-nms models. + +The [Seq2SeqNMSLearner](/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py) class has the following +public methods: + +#### `Seq2SeqNMSLearner` constructor +```python +SingleShotDetectorLearner(self, lr, lr_schedule='', checkpoint_after_iter, checkpoint_load_iter, experiment_name, temp_path, device, use_fmod, fmod_map_type, fmod_map_bin, dropout, fmod_roi_pooling_dim, fmod_map_res_dim, fmod_pyramid_lvl, lq_dim, sq_dim, app_input_dim, num_JPUs, pretrained_demo_model, log_after, iou_filtering, fmod_init_path) +``` + +Constructor parameters: + +- **lr**: *float, default=0.0001*\ + Specifies the initial learning rate to be used during training. +- **epochs**: *int, default=8*\ + Specifies the number of epochs to be used during training. +- **device**: *{'cuda', 'cpu'}, default='cuda'*\ + Specifies the device to be used. +- **temp_path**: *str, default='./temp'*\ + Specifies a path to be used for storage of checkpoints during training. +- **checkpoint_after_iter**: *int, default=0*\ + Specifies the epoch interval between checkpoints during training. If set to 0 no checkpoint will be saved. +- **checkpoint_load_iter**: *int, default=0*\ + Specifies the epoch to load a saved checkpoint from. If set to 0 no checkpoint will be loaded. +- **log_after**: *int, default=500*\ + Specifies interval (in iterations/batches) between information logging on *stdout*. +- **experiment_name**: *str, default='default'*\ + Specifies the name of the experiment. +- **iou_filtering**: *float, default=0.8*\ + Specifies the IoU threshold used for filtering RoIs before provided by the seq2seq-nms model.If set to values <0 or >1, no filtering is applied. +- **dropout**: *float, default=0.05*\ + Specifies the dropout rate. +- **pretrained_demo_model**: *\ +- **app_feats**: {'fmod', 'zeros', 'custom'}, default='fmod'*\ + Specifies the type of the appearance-based features of RoIs used in the model. +- **fmod_map_type**: {'EDGEMAP', 'FAST', 'AKAZE', 'BRISK', 'ORB'}, default='EDGEMAP'*\ + Specifies the type of maps used by FMoD, in the case where **app_feats**='fmod'. +- **fmod_map_bin**:*bool, default=True*\ + Specifies whether FMoD maps are binary or not, in the case where **app_feats**='fmod'. +- **app_input_dim**: *int, default=None*\ + Specifies the dimension of appearance-based RoI features. In the case where **app_feats**='fmod', the corresponding dimension is automatically computed. +- **fmod_init_path**: *str, default=None *\ + Specifies the path to the the file used for normalizing appearance-based features, in the case where **app_feats**='fmod'. From f822c2b5fa9e7dea9a777bcb54758af526f4278a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 16:07:59 +0200 Subject: [PATCH 040/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index fa3da0d610..b22823224f 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -39,7 +39,7 @@ Constructor parameters: - **dropout**: *float, default=0.05*\ Specifies the dropout rate. - **pretrained_demo_model**: *\ -- **app_feats**: {'fmod', 'zeros', 'custom'}, default='fmod'*\ +- **app_feats**: {'fmod', 'zeros', 'custom'}, default='fmod' *\ Specifies the type of the appearance-based features of RoIs used in the model. - **fmod_map_type**: {'EDGEMAP', 'FAST', 'AKAZE', 'BRISK', 'ORB'}, default='EDGEMAP'*\ Specifies the type of maps used by FMoD, in the case where **app_feats**='fmod'. From f73d6de20c1faedf28d2e1f3566486bec4d21c85 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 16:10:26 +0200 Subject: [PATCH 041/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index b22823224f..6cf05adbc7 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -38,8 +38,8 @@ Constructor parameters: Specifies the IoU threshold used for filtering RoIs before provided by the seq2seq-nms model.If set to values <0 or >1, no filtering is applied. - **dropout**: *float, default=0.05*\ Specifies the dropout rate. -- **pretrained_demo_model**: *\ -- **app_feats**: {'fmod', 'zeros', 'custom'}, default='fmod' *\ + +- **app_feats**: {'fmod', 'zeros', 'custom'}, default='fmod'*\ Specifies the type of the appearance-based features of RoIs used in the model. - **fmod_map_type**: {'EDGEMAP', 'FAST', 'AKAZE', 'BRISK', 'ORB'}, default='EDGEMAP'*\ Specifies the type of maps used by FMoD, in the case where **app_feats**='fmod'. From e82dbea9c350f7b4ca29dc4ff1c6fbc56b2b97f8 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 16:11:23 +0200 Subject: [PATCH 042/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 6cf05adbc7..ae1b1c9165 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -39,7 +39,7 @@ Constructor parameters: - **dropout**: *float, default=0.05*\ Specifies the dropout rate. -- **app_feats**: {'fmod', 'zeros', 'custom'}, default='fmod'*\ +- **app_feats**: {'fmod', 'zeros', 'custom'}, default='a'*\ Specifies the type of the appearance-based features of RoIs used in the model. - **fmod_map_type**: {'EDGEMAP', 'FAST', 'AKAZE', 'BRISK', 'ORB'}, default='EDGEMAP'*\ Specifies the type of maps used by FMoD, in the case where **app_feats**='fmod'. From 4dc6164317cbd25358c82ce48de58700bdc981c3 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 16:14:38 +0200 Subject: [PATCH 043/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index ae1b1c9165..85bc08adab 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -42,10 +42,10 @@ Constructor parameters: - **app_feats**: {'fmod', 'zeros', 'custom'}, default='a'*\ Specifies the type of the appearance-based features of RoIs used in the model. - **fmod_map_type**: {'EDGEMAP', 'FAST', 'AKAZE', 'BRISK', 'ORB'}, default='EDGEMAP'*\ - Specifies the type of maps used by FMoD, in the case where **app_feats**='fmod'. + Specifies the type of maps used by FMoD, in the case where *app_feats*='fmod'. - **fmod_map_bin**:*bool, default=True*\ - Specifies whether FMoD maps are binary or not, in the case where **app_feats**='fmod'. + Specifies whether FMoD maps are binary or not, in the case where *app_feats*='fmod'. - **app_input_dim**: *int, default=None*\ - Specifies the dimension of appearance-based RoI features. In the case where **app_feats**='fmod', the corresponding dimension is automatically computed. + Specifies the dimension of appearance-based RoI features. In the case where *app_feats*='fmod', the corresponding dimension is automatically computed. - **fmod_init_path**: *str, default=None *\ - Specifies the path to the the file used for normalizing appearance-based features, in the case where **app_feats**='fmod'. + Specifies the path to the the file used for normalizing appearance-based features, in the case where *app_feats*='fmod'. From 4347cd9c1cfc290ea87b12ff4286aa4f6b5f4a20 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 16:15:31 +0200 Subject: [PATCH 044/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 85bc08adab..a308a5fd56 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -39,9 +39,9 @@ Constructor parameters: - **dropout**: *float, default=0.05*\ Specifies the dropout rate. -- **app_feats**: {'fmod', 'zeros', 'custom'}, default='a'*\ +- **app_feats**: *{'fmod', 'zeros', 'custom'}, default='fmod'*\ Specifies the type of the appearance-based features of RoIs used in the model. -- **fmod_map_type**: {'EDGEMAP', 'FAST', 'AKAZE', 'BRISK', 'ORB'}, default='EDGEMAP'*\ +- **fmod_map_type**: *{'EDGEMAP', 'FAST', 'AKAZE', 'BRISK', 'ORB'}, default='EDGEMAP'*\ Specifies the type of maps used by FMoD, in the case where *app_feats*='fmod'. - **fmod_map_bin**:*bool, default=True*\ Specifies whether FMoD maps are binary or not, in the case where *app_feats*='fmod'. From 7f74ed3e63f18cd7349c2f1f08a1245c37a276fb Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 16:17:55 +0200 Subject: [PATCH 045/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index a308a5fd56..4fd7924925 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -32,6 +32,8 @@ Constructor parameters: Specifies the epoch to load a saved checkpoint from. If set to 0 no checkpoint will be loaded. - **log_after**: *int, default=500*\ Specifies interval (in iterations/batches) between information logging on *stdout*. +- **variant**: *{'light', 'medium', 'full'}, default='medium'*\ + Specifies the variant of seq2seq-nms model. - **experiment_name**: *str, default='default'*\ Specifies the name of the experiment. - **iou_filtering**: *float, default=0.8*\ From 4d8a62e5a02b8e1fe32694481067f53a361b91bd Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 16:20:59 +0200 Subject: [PATCH 046/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 4fd7924925..8a76c7d0e2 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -13,7 +13,8 @@ public methods: #### `Seq2SeqNMSLearner` constructor ```python -SingleShotDetectorLearner(self, lr, lr_schedule='', checkpoint_after_iter, checkpoint_load_iter, experiment_name, temp_path, device, use_fmod, fmod_map_type, fmod_map_bin, dropout, fmod_roi_pooling_dim, fmod_map_res_dim, fmod_pyramid_lvl, lq_dim, sq_dim, app_input_dim, num_JPUs, pretrained_demo_model, log_after, iou_filtering, fmod_init_path) +Seq2SeqNMSLearner(self, lr, epochs, device', temp_path, checkpoint_after_iter, checkpoint_load_iter, log_after, variant, experiment_name, + iou_filtering, dropout, pretrained_demo_model, app_feats, fmod_map_type, fmod_map_bin, app_input_dim, fmod_init_path) ``` Constructor parameters: @@ -45,7 +46,7 @@ Constructor parameters: Specifies the type of the appearance-based features of RoIs used in the model. - **fmod_map_type**: *{'EDGEMAP', 'FAST', 'AKAZE', 'BRISK', 'ORB'}, default='EDGEMAP'*\ Specifies the type of maps used by FMoD, in the case where *app_feats*='fmod'. -- **fmod_map_bin**:*bool, default=True*\ +- **fmod_map_bin**: *bool, default=True*\ Specifies whether FMoD maps are binary or not, in the case where *app_feats*='fmod'. - **app_input_dim**: *int, default=None*\ Specifies the dimension of appearance-based RoI features. In the case where *app_feats*='fmod', the corresponding dimension is automatically computed. From 7f12d0d710246627166551f551f4fd1d83b9a822 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 16:21:18 +0200 Subject: [PATCH 047/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 8a76c7d0e2..bc3dc0ec29 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -13,7 +13,7 @@ public methods: #### `Seq2SeqNMSLearner` constructor ```python -Seq2SeqNMSLearner(self, lr, epochs, device', temp_path, checkpoint_after_iter, checkpoint_load_iter, log_after, variant, experiment_name, +Seq2SeqNMSLearner(self, lr, epochs, device, temp_path, checkpoint_after_iter, checkpoint_load_iter, log_after, variant, experiment_name, iou_filtering, dropout, pretrained_demo_model, app_feats, fmod_map_type, fmod_map_bin, app_input_dim, fmod_init_path) ``` From 7c4260e222777668471f184feb244e754c240ae5 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 16:54:47 +0200 Subject: [PATCH 048/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index bc3dc0ec29..e145ce7954 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -41,7 +41,8 @@ Constructor parameters: Specifies the IoU threshold used for filtering RoIs before provided by the seq2seq-nms model.If set to values <0 or >1, no filtering is applied. - **dropout**: *float, default=0.05*\ Specifies the dropout rate. - +- **pretrained_demo_model**: *{'PETS_JPD_medium', 'COCO_FRCN_medium' , defualt=None*\ +- Specifies the name of the pretrained model - **app_feats**: *{'fmod', 'zeros', 'custom'}, default='fmod'*\ Specifies the type of the appearance-based features of RoIs used in the model. - **fmod_map_type**: *{'EDGEMAP', 'FAST', 'AKAZE', 'BRISK', 'ORB'}, default='EDGEMAP'*\ From 66fc890b2fc118135ad97fcdf0991ecfa0e227f0 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 17:00:19 +0200 Subject: [PATCH 049/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../object-detection-2d-nms-seq2seq_nms.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index e145ce7954..f8f96b7dc7 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -53,3 +53,21 @@ Constructor parameters: Specifies the dimension of appearance-based RoI features. In the case where *app_feats*='fmod', the corresponding dimension is automatically computed. - **fmod_init_path**: *str, default=None *\ Specifies the path to the the file used for normalizing appearance-based features, in the case where *app_feats*='fmod'. + + + +#### `Seq2SeqNMSLearner.fit` +```python +Seq2SeqNMSLearner.fit(self, dataset, logging_path, logging_flush_secs, silent, verbose, nms_gt_iou, max_dt_boxes, datasets_folder, use_ssd) +``` + +This method is used to train the algorithm on a `Dataset_NMS` dataset. Returns a dictionary containing stats regarding the training process. + +Parameters: + +- **dataset**: *object*\ + Object that holds the training dataset. +- **val_dataset**: *object, default=None*\ + Object that holds the validation dataset. +- **verbose**: *bool, default=True*\ + If True, enables maximum verbosity. From 997ab784cb4f782ab34af6127aee2b0aaf6c731e Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 17:39:52 +0200 Subject: [PATCH 050/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../object-detection-2d-nms-seq2seq_nms.md | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index f8f96b7dc7..3e2a4dee8a 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -65,9 +65,19 @@ This method is used to train the algorithm on a `Dataset_NMS` dataset. Returns a Parameters: -- **dataset**: *object*\ - Object that holds the training dataset. -- **val_dataset**: *object, default=None*\ - Object that holds the validation dataset. +- **dataset**: *{'PETS', 'COCO'}*\ + Specifies the name of the dataset among those available from training. +- **logging_path**: *str, default=None*\ + Path to save log files. If set to None, only the console will be used for logging. +- **logging_flush_secs**: *int, default=30*\ + How often, in seconds, to flush the TensorBoard data to disk. +- **silent**: *bool, default=False*\ + If set to True, disables all printing of training progress reports and other information to STDOUT. - **verbose**: *bool, default=True*\ If True, enables maximum verbosity. +- **nms_gt_iou**: *float, default=0.5*\ + Specifies the threshold used to determine whether a detection RoI must be suppressed or not based on its IoU with the image's ground-truth RoIs. +- **max_dt_boxes**: *int, default=500*\ + Specifies the maximum number of RoIs provided to seq2Seq-nms model as input. +- **datasets_folder**: *str, default='./datasets'*\ + Specifies the path to the folder where the datasets are stored. From 15b3b6912e2546fee349a92044bcdad489948461 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 17:42:40 +0200 Subject: [PATCH 051/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 3e2a4dee8a..6bc921b9b3 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -81,3 +81,5 @@ Parameters: Specifies the maximum number of RoIs provided to seq2Seq-nms model as input. - **datasets_folder**: *str, default='./datasets'*\ Specifies the path to the folder where the datasets are stored. +- **use_ssd**: *bool, default=False*\ + If set to True, RoIs fromm SSD are fed to the seq2Seq-nms model. Otherwise, RoIs from the default detector of the specified dataset are used as input. From 656021d1cb546e30a18da8b86eba52b35021e762 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 17:43:07 +0200 Subject: [PATCH 052/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 6bc921b9b3..e551378afe 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -82,4 +82,4 @@ Parameters: - **datasets_folder**: *str, default='./datasets'*\ Specifies the path to the folder where the datasets are stored. - **use_ssd**: *bool, default=False*\ - If set to True, RoIs fromm SSD are fed to the seq2Seq-nms model. Otherwise, RoIs from the default detector of the specified dataset are used as input. + If set to True, RoIs from SSD are fed to the seq2Seq-nms model. Otherwise, RoIs from the default detector of the specified dataset are used as input. From 09b1e2e0a497ac50f5aa7397637a8e93c98864da Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 17:51:41 +0200 Subject: [PATCH 053/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../object-detection-2d-nms-seq2seq_nms.md | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index e551378afe..0365b986a7 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -83,3 +83,26 @@ Parameters: Specifies the path to the folder where the datasets are stored. - **use_ssd**: *bool, default=False*\ If set to True, RoIs from SSD are fed to the seq2Seq-nms model. Otherwise, RoIs from the default detector of the specified dataset are used as input. + +#### `Seq2SeqNMSLearner.eval` +```python +Seq2SeqNMSLearner.eval(self, dataset, split, verbose, max_dt_boxes, datasets_folder, use_ssd) +``` + +Performs evaluation on a set of dataset. + +Parameters: + +- **dataset**: *{'PETS', 'COCO'}*\ + Specifies the name of the dataset among those available from training. +- **split**: *{'train', 'val', 'test'} default='test'*\ + Specifies the set of the corresponding dataset where the evaluation will be performed. +- **verbose**: *bool, default=True*\ + If True, enables maximum verbosity. +- **max_dt_boxes**: *int, default=500*\ + Specifies the maximum number of RoIs provided to seq2Seq-nms model as input. +- **datasets_folder**: *str, default='./datasets'*\ + Specifies the path to the folder where the datasets are stored. +- **use_ssd**: *bool, default=False*\ + If set to True, RoIs from SSD are fed to the seq2Seq-nms model. Otherwise, RoIs from the default detector of the specified dataset are used as input. + From d0c90260857866e94819aea46c6bcd505f922b6a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 17:55:58 +0200 Subject: [PATCH 054/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../object-detection-2d-nms-seq2seq_nms.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 0365b986a7..2a27a06931 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -106,3 +106,18 @@ Parameters: - **use_ssd**: *bool, default=False*\ If set to True, RoIs from SSD are fed to the seq2Seq-nms model. Otherwise, RoIs from the default detector of the specified dataset are used as input. +#### `Seq2SeqNMSLearner.infer` +```python +Seq2SeqNMSLearner.infer(self, boxes, scores, boxes_sorted, max_dt_boxes, img_res, threshold) +``` + +Performs non-maximum suppression, using seq2seq-nms. Appearance-based RoI feature computation is not included. + +Parameters: + +- **img**: *object*\ + Object of type engine.data.Image. +- **threshold**: *float, default=0.2*\ + Defines the detection threshold. Bounding boxes with confidence under this value are discarded. +- **keep_size**: *bool, default=False*\ + Specifies whether to resize the input image to *self.img_size* or keep original image dimensions. From 30222a3bd2bdfb7f9b80ca827adc11714c00ae6a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 8 Mar 2022 18:06:43 +0200 Subject: [PATCH 055/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../object-detection-2d-nms-seq2seq_nms.md | 43 ++++++++++++++++--- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 2a27a06931..fb805fd057 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -111,13 +111,42 @@ Parameters: Seq2SeqNMSLearner.infer(self, boxes, scores, boxes_sorted, max_dt_boxes, img_res, threshold) ``` -Performs non-maximum suppression, using seq2seq-nms. Appearance-based RoI feature computation is not included. +Performs non-maximum suppression, using seq2seq-nms. In the case where FMoD is selected for appearance-based RoI feature computation, FMoD maps are not computed. Parameters: -- **img**: *object*\ - Object of type engine.data.Image. -- **threshold**: *float, default=0.2*\ - Defines the detection threshold. Bounding boxes with confidence under this value are discarded. -- **keep_size**: *bool, default=False*\ - Specifies whether to resize the input image to *self.img_size* or keep original image dimensions. +#### `Seq2SeqNMSLearner.run_nms` +```python +Seq2SeqNMSLearner.run_nms(self, boxes, scores, boxes_sorted, max_dt_boxes, img_res, threshold) +``` + +Performs non-maximum suppression, using seq2seq-nms. It incorporates the full pipeline needed for inference. + +Parameters: + +#### `Seq2SeqNMSLearner.save` +```python +Seq2SeqNMSLearner.save(self, path, verbose) +``` + +Saves a model in OpenDR format at the specified path. + +Parameters: + +#### `Seq2SeqNMSLearner.load` +```python +Seq2SeqNMSLearner.load(self, path, verbose) +``` + +Loads a model which was previously saved in OpenDR format at the specified path. + +Parameters: + +#### `Seq2SeqNMSLearner.download` +```python +Seq2SeqNMSLearner.download(self, path, mode, verbose, url) +``` + +Downloads pretrained models of seq2seq-nms. + +Parameters: From c6dc777fd1a8eb4b683042a080da6c933abf32ba Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 13:50:40 +0200 Subject: [PATCH 056/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index fb805fd057..0ff7b4e04b 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -124,6 +124,9 @@ Performs non-maximum suppression, using seq2seq-nms. It incorporates the full pi Parameters: +- **boxes**: *numpy.ndarray, default=None*\ + Image coordinates of candidate detection RoIs, expressed as the coordinates of their upper-left and top-down corners (x_min, y_min, x_max, y_max). For N candidate detection RoIS, the size of the array is Nx4. + #### `Seq2SeqNMSLearner.save` ```python Seq2SeqNMSLearner.save(self, path, verbose) From 26d67828f63242605bc76bf3893d4a0811e19f76 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 13:59:42 +0200 Subject: [PATCH 057/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../object-detection-2d-nms-seq2seq_nms.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 0ff7b4e04b..799c46df70 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -125,8 +125,18 @@ Performs non-maximum suppression, using seq2seq-nms. It incorporates the full pi Parameters: - **boxes**: *numpy.ndarray, default=None*\ - Image coordinates of candidate detection RoIs, expressed as the coordinates of their upper-left and top-down corners (x_min, y_min, x_max, y_max). For N candidate detection RoIS, the size of the array is Nx4. - + Image coordinates of candidate detection RoIs, expressed as the coordinates of their upper-left and top-down corners (x_min, y_min, x_max, y_max). For N candidate detection RoIs, the size of the array is Nx4. +- **scores**: *numpy.ndarray, default=None*\ + Specifies the scores of the candidate detection RoIs, assigned previously by a detector. For N candidate detection RoIs, the size of the array is Nx1. +- **boxes_sorted**: *bool, default=False*\ + Specifies whether *boxes* and *scores* are sorted based on *scores* in descending order. +- **max_dt_boxes**: *int, default=400*\ + Specifies the maximum number of detection RoIs that are fed as input to seq2seq-nms model. +- **img_res**: *[int, int], default=None*\ + Specifies the image resolution expressed as [width, height]. +- **threshold**: *float, default=0.1*\ + Specifies the score threshold that will determine which RoIs will be kept after seq2seq-nms rescoring. + #### `Seq2SeqNMSLearner.save` ```python Seq2SeqNMSLearner.save(self, path, verbose) From 7685678f7a61df2df3ad573c115fa85918466dc6 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 15:08:14 +0200 Subject: [PATCH 058/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../object-detection-2d-nms-seq2seq_nms.md | 38 ++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 799c46df70..2254d46770 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -115,9 +115,22 @@ Performs non-maximum suppression, using seq2seq-nms. In the case where FMoD is s Parameters: +- **boxes**: *torch.tensor, default=None*\ + Image coordinates of candidate detection RoIs, expressed as the coordinates of their upper-left and top-down corners (x_min, y_min, x_max, y_max). For N candidate detection RoIs, the size of the *torch.tensor* is Nx4. +- **scores**: *torch.tensor, default=None*\ + Specifies the scores of the candidate detection RoIs, assigned previously by a detector. For N candidate detection RoIs, the size of the *torch.tensor* is Nx1. +- **boxes_sorted**: *bool, default=False*\ + Specifies whether *boxes* and *scores* are sorted based on *scores* in descending order. +- **max_dt_boxes**: *int, default=400*\ + Specifies the maximum number of detection RoIs that are fed as input to seq2seq-nms model. +- **img_res**: *[int, int], default=None*\ + Specifies the image resolution expressed as [width, height]. +- **threshold**: *float, default=0.1*\ + Specifies the score threshold that will determine which RoIs will be kept after seq2seq-nms rescoring. + #### `Seq2SeqNMSLearner.run_nms` ```python -Seq2SeqNMSLearner.run_nms(self, boxes, scores, boxes_sorted, max_dt_boxes, img_res, threshold) +Seq2SeqNMSLearner.run_nms(self, boxes, scores, img, threshold, boxes_sorted, top_k) ``` Performs non-maximum suppression, using seq2seq-nms. It incorporates the full pipeline needed for inference. @@ -130,22 +143,37 @@ Parameters: Specifies the scores of the candidate detection RoIs, assigned previously by a detector. For N candidate detection RoIs, the size of the array is Nx1. - **boxes_sorted**: *bool, default=False*\ Specifies whether *boxes* and *scores* are sorted based on *scores* in descending order. -- **max_dt_boxes**: *int, default=400*\ +- **top_k**: *int, default=400*\ Specifies the maximum number of detection RoIs that are fed as input to seq2seq-nms model. -- **img_res**: *[int, int], default=None*\ - Specifies the image resolution expressed as [width, height]. +- **img**: *object*\ + Object of type engine.data.Image. - **threshold**: *float, default=0.1*\ Specifies the score threshold that will determine which RoIs will be kept after seq2seq-nms rescoring. #### `Seq2SeqNMSLearner.save` ```python -Seq2SeqNMSLearner.save(self, path, verbose) +Seq2SeqNMSLearner.save(self, path, verbose, optimizer, scheduler, current_epoch, max_dt_boxes) ``` Saves a model in OpenDR format at the specified path. Parameters: +- **path**: *str*\ + Specifies the folder where the model will be saved. +- **verbose**: *bool default=True*\ + If True, enables maximum verbosity. +- **optimizer**: *torch.optim.Optimizer default=None*\ + Specifies the optimizer used for training. +- **scheduler**: *torch.optim.lr_scheduler default=None*\ + Specifies the learning rate scheduler used for training. +- **current_epoch**: *int, default=None*\ + Specifies the number of epochs the model has been trained. +- **max_dt_boxes**: *int, default=400*\ + Specifies the maximum number of detection RoIs that are fed as input to seq2seq-nms model. + + + #### `Seq2SeqNMSLearner.load` ```python Seq2SeqNMSLearner.load(self, path, verbose) From 22c5e51b5f50357987f7a74fd955e071db74c78c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 15:56:46 +0200 Subject: [PATCH 059/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../object-detection-2d-nms-seq2seq_nms.md | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 2254d46770..401386111b 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -5,8 +5,7 @@ The *seq2seq-nms* module contains the *Seq2SeqNMSLearner* class, which inherits ### Class Seq2SeqNMSLearner Bases: `engine.learners.Learner` - -It can be used to perform single-class non-maximum suppression on images (inference) as well as training new seq2seq-nms models. +It can be used to perform single-class non-maximum suppression on images (inference) as well as training new seq2seq-nms models. The implementation is based on [[1]](#seq2seq_nms-1). The [Seq2SeqNMSLearner](/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py) class has the following public methods: @@ -183,11 +182,35 @@ Loads a model which was previously saved in OpenDR format at the specified path. Parameters: +- **path**: *str*\ + Specifies the folder where the model will be loaded from. +- **verbose**: *bool default=True*\ + If True, enables maximum verbosity. + + #### `Seq2SeqNMSLearner.download` ```python -Seq2SeqNMSLearner.download(self, path, mode, verbose, url) +Seq2SeqNMSLearner.download(self, path, model_name, verbose, url) ``` Downloads pretrained models of seq2seq-nms. Parameters: + +Downloads data needed for the various functions of the learner, e.g., pretrained models as well as test data. + +Parameters: + +- **path**: *str, default=None*\ + Specifies the folder where data will be downloaded. If *None*, the *self.temp_path* directory is used instead. +- **model_name**: *{'seq2seq_medium_pets_jpd_fmod_3', 'seq2seq_medium_pets_ssd_fmod_3', 'seq2seq_medium_coco_frcn_fmod_3', 'seq2seq_medium_pets_ssd_fmod_3'}, default=''seq2seq_medium_pets_jpd_fmod_3'*\ + If *'pretrained'*, downloads a pretrained detector model. If *'images'*, downloads an image to perform inference on. If + *'test_data'* downloads a dummy dataset for testing purposes. +- **verbose**: *bool default=True*\ + If True, enables maximum verbosity. +- **url**: *str, default=OpenDR FTP URL*\ + URL of the FTP server. + + #### References +[1] Neural Attention-driven Non-Maximum Suppression for Person Detection, +[TechRxiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). From d9c760060cd86dc3a7653b7fea8861caf5b1923c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 15:57:41 +0200 Subject: [PATCH 060/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 401386111b..2bfdd2d768 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -211,6 +211,6 @@ Parameters: - **url**: *str, default=OpenDR FTP URL*\ URL of the FTP server. - #### References +#### References [1] Neural Attention-driven Non-Maximum Suppression for Person Detection, [TechRxiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). From 829ef637796de589dd775324635f961c35486493 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:25:34 +0200 Subject: [PATCH 061/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../object-detection-2d-nms-seq2seq_nms.md | 52 +++++++++++++++++-- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 2bfdd2d768..bbf2717d6f 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -13,7 +13,7 @@ public methods: #### `Seq2SeqNMSLearner` constructor ```python Seq2SeqNMSLearner(self, lr, epochs, device, temp_path, checkpoint_after_iter, checkpoint_load_iter, log_after, variant, experiment_name, - iou_filtering, dropout, pretrained_demo_model, app_feats, fmod_map_type, fmod_map_bin, app_input_dim, fmod_init_path) + iou_filtering, dropout, pretrained_demo_model, app_feats, fmod_map_type, fmod_map_bin, app_input_dim) ``` Constructor parameters: @@ -50,9 +50,6 @@ Constructor parameters: Specifies whether FMoD maps are binary or not, in the case where *app_feats*='fmod'. - **app_input_dim**: *int, default=None*\ Specifies the dimension of appearance-based RoI features. In the case where *app_feats*='fmod', the corresponding dimension is automatically computed. -- **fmod_init_path**: *str, default=None *\ - Specifies the path to the the file used for normalizing appearance-based features, in the case where *app_feats*='fmod'. - #### `Seq2SeqNMSLearner.fit` @@ -211,6 +208,53 @@ Parameters: - **url**: *str, default=OpenDR FTP URL*\ URL of the FTP server. +#### Examples + +* **Training example using an `ExternalDataset`**. + To train seq2seq-nms properly, the PETS and COCO datasets are supported as Dataset_NMS types. + + ```python + from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner + import os + OPENDR_HOME = os.environ['OPENDR_HOME'] + +seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=0.8, experiment_name='pets_exp0', + app_feats='fmod', checkpoint_after_iter=1, + temp_path=OPENDR_HOME + '/src/opendr/perception/' + 'object_detection_2d/nms/seq2seq_nms/temp', + epochs=8) + +seq2SeqNMSLearner.fit(dataset='PETS', use_ssd=False, + datasets_folder=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/datasets', + logging_path='./logs_pets_exp1', silent=False, verbose=True, nms_gt_iou=0.50, + max_dt_boxes=500) + ``` + + +* **Inference and result drawing example on a test .jpg image using OpenCV.** + ```python +from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner +from opendr.engine.data import Image +from opendr.perception.object_detection_2d import SingleShotDetectorLearner +from opendr.perception.object_detection_2d import draw_bounding_boxes +import os +OPENDR_HOME = os.environ['OPENDR_HOME'] + +seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, experiment_name='pets_exp0', + app_feats='fmod', device='cpu') +seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/pets_exp0/' + 'checkpoints/checkpoint_epoch_7', verbose=True) +ssd = SingleShotDetectorLearner(device='cuda') +ssd.download(".", mode="pretrained") +ssd.load("./ssd_default_person", verbose=True) +img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg') +if not isinstance(img, Image): + img = Image(img) +boxes = ssd.infer(img, threshold=0.25, custom_nms=seq2SeqNMSLearner) +draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) + ``` + + #### References [1] Neural Attention-driven Non-Maximum Suppression for Person Detection, [TechRxiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). From 0ef6297fc808fe6c182778adae26f49c7fe3cc28 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:26:59 +0200 Subject: [PATCH 062/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index bbf2717d6f..c0d831f6cb 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -210,7 +210,7 @@ Parameters: #### Examples -* **Training example using an `ExternalDataset`**. +* **Training example.** To train seq2seq-nms properly, the PETS and COCO datasets are supported as Dataset_NMS types. ```python @@ -218,19 +218,17 @@ Parameters: import os OPENDR_HOME = os.environ['OPENDR_HOME'] -seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=0.8, experiment_name='pets_exp0', + seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=0.8, experiment_name='pets_exp0', app_feats='fmod', checkpoint_after_iter=1, temp_path=OPENDR_HOME + '/src/opendr/perception/' 'object_detection_2d/nms/seq2seq_nms/temp', epochs=8) - -seq2SeqNMSLearner.fit(dataset='PETS', use_ssd=False, + seq2SeqNMSLearner.fit(dataset='PETS', use_ssd=False, datasets_folder=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/datasets', logging_path='./logs_pets_exp1', silent=False, verbose=True, nms_gt_iou=0.50, max_dt_boxes=500) ``` - - + * **Inference and result drawing example on a test .jpg image using OpenCV.** ```python from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner From b970a1fb8b375cdf2398b7643f5c9669de1a60da Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:28:01 +0200 Subject: [PATCH 063/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index c0d831f6cb..4bccdbd3f1 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -230,7 +230,8 @@ Parameters: ``` * **Inference and result drawing example on a test .jpg image using OpenCV.** - ```python + ``` +python from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner @@ -251,8 +252,8 @@ if not isinstance(img, Image): boxes = ssd.infer(img, threshold=0.25, custom_nms=seq2SeqNMSLearner) draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) ``` - - + + #### References [1] Neural Attention-driven Non-Maximum Suppression for Person Detection, [TechRxiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). From 5cd5fb71b508fb0a2ba48c419d5a805d651520f4 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:29:06 +0200 Subject: [PATCH 064/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../object-detection-2d-nms-seq2seq_nms.md | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 4bccdbd3f1..0fcbaba486 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -231,26 +231,26 @@ Parameters: * **Inference and result drawing example on a test .jpg image using OpenCV.** ``` -python -from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner -from opendr.engine.data import Image -from opendr.perception.object_detection_2d import SingleShotDetectorLearner -from opendr.perception.object_detection_2d import draw_bounding_boxes -import os -OPENDR_HOME = os.environ['OPENDR_HOME'] - -seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, experiment_name='pets_exp0', - app_feats='fmod', device='cpu') -seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/pets_exp0/' - 'checkpoints/checkpoint_epoch_7', verbose=True) -ssd = SingleShotDetectorLearner(device='cuda') -ssd.download(".", mode="pretrained") -ssd.load("./ssd_default_person", verbose=True) -img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg') -if not isinstance(img, Image): - img = Image(img) -boxes = ssd.infer(img, threshold=0.25, custom_nms=seq2SeqNMSLearner) -draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) + python + from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner + from opendr.engine.data import Image + from opendr.perception.object_detection_2d import SingleShotDetectorLearner + from opendr.perception.object_detection_2d import draw_bounding_boxes + import os + OPENDR_HOME = os.environ['OPENDR_HOME'] + + seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, experiment_name='pets_exp0', + app_feats='fmod', device='cpu') + seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/pets_exp0/' + 'checkpoints/checkpoint_epoch_7', verbose=True) + ssd = SingleShotDetectorLearner(device='cuda') + ssd.download(".", mode="pretrained") + ssd.load("./ssd_default_person", verbose=True) + img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg') + if not isinstance(img, Image): + img = Image(img) + boxes = ssd.infer(img, threshold=0.25, custom_nms=seq2SeqNMSLearner) + draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) ``` From 3876226b6b8d7aedd0aebf5fa4fa35546b070264 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:29:39 +0200 Subject: [PATCH 065/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 0fcbaba486..c24c51c953 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -230,8 +230,8 @@ Parameters: ``` * **Inference and result drawing example on a test .jpg image using OpenCV.** - ``` - python + + ```python from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner From ed5ecf99724081c89f97232db42c9409c186e2dd Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:34:44 +0200 Subject: [PATCH 066/374] Add files via upload --- .../nms/seq2seq_nms/algorithm/fmod.py | 4 +- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 577 +++++++----------- 2 files changed, 229 insertions(+), 352 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py index 73114307bb..aee4f2f8aa 100755 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py @@ -24,8 +24,8 @@ class FMoD: def __init__(self, roi_pooling_dim=None, pyramid_depth=3, map_type="SIFT", map_bin=False, resize_dim=None, device='cpu'): if roi_pooling_dim is None: - roi_pooling_dim = [160, 160] - self.roi_pooling_dim = roi_pooling_dim + roi_pooling_dim = 160 + self.roi_pooling_dim = [roi_pooling_dim, roi_pooling_dim] self.pyramid_depth = pyramid_depth self.boxes_p = [] self.rp_size = [] diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index ac6257cff1..56154096e5 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -15,7 +15,6 @@ import torch.nn.functional as F import pickle import numpy as np -import torchvision import os from opendr.engine.learners import Learner from opendr.engine.constants import OPENDR_SERVER_URL @@ -26,42 +25,43 @@ from tqdm import tqdm import collections import json -from pycocotools.coco import COCO -from pycocotools.cocoeval import COCOeval -import sys from opendr.engine.target import BoundingBox, BoundingBoxList from opendr.engine.data import Image from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.fmod import FMoD -from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.nms_dataset import Dataset_NMS -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom - +from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ + run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS +import pickle class Seq2SeqNMSLearner(Learner, NMSCustom): - def __init__(self, lr=0.0001, lr_schedule='', checkpoint_after_iter=1, checkpoint_load_iter=0, - experiment_name='default', temp_path='temp', device='cuda', app_feats='fmod', - fmod_map_type='EDGEMAP_B', fmod_map_bin=True, dropout=0.02, fmod_roi_pooling_dim=160, - fmod_map_res_dim=800, fmod_pyramid_lvl=3, lq_dim=256, sq_dim=128, app_input_dim=None, - num_JPUs=4, pretrained_demo_model=None, log_after=500, iou_filtering=None, fmod_init_path=None): - super(Seq2SeqNMSLearner, self).__init__(lr=lr, batch_size=1, lr_schedule=lr_schedule, + def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', checkpoint_after_iter=0, + checkpoint_load_iter=0, log_after=500, variant='medium', experiment_name='default', + iou_filtering=0.8, dropout=0.05, pretrained_demo_model=None, app_feats='fmod', + fmod_map_type='EDGEMAP', fmod_map_bin=True, app_input_dim=None): + super(Seq2SeqNMSLearner, self).__init__(lr=lr, batch_size=1, checkpoint_after_iter=checkpoint_after_iter, checkpoint_load_iter=checkpoint_load_iter, temp_path=temp_path, device=device, backbone='default') + self.epochs = epochs + self.variant = variant self.app_feats = app_feats self.use_app_feats = False if self.app_feats is not None: self.use_app_feats = True if self.app_feats == 'fmod': - self.fmod_normalization = None self.fmod_map_type = fmod_map_type - self.fmod_roi_pooling_dim = [fmod_roi_pooling_dim, fmod_roi_pooling_dim] - self.fmod_map_res_dim = fmod_map_res_dim - self.fmod_pyramid_lvl = fmod_pyramid_lvl + self.fmod_roi_pooling_dim = 160 + self.fmod_map_res_dim = 600 + self.fmod_pyramid_lvl = 3 + self.sef_fmod_architecture() self.fmod_feats_dim = 0 for i in range(0, self.fmod_pyramid_lvl): self.fmod_feats_dim = self.fmod_feats_dim + 15 * (pow(4, i)) self.fmod_map_bin = fmod_map_bin self.app_input_dim = self.fmod_feats_dim + self.fmod_mean_std = None elif self.app_feats == 'zeros' or self.app_feats == 'custom': if app_input_dim is None: raise Exception("The dimension of the input appearance-based features is not provided...") @@ -69,11 +69,13 @@ def __init__(self, lr=0.0001, lr_schedule='', checkpoint_after_iter=1, checkpoin self.app_input_dim = app_input_dim if self.app_feats == 'custom': raise AttributeError("Custom appearance-based features are not yet supported.") + self.lq_dim = 256 + self.sq_dim = 128 + self.geom_input_dim = 14 + self.num_JPUs = 4 self.geom_input_dim = 14 - self.lq_dim = lq_dim - self.sq_dim = sq_dim + self.set_architecture() self.dropout = dropout - self.num_JPUs = num_JPUs self.parent_dir = temp_path if not os.path.isdir(self.parent_dir): os.mkdir(self.parent_dir) @@ -86,18 +88,15 @@ def __init__(self, lr=0.0001, lr_schedule='', checkpoint_after_iter=1, checkpoin self.iou_filtering = iou_filtering self.classes = None self.class_ids = None - self.device = device self.fMoD = None + self.fmod_init_file = None if self.app_feats == 'fmod': self.fMoD = FMoD(roi_pooling_dim=self.fmod_roi_pooling_dim, pyramid_depth=self.fmod_pyramid_lvl, resize_dim=self.fmod_map_res_dim, map_type=self.fmod_map_type, map_bin=self.fmod_map_bin, device=self.device) - if fmod_init_path is not None: - fmod_mean_std = load_FMoD_init(fmod_init_path) - self.fMoD.set_mean_std(mean_values=fmod_mean_std['mean'], std_values=fmod_mean_std['std']) - def fit(self, dataset, val_dataset=None, epochs=None, logging_path='', logging_flush_secs=30, silent=True, - verbose=True, nms_gt_iou=0.5, boxes_sorted=False, max_dt_boxes=400, datasets_folder='./datasets', + def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, + verbose=True, nms_gt_iou=0.5, max_dt_boxes=400, datasets_folder='./datasets', use_ssd=False): dataset_nms = Dataset_NMS(path=datasets_folder, dataset_name=dataset, split='train', use_ssd=use_ssd) @@ -119,16 +118,14 @@ def fit(self, dataset, val_dataset=None, epochs=None, logging_path='', logging_f os.makedirs(checkpoints_folder) if self.pretrained_demo_model is not None: - self.download(mode="weights", verbose=verbose and not silent) + self.download(path=self.temp_path, model_name=self.pretrained_demo_model, + verbose=verbose and not silent) weights_path = None if self.pretrained_demo_model == 'PETS': - weights_path = os.path.join(self.parent_dir, "seq2seq_pets.pth.tar") - self.checkpoint_load_iter = '?' + weights_path = os.path.join(checkpoints_folder, self.pretrained_demo_model) + self.checkpoint_load_iter = 7 elif self.pretrained_demo_model == 'COCO': - weights_path = os.path.join(self.parent_dir, "seq2seq_coco.pth.tar") - self.checkpoint_load_iter = '?' - elif self.pretrained_demo_model == 'CrownHuman': - weights_path = os.path.join(self.parent_dir, "seq2seq_crowdhuman.pth.tar") + weights_path = os.path.join(checkpoints_folder, "seq2seq_coco.pth") self.checkpoint_load_iter = '?' self.load(path=weights_path, verbose=verbose) elif self.checkpoint_load_iter != 0: @@ -143,16 +140,16 @@ def fit(self, dataset, val_dataset=None, epochs=None, logging_path='', logging_f if self.device == 'cuda': self.model = self.model.cuda() - if epochs is None: + if self.epochs is None: raise ValueError("Training epochs not specified") - elif epochs <= self.checkpoint_load_iter: + elif self.epochs <= self.checkpoint_load_iter: raise ValueError("Training epochs are less than those of the loaded model") - if self.app_feats == 'fmod': - fmod_mean_std = load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, - fmod_pyramid_lvl=self.fmod_pyramid_lvl, - datasets_folder=datasets_folder, verbose=verbose) - self.fMoD.set_mean_std(mean_values=fmod_mean_std['mean'], std_values=fmod_mean_std['std']) + if self.app_feats == 'fmod' and self.fmod_mean_std is None: + self.fmod_mean_std = self.load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, + fmod_pyramid_lvl=self.fmod_pyramid_lvl, + datasets_folder=datasets_folder, verbose=verbose) + self.fMoD.set_mean_std(mean_values=self.fmod_mean_std['mean'], std_values=self.fmod_mean_std['std']) start_epoch = 0 drop_after_epoch = [4, 6] @@ -172,7 +169,8 @@ def fit(self, dataset, val_dataset=None, epochs=None, logging_path='', logging_f training_weights = compute_class_weights(pos_weights=[0.9, 0.1], max_dets=max_dt_boxes, dataset_nms=dataset_nms) # Single class NMS only. class_index = 1 - for epoch in range(start_epoch, epochs): + training_dict = {"cross_entropy_loss": []} + for epoch in range(start_epoch, self.epochs): pbar = None if not silent: pbarDesc = "Epoch #" + str(epoch) + " progress" @@ -187,9 +185,8 @@ def fit(self, dataset, val_dataset=None, epochs=None, logging_path='', logging_f dt_boxes = torch.tensor( dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 0:4]).float() dt_scores = torch.tensor(dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 4]).float() - if not boxes_sorted: - dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) - dt_boxes = dt_boxes[dt_scores_ids] + dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) + dt_boxes = dt_boxes[dt_scores_ids] else: continue gt_boxes = torch.tensor([]).float() @@ -231,16 +228,16 @@ def fit(self, dataset, val_dataset=None, epochs=None, logging_path='', logging_f elif self.app_feats == 'custom': raise AttributeError("Custom appearance-based features are not yet supported.") - msk = compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) - q_geom_feats, k_geom_feats = compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, - resolution=img_res) + msk = self.compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) + q_geom_feats, k_geom_feats = self.compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, + resolution=img_res) optimizer.zero_grad() preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, app_feats=app_feats) preds = torch.clamp(preds, 0.001, 1 - 0.001) - labels = matching_module(scores=preds, dt_boxes=dt_boxes, gt_boxes=gt_boxes, - iou_thres=nms_gt_iou) + labels = det_matching(scores=preds, dt_boxes=dt_boxes, gt_boxes=gt_boxes, + iou_thres=nms_gt_iou) # weights = (2.92 * labels + 0.932 * (1 - labels)).cuda() weights = (training_weights[class_index][1] * labels + training_weights[class_index][0] * ( @@ -272,25 +269,23 @@ def fit(self, dataset, val_dataset=None, epochs=None, logging_path='', logging_f if not silent: pbar.close() if verbose: - print(''.join(['Epoch: {}', + print(''.join(['\nEpoch: {}', ' cross_entropy_loss: {}\n']).format(epoch, total_loss_epoch / len(train_ids))) + training_dict['cross_entropy_loss'].append(total_loss_epoch / len(train_ids)) if self.checkpoint_after_iter != 0 and epoch % self.checkpoint_after_iter == self.checkpoint_after_iter - 1: snapshot_name = '{}/checkpoint_epoch_{}'.format(checkpoints_folder, epoch) - # Save checkpoint with full information for training state self.save(path=snapshot_name, optimizer=optimizer, scheduler=scheduler, current_epoch=epoch, max_dt_boxes=max_dt_boxes) total_loss_epoch = 0 scheduler.step() if logging: file_writer.close() - # if not silent and verbose: - # print("Model trainable parameters:", self.count_parameters()) + return training_dict - def eval(self, dataset, verbose=True, split='test', boxes_sorted=False, max_dt_boxes=400, eval_folder=None, - use_ssd=False, datasets_folder='./datasets'): + def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, + datasets_folder='./datasets', use_ssd=False): - # Load dataset dataset_nms = Dataset_NMS(path=datasets_folder, dataset_name=dataset, split=split, use_ssd=use_ssd) if self.classes is None: @@ -299,15 +294,14 @@ def eval(self, dataset, verbose=True, split='test', boxes_sorted=False, max_dt_b annotations_filename = str.lower(dataset) + '_' + split + '.json' - if eval_folder is None: - eval_folder = os.path.join(self.parent_dir, self.experiment_name, 'eval') + eval_folder = os.path.join(self.parent_dir, self.experiment_name, 'eval') + if not os.path.isdir(os.path.join(self.parent_dir, self.experiment_name)): + os.mkdir(os.path.join(self.parent_dir, self.experiment_name)) if not os.path.isdir(eval_folder): os.mkdir(eval_folder) output_file = os.path.join(eval_folder, 'detections.json') - # Model initialization if needed if self.model is None and self.checkpoint_load_iter != 0: - # No model loaded, initializing new self.init_model() checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) checkpoint_folder = os.path.join(self.parent_dir, self.experiment_name, 'checkpoints') @@ -317,17 +311,16 @@ def eval(self, dataset, verbose=True, split='test', boxes_sorted=False, max_dt_b elif self.model is None: raise AttributeError("self.model is None. Please load a model or set checkpoint_load_iter.") - if self.app_feats == 'fmod' and (self.fMoD.mean is None or self.fMoD.std is None): - fmod_mean_std = load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, - fmod_pyramid_lvl=self.fmod_pyramid_lvl, - datasets_folder=datasets_folder, verbose=verbose) - self.fMoD.set_mean_std(mean_values=fmod_mean_std['mean'], std_values=fmod_mean_std['std']) + if self.app_feats == 'fmod' and (self.fmod_mean_std is None): + self.fmod_mean_std = self.load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, + fmod_pyramid_lvl=self.fmod_pyramid_lvl, + datasets_folder=datasets_folder, verbose=verbose) + self.fMoD.set_mean_std(mean_values=self.fmod_mean_std['mean'], std_values=self.fmod_mean_std['std']) - self.model = self.model.eval() # Change model state to evaluation + self.model = self.model.eval() if self.device == "cuda": self.model = self.model.cuda() - # Change model state to evaluation self.model = self.model.eval() if self.device == "cuda": self.model = self.model.cuda() @@ -348,9 +341,8 @@ def eval(self, dataset, verbose=True, split='test', boxes_sorted=False, max_dt_b if len(dataset_nms.src_data[sample_id]['dt_boxes'][class_index]) > 0: dt_boxes = torch.tensor(dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 0:4]).float() dt_scores = torch.tensor(dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 4]).float() - if not boxes_sorted: - dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) - dt_boxes = dt_boxes[dt_scores_ids] + dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) + dt_boxes = dt_boxes[dt_scores_ids] else: continue @@ -381,9 +373,9 @@ def eval(self, dataset, verbose=True, split='test', boxes_sorted=False, max_dt_b app_feats = app_feats.cuda() elif self.app_feats == 'custom': raise AttributeError("Custom appearance-based features are not yet supported.") - msk = compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) - q_geom_feats, k_geom_feats = compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, - resolution=img_res) + msk = self.compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) + q_geom_feats, k_geom_feats = self.compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, + resolution=img_res) with torch.no_grad(): preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, app_feats=app_feats) @@ -412,20 +404,7 @@ def eval(self, dataset, verbose=True, split='test', boxes_sorted=False, max_dt_b print(eval_result[i][0][3][1]) print('\n') - def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoch=None, max_dt_boxes=800): - """ - Method for saving the current model in the path provided - :param path: path for the model to be saved - :type path: str - :param verbose: whether to print a success message or not, defaults to False - :type verbose: bool, optional - :param optimizer: the optimizer used for training - :type optimizer: Optimizer PyTorch object - :param scheduler: the scheduler used for training - :type scheduler: Scheduler PyTorch object - :param current_epoch: the current epoch id - :type current_epoch: int - """ + def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoch=None, max_dt_boxes=400): path = path.split('.')[0] custom_dict = {'state_dict': self.model.state_dict(), 'optimizer': optimizer.state_dict(), 'scheduler': scheduler.state_dict(), 'current_epoch': current_epoch} @@ -436,14 +415,16 @@ def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoc "format": "pth", "classes": self.classes, "app_feats": self.app_feats, "lq_dim": self.lq_dim, "sq_dim": self.sq_dim, "num_JPUs": self.num_JPUs, "geom_input_dim": self.geom_input_dim, "app_input_dim": self.app_input_dim, - "max_dt_boxes": max_dt_boxes} + "max_dt_boxes": max_dt_boxes, "variant": self.variant} if self.app_feats == 'fmod': metadata["fmod_map_type"] = self.fmod_map_type metadata["fmod_map_bin"] = self.fmod_map_bin metadata["fmod_roi_pooling_dim"] = self.fmod_roi_pooling_dim metadata["fmod_map_res_dim"] = self.fmod_map_res_dim metadata["fmod_pyramid_lvl"] = self.fmod_pyramid_lvl - + metadata["fmod_normalization"] = 'fmod_normalization.pkl' + with open(os.path.join(os.path.dirname(path),'fmod_normalization.pkl'), 'wb') as f: + pickle.dump(self.fmod_mean_std, f) with open(path + '.json', 'w', encoding='utf-8') as f: json.dump(metadata, f, ensure_ascii=False, indent=4) if verbose: @@ -462,13 +443,7 @@ def init_model(self): raise UserWarning("Tried to initialize model while model is already initialized.") def load(self, path, verbose=False): - """ - Loads the model from inside the path provided, based on the metadata .json file included - :param path: path of the checkpoint file was saved - :type path: str - :param verbose: whether to print success message or not, defaults to 'False' - :type verbose: bool, optional - """ + model_name = os.path.basename(os.path.normpath(path)).split('.')[0] dir_path = os.path.dirname(os.path.normpath(path)) @@ -484,6 +459,16 @@ def load(self, path, verbose=False): except FileNotFoundError as e: e.strerror = "File " + pth_path + "not found." raise e + if metadata['fmod_normalization']: + pkl_fmod = os.path.join(dir_path, metadata["fmod_normalization"]) + if verbose: + print("Loading FMoD normalization values:", pkl_fmod) + try: + with open(pkl_fmod, 'rb') as f: + self.fmod_mean_std = pickle.load(f) + except FileNotFoundError as e: + e.strerror = "File " + pkl_fmod + "not found." + raise e self.assign_params(metadata=metadata, verbose=verbose) self.init_model() @@ -496,6 +481,10 @@ def load(self, path, verbose=False): def assign_params(self, metadata, verbose): + if verbose and self.geom_input_dim is not None and self.geom_input_dim != metadata["variant"]: + print("Incompatible value for the attribute \"variant\". It is now set to: " + + str(metadata["variant"])) + self.variant = metadata["variant"] if verbose and self.geom_input_dim is not None and self.geom_input_dim != metadata["geom_input_dim"]: print("Incompatible value for the attribute \"geom_input_dim\". It is now set to: " + str(metadata["geom_input_dim"])) @@ -546,6 +535,11 @@ def assign_params(self, metadata, verbose): self.num_JPUs = metadata["num_JPUs"] if verbose and 'max_dt_boxes' in metadata: print('Model is trained with as ' + str(metadata['max_dt_boxes']) + 'its maximum number of detections.') + if verbose and self.fmod_pyramid_lvl is not None and \ + self.fmod_pyramid_lvl != metadata["fmod_mean_std"]: + print("Incompatible value for the attribute \"fmod_mean_std\". It is now set to: " + + str(metadata["fmod_mean_std"])) + #self.fmod_mean_std = metadata["fmod_mean_std"] def load_state(self, checkpoint=None): if checkpoint is None: @@ -564,29 +558,44 @@ def load_state(self, checkpoint=None): new_target_state[target_key] = source_state[target_key] else: new_target_state[target_key] = target_state[target_key] - # print('[WARNING] Not found pre-trained parameters for {}'.format(target_key)) self.model.load_state_dict(new_target_state) def count_parameters(self): - """ - Returns the number of the model's trainable parameters. - :return: number of trainable parameters - :rtype: int - """ + if self.model is None: raise UserWarning("Model is not initialized, can't count trainable parameters.") return sum(p.numel() for p in self.model.parameters() if p.requires_grad) - def download(self, path=None, mode="pretrained", verbose=False, - url=OPENDR_SERVER_URL + "perception/pose_estimation/lightweight_open_pose/"): - print('ToDo') + def download(self, path=None, model_name='seq2seq_medium_pets_jpd_fmod_3', verbose=False, + url=OPENDR_SERVER_URL + "perception/object_detection_2d/nms/pretrained/"): + + if path is None: + path = self.temp_path + + if not os.path.exists(path): + os.makedirs(path) + + path = os.path.join(path, model_name) + if not os.path.exists(path): + os.makedirs(path) + + if verbose: + print("Downloading pretrained model...") + + file_url_json = os.path.join(url, "pretrained", model_name + '.json') + file_url_pth = os.path.join(url, "pretrained", model_name + '.pth') + try: + urlretrieve(file_url_json, os.path.join(path, model_name + '.json')) + urlretrieve(file_url_pth, os.path.join(path, model_name + '.pth')) + except: + raise UserWarning('Pretrained model not found on server.') - def infer(self, boxes=None, scores=None, boxes_sorted=False, max_dt_boxes=1200, img_res=None, threshold=0.1): + def infer(self, boxes=None, scores=None, boxes_sorted=False, max_dt_boxes=400, img_res=None, threshold=0.1): bounding_boxes = BoundingBoxList([]) if scores.shape[0] == 0: return bounding_boxes - if scores.shape[1]>1: + if scores.shape[1] > 1: raise ValueError('Multi-class NMS is not supported in Seq2Seq-NMS yet.') if boxes.shape[0] != scores.shape[0]: raise ValueError('Scores and boxes must have the same size in dim 0.') @@ -602,7 +611,6 @@ def infer(self, boxes=None, scores=None, boxes_sorted=False, max_dt_boxes=1200, scores, scores_ids = torch.sort(scores, dim=0, descending=True) boxes = boxes[scores_ids] - val_ids = torch.logical_and((boxes[:, 2] - boxes[:, 0]) > 4, (boxes[:, 3] - boxes[:, 1]) > 4) boxes = boxes[val_ids, :] @@ -625,9 +633,9 @@ def infer(self, boxes=None, scores=None, boxes_sorted=False, max_dt_boxes=1200, elif self.app_feats == 'custom': raise AttributeError("Custom appearance-based features are not yet supported.") - msk = compute_mask(boxes, iou_thres=0.2, extra=0.1) - q_geom_feats, k_geom_feats = compute_geometrical_feats(boxes=boxes, scores=scores, - resolution=img_res) + msk = self.compute_mask(boxes, iou_thres=0.2, extra=0.1) + q_geom_feats, k_geom_feats = self.compute_geometrical_feats(boxes=boxes, scores=scores, + resolution=img_res) with torch.no_grad(): preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, @@ -656,7 +664,7 @@ def reset(self): """This method is not used in this implementation.""" return NotImplementedError - def run_nms(self, boxes=None, scores=None, img=None, threshold=0.2, boxes_sorted=False, top_k=400): + def run_nms(self, boxes=None, scores=None, boxes_sorted=False, top_k=400, img=None, threshold=0.2): if self.app_feats == 'fmod': if not isinstance(img, Image): @@ -682,242 +690,111 @@ def run_nms(self, boxes=None, scores=None, img=None, threshold=0.2, boxes_sorted boxes = self.infer(boxes=boxes, scores=scores, boxes_sorted=boxes_sorted, max_dt_boxes=top_k, img_res=img.opencv().shape[::-1][1:]) return boxes - # draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) - - - -def apply_torchNMS(boxes, scores, iou_thres): - ids_nms = torchvision.ops.nms(boxes, scores, iou_thres) - scores = scores[ids_nms] - boxes = boxes[ids_nms] - return boxes, scores - - -def compute_mask(boxes=None, iou_thres=0.2, extra=0.1): - relations = filter_iou_boxes(boxes, iou_thres=iou_thres) - mask1 = torch.tril(relations).float() - mask2 = extra * torch.triu(relations, diagonal=1).float() - mask = mask1 + mask2 - return mask - - -def filter_iou_boxes(boxes=None, iou_thres=0.2): - ious = bb_intersection_over_union(boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1), - boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1)) - ids_boxes = ious >= iou_thres - return ids_boxes - - -def bb_intersection_over_union(boxAs=None, boxBs=None): - xA = torch.maximum(boxAs[:, :, 0], boxBs[:, :, 0]) - yA = torch.maximum(boxAs[:, :, 1], boxBs[:, :, 1]) - xB = torch.minimum(boxAs[:, :, 2], boxBs[:, :, 2]) - yB = torch.minimum(boxAs[:, :, 3], boxBs[:, :, 3]) - interAreas = torch.maximum(torch.zeros_like(xB), xB - xA + 1) * torch.maximum(torch.zeros_like(yB), yB - yA + 1) - boxAAreas = (boxAs[:, :, 2] - boxAs[:, :, 0] + 1) * (boxAs[:, :, 3] - boxAs[:, :, 1] + 1) - boxBAreas = (boxBs[:, :, 2] - boxBs[:, :, 0] + 1) * (boxBs[:, :, 3] - boxBs[:, :, 1] + 1) - ious = interAreas / (boxAAreas + boxBAreas - interAreas) - return ious - - -def compute_geometrical_feats(boxes, scores, resolution): - boxBs = boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1) - boxAs = boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1) - scoresBs = scores.unsqueeze(0).unsqueeze(-1).repeat(scores.shape[0], 1, 1) - scoresAs = scores.unsqueeze(1).unsqueeze(1).repeat(1, scores.shape[0], 1) - - scale_div = [resolution[0] / 20, resolution[1] / 20] - dx = ((boxBs[:, :, 0] - boxAs[:, :, 0] + boxBs[:, :, 2] - boxAs[:, :, 2]) / 2).unsqueeze(-1) - dy = ((boxBs[:, :, 1] - boxAs[:, :, 1] + boxBs[:, :, 3] - boxAs[:, :, 3]) / 2).unsqueeze(-1) - dxy = dx * dx + dy * dy - dxy = dxy / (scale_div[0] * scale_div[0] + scale_div[1] * scale_div[1]) - dx = (dx / scale_div[0]) - dy = (dy / scale_div[1]) - sx = boxBs[:, :, 2] - boxBs[:, :, 0] - sx_1 = (sx / (boxAs[:, :, 2] - boxAs[:, :, 0])).unsqueeze(-1) - sx_2 = (sx / scale_div[0]).unsqueeze(-1) - sy = boxBs[:, :, 3] - boxBs[:, :, 1] - sy_1 = (sy / (boxAs[:, :, 3] - boxAs[:, :, 1])).unsqueeze(-1) - sy_2 = (sy / scale_div[1]).unsqueeze(-1) - scl = (boxBs[:, :, 2] - boxBs[:, :, 0]) * (boxBs[:, :, 3] - boxBs[:, :, 1]) - scl_1 = (scl / ((boxAs[:, :, 2] - boxAs[:, :, 0]) * (boxAs[:, :, 3] - boxAs[:, :, 1]))).unsqueeze(-1) - scl_2 = (scl / (scale_div[0] * scale_div[1])).unsqueeze(-1) - del scl - - scr_1 = 5 * scoresBs - scr_2 = scr_1 - 5 * scoresAs - - sr_1 = torch.unsqueeze((boxBs[:, :, 3] - boxBs[:, :, 1]) / (boxBs[:, :, 2] - boxBs[:, :, 0]), dim=-1) - sr_2 = torch.unsqueeze(((boxBs[:, :, 3] - boxBs[:, :, 1]) / (boxBs[:, :, 2] - boxBs[:, :, 0])) / ( - (boxAs[:, :, 3] - boxAs[:, :, 1]) / (boxAs[:, :, 2] - boxAs[:, :, 0])), dim=-1) - - ious = 5 * (bb_intersection_over_union(boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1), - boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1))).unsqueeze(-1) - enc_vers_all = torch.cat((dx, dy, dxy, sx_1, sx_2, sy_1, sy_2, ious, scl_1, scl_2, scr_1, scr_2, sr_1, sr_2), dim=2) - enc_vers = enc_vers_all.diagonal(dim1=0, dim2=1).transpose(0, 1).unsqueeze(1) - return enc_vers, enc_vers_all - - -def matching_module(scores, dt_boxes, gt_boxes, iou_thres, device='cuda'): - sorted_indices = torch.argsort(-scores, dim=0) - labels = torch.zeros(len(dt_boxes)) - if device == 'cuda': - labels = labels.cuda() - if gt_boxes.shape[0] == 0: - return labels.unsqueeze(-1) - assigned_GT = -torch.ones(len(gt_boxes)) - r = torch.tensor([-1, -1, -1, -1]).float().unsqueeze(0).unsqueeze(0) - if device == 'cuda': - r = r.cuda() - for s in sorted_indices: - gt_boxes_c = gt_boxes.clone().unsqueeze(0) - gt_boxes_c[0, assigned_GT > -1, :] = r - ious = bb_intersection_over_union(boxAs=dt_boxes[s].clone().unsqueeze(0), boxBs=gt_boxes_c) - annot_iou, annot_box_id = torch.sort(ious.squeeze(), descending=True) - if annot_box_id.ndim > 0: - annot_box_id = annot_box_id[0] - annot_iou = annot_iou[0] - if annot_iou > iou_thres: - assigned_GT[annot_box_id] = s - labels[s] = 1 - return labels.unsqueeze(-1) - - -def run_coco_eval(dt_file_path=None, gt_file_path=None, only_classes=None, max_dets=None, - verbose=False): - if max_dets is None: - max_dets = [200, 400, 600, 800, 1000, 1200] - results = [] - sys.stdout = open(os.devnull, 'w') - for i in range(len(max_dets)): - coco = COCO(gt_file_path) - coco_dt = coco.loadRes(dt_file_path) - cocoEval = COCOeval(coco, coco_dt, 'bbox') - cocoEval.params.iouType = 'bbox' - cocoEval.params.useCats = True - cocoEval.params.catIds = only_classes - cocoEval.params.maxDets = [max_dets[i]] - cocoEval.evaluate() - results.append([summarize_nms(coco_eval=cocoEval, maxDets=max_dets[i]), max_dets[i]]) - # print(results[i]) - del cocoEval, coco_dt, coco - sys.stdout = sys.__stdout__ - return results - - -def summarize_nms(coco_eval=None, maxDets=100): - def summarize(ap=1, iouThr=None, areaRng='all', maxDets=100): - p = coco_eval.params - iStr = ' {:<18} {} @[ IoU={:<9} | area={:>6s} | maxDets={:>3d} ] = {:0.3f}' - titleStr = 'Average Precision' if ap == 1 else 'Average Recall' - typeStr = '(AP)' if ap == 1 else '(AR)' - iouStr = '{:0.2f}:{:0.2f}'.format(p.iouThrs[0], p.iouThrs[-1]) \ - if iouThr is None else '{:0.2f}'.format(iouThr) - aind = [i for i, aRng in enumerate(p.areaRngLbl) if aRng == areaRng] - mind = [i for i, mDet in enumerate(p.maxDets) if mDet == maxDets] - if ap == 1: - # dimension of precision: [TxRxKxAxM] - s = coco_eval.eval['precision'] - # IoU - if iouThr is not None: - t = np.where(iouThr == p.iouThrs)[0] - s = s[t] - s = s[:, :, :, aind, mind] - else: - # dimension of recall: [TxKxAxM] - s = coco_eval.eval['recall'] - if iouThr is not None: - t = np.where(iouThr == p.iouThrs)[0] - s = s[t] - s = s[:, :, aind, mind] - if len(s[s > -1]) == 0: - mean_s = -1 - else: - mean_s = np.mean(s[s > -1]) - stat_str = iStr.format(titleStr, typeStr, iouStr, areaRng, maxDets, mean_s) - return [mean_s, stat_str] - - def summarizeDets(): - stats = [] - stat, stat_str = summarize(1, maxDets=maxDets) - stats.append([stat, stat_str]) - stat, stat_str = summarize(1, iouThr=.5, maxDets=maxDets) - stats.append([stat, stat_str]) - stat, stat_str = summarize(1, iouThr=.75, maxDets=maxDets) - stats.append([stat, stat_str]) - stat, stat_str = summarize(0, maxDets=maxDets) - stats.append([stat, stat_str]) - return stats - - coco_eval.accumulate() - summarized = summarizeDets() - return summarized - - -def drop_dets(boxes, scores, keep_ratio=0.85): - ids = np.arange(len(boxes)) - np.random.shuffle(ids) - ids_keep = ids[0:int(len(boxes) * keep_ratio)] - boxes_new = boxes[ids_keep, :] - scores_new = scores[ids_keep] - return boxes_new, scores_new - - -def load_FMoD_init_from_dataset(dataset=None, map_type='edgemap', fmod_pyramid_lvl=3, datasets_folder='./datasets', - map_bin=True, verbose=False): - fmod_dir = os.path.join(datasets_folder, dataset, 'FMoD') - if not os.path.exists(fmod_dir): - os.makedirs(fmod_dir, exist_ok=True) - map_type_c = map_type - if map_bin: - map_type_c = map_type_c + '_B' - fmod_filename = dataset + '_' + map_type_c + '_' + str(fmod_pyramid_lvl) + '.pkl' - fmod_filename = fmod_filename.lower() - fmod_stats = None - if not os.path.exists(os.path.join(fmod_dir, fmod_filename)): - file_url = os.path.join(OPENDR_SERVER_URL + 'perception/non-maximum_suppression/FMoD', fmod_filename) + + def set_architecture(self): + if self.variant == 'light': + self.lq_dim = 160 + elif self.variant == 'full': + self.lq_dim = 320 + if self.variant == 'light': + self.sq_dim = 80 + elif self.variant == 'full': + self.sq_dim = 160 + if self.variant == 'light': + self.num_JPUs = 2 + + def sef_fmod_architecture(self): + if self.variant == 'light': + self.fmod_roi_pooling_dim = 120 + if self.variant == 'light': + self.fmod_map_res_dim = 480 + elif self.variant == 'full': + self.fmod_map_res_dim = 800 + if self.variant == 'light': + self.fmod_pyramid_lvl = 2 + + def compute_mask(self, boxes=None, iou_thres=0.2, extra=0.1): + relations = filter_iou_boxes(boxes, iou_thres=iou_thres) + mask1 = torch.tril(relations).float() + mask2 = extra * torch.triu(relations, diagonal=1).float() + mask = mask1 + mask2 + return mask + + def compute_geometrical_feats(self, boxes, scores, resolution): + boxBs = boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1) + boxAs = boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1) + scoresBs = scores.unsqueeze(0).unsqueeze(-1).repeat(scores.shape[0], 1, 1) + scoresAs = scores.unsqueeze(1).unsqueeze(1).repeat(1, scores.shape[0], 1) + + scale_div = [resolution[0] / 20, resolution[1] / 20] + dx = ((boxBs[:, :, 0] - boxAs[:, :, 0] + boxBs[:, :, 2] - boxAs[:, :, 2]) / 2).unsqueeze(-1) + dy = ((boxBs[:, :, 1] - boxAs[:, :, 1] + boxBs[:, :, 3] - boxAs[:, :, 3]) / 2).unsqueeze(-1) + dxy = dx * dx + dy * dy + dxy = dxy / (scale_div[0] * scale_div[0] + scale_div[1] * scale_div[1]) + dx = (dx / scale_div[0]) + dy = (dy / scale_div[1]) + sx = boxBs[:, :, 2] - boxBs[:, :, 0] + sx_1 = (sx / (boxAs[:, :, 2] - boxAs[:, :, 0])).unsqueeze(-1) + sx_2 = (sx / scale_div[0]).unsqueeze(-1) + sy = boxBs[:, :, 3] - boxBs[:, :, 1] + sy_1 = (sy / (boxAs[:, :, 3] - boxAs[:, :, 1])).unsqueeze(-1) + sy_2 = (sy / scale_div[1]).unsqueeze(-1) + scl = (boxBs[:, :, 2] - boxBs[:, :, 0]) * (boxBs[:, :, 3] - boxBs[:, :, 1]) + scl_1 = (scl / ((boxAs[:, :, 2] - boxAs[:, :, 0]) * (boxAs[:, :, 3] - boxAs[:, :, 1]))).unsqueeze(-1) + scl_2 = (scl / (scale_div[0] * scale_div[1])).unsqueeze(-1) + del scl + + scr_1 = 5 * scoresBs + scr_2 = scr_1 - 5 * scoresAs + + sr_1 = torch.unsqueeze((boxBs[:, :, 3] - boxBs[:, :, 1]) / (boxBs[:, :, 2] - boxBs[:, :, 0]), dim=-1) + sr_2 = torch.unsqueeze(((boxBs[:, :, 3] - boxBs[:, :, 1]) / (boxBs[:, :, 2] - boxBs[:, :, 0])) / ( + (boxAs[:, :, 3] - boxAs[:, :, 1]) / (boxAs[:, :, 2] - boxAs[:, :, 0])), dim=-1) + + ious = 5 * (bb_intersection_over_union(boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1), + boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1))).unsqueeze(-1) + enc_vers_all = torch.cat((dx, dy, dxy, sx_1, sx_2, sy_1, sy_2, ious, scl_1, scl_2, scr_1, scr_2, sr_1, sr_2), + dim=2) + enc_vers = enc_vers_all.diagonal(dim1=0, dim2=1).transpose(0, 1).unsqueeze(1) + return enc_vers, enc_vers_all + + def load_FMoD_init_from_dataset(self, dataset=None, map_type='edgemap', fmod_pyramid_lvl=3, + datasets_folder='./datasets', + map_bin=True, verbose=False): + fmod_dir = os.path.join(datasets_folder, dataset, 'FMoD') + if not os.path.exists(fmod_dir): + os.makedirs(fmod_dir, exist_ok=True) + map_type_c = map_type + if map_bin: + map_type_c = map_type_c + '_B' + fmod_filename = dataset + '_' + map_type_c + '_' + str(fmod_pyramid_lvl) + '.pkl' + fmod_filename = fmod_filename.lower() + fmod_stats = None + if not os.path.exists(os.path.join(fmod_dir, fmod_filename)): + file_url = os.path.join(OPENDR_SERVER_URL + 'perception/object_detection_2d/nms/FMoD', fmod_filename) + try: + urlretrieve(file_url, os.path.join(fmod_dir, fmod_filename)) + except: + if verbose: + print( + 'Normalization files not found on FTP server. Normalization will be performed setting \u03BC = ' + '0 and \u03C3 = 1.') + fmod_feats_dim = 0 + for i in range(0, fmod_pyramid_lvl): + fmod_feats_dim = fmod_feats_dim + 15 * (pow(4, i)) + self.fmod_init_file = None + return {'mean': np.zeros(fmod_feats_dim), 'std': np.ones(fmod_feats_dim)} + self.fmod_init_file = os.path.join(fmod_dir, fmod_filename) + fmod_stats = self.load_FMoD_init(self.fmod_init_file) + return fmod_stats + + def load_FMoD_init(self, path=None): try: - urlretrieve(file_url, os.path.join(fmod_dir, fmod_filename)) - except: - if verbose: - print('Normalization files not found on FTP server. Normalization will be performed setting \u03BC = ' - '0 and \u03C3 = 1.') - fmod_feats_dim = 0 - for i in range(0, fmod_pyramid_lvl): - fmod_feats_dim = fmod_feats_dim + 15 * (pow(4, i)) - return {'mean': np.zeros(fmod_feats_dim), 'std': np.ones(fmod_feats_dim)} - fmod_stats = load_FMoD_init(os.path.join(fmod_dir, fmod_filename)) - - return fmod_stats - - -def load_FMoD_init(path=None): - try: - with open(path, 'rb') as fp: - fmod_stats = pickle.load(fp) - map_type = list(fmod_stats.keys())[0] - fmod_stats = fmod_stats[map_type] - except EnvironmentError as e: - e.strerror = 'FMoD initialization .pkl file not found' - raise e - return fmod_stats - - -def compute_class_weights(pos_weights, max_dets=400, dataset_nms=None): - num_pos = np.ones([len(dataset_nms.classes), 1]) - num_bg = np.ones([len(dataset_nms.classes), 1]) - weights = np.zeros([len(dataset_nms.classes), 2]) - for i in range(len(dataset_nms.src_data)): - for cls_index in range(len(dataset_nms.classes)): - num_pos[cls_index] = num_pos[cls_index] + \ - min(max_dets, len(dataset_nms.src_data[i]['gt_boxes'][cls_index])) - num_bg[cls_index] = num_bg[cls_index] + max(0, min(max_dets, - len(dataset_nms.src_data[i]['dt_boxes'][cls_index])) - - min(max_dets, - len(dataset_nms.src_data[i]['gt_boxes'][cls_index]))) - for class_index in range(len(dataset_nms.classes)): - weights[class_index, 0] = (1 - pos_weights[class_index]) * (num_pos[class_index] + - num_bg[class_index]) / num_bg[class_index] - weights[class_index, 1] = pos_weights[class_index] * (num_pos[class_index] + - num_bg[class_index]) / num_pos[class_index] - return weights + with open(path, 'rb') as fp: + fmod_stats = pickle.load(fp) + map_type = list(fmod_stats.keys())[0] + fmod_stats = fmod_stats[map_type] + except EnvironmentError as e: + e.strerror = 'FMoD initialization .pkl file not found' + raise e + return fmod_stats From f623da6a51573619869fb868419e5201a99dbca5 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:35:16 +0200 Subject: [PATCH 067/374] Delete src/opendr/perception/object_detection_2d/nms/seq2seq_nms/datasets/PETS/FMoD directory --- .../datasets/PETS/FMoD/pets_edgemap_b.pkl | Bin 2739 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/datasets/PETS/FMoD/pets_edgemap_b.pkl diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/datasets/PETS/FMoD/pets_edgemap_b.pkl b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/datasets/PETS/FMoD/pets_edgemap_b.pkl deleted file mode 100644 index 22097bf87d9456abf921d9774d9e17b763eaad4c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2739 zcmbuAdoyt`(8y3OW2WRX-BC#DIu}kczNsX2+ri^05X=(~HU1qAIrZvl1=d5%7IPV|tAK&%7&-$*bbW zlzM++1bhX{m8&dmx$C!C2x0_t`7!}s?tudSjKJ`K;3z|npinQvfbbnWKljj3_b35> z>b6iXkD$OXUTC-nPmnF(%f1&1`0|0Ce@U_hHd2X#FQvB&k_GmHxi-?a=F*7*UwOW) zCod}4>)o44-X`NB8|l9Ulljt&z|PLj`tA66f7wX!1l#vm{30VIHPfsG3xcO0U403{ z%APmhsPR~puf2a&iS>N<$M}J$yabn(u5qD61-7vg-vxUPTjhJe*0D& z`$&Rbp#(n%+yZ~-3gS5R818F_t$9&Y*q!U{`#rLi1-e;UH_jT!1ZIr#Xy#mE;K z!T;(42(?1?)Q#dJ^ z;5>-S8wWjA~AxxYOqc96nw|K;jmW=mbNv3 znOcfq$2ydFR%7IT0R-c%$DbU=^Az~X`6|3?QD3Eh=}@)5I#I3qIN42_%Xr((LG&R9 zq}~ss8RN6Ch1pEBvo}uM8-t;90!<&EMMr#2StBEO=CYgXZ(T?|=^|>CKSp~yt104k zAt|)^F@+{E%=A20MsJZTV{%mv-Ud^##`F!XTs%r{!(U)`y%S1ujd5Go5*HWlA$>_O z9ZlU$v7hvp<7PSS&=XR*!Ueh_Iz++Vhl%)kq<%z19gEMB=J8s3q zx$0MB^Ja`Jny=G=qDz$Qe3iEM+#%lSKI+!GNX5PvDB#suGPUZYpN@#>D?Fr)bABY1 z$eZ+bM{e%j5ilCh%*Y!0%L!9FjCu2rpmPavQn`>%7vSE35-7$9 zY4w^TRP9qhArA2*@jFU-CTV14oJL(PNfi93lyuGFDf4OqSsqHDqc3wQ@Q;HOmzG7Q zFXH~@_rLNN_#gQFF`mC3M|*lO%ArY>wlvi1NV;JhdcDqo7z<-k>oBDUkCxFlMxRi6 zw*gtVEutI0uB4qWm(o=m4$T>`p~uO?7&!AB8G|F3KG=z3}oS|2%&e7(+I_m2>NJ~l@ zNoz2V4t|tRs@@04=t&*P?A=T4 Date: Wed, 9 Mar 2022 18:46:10 +0200 Subject: [PATCH 068/374] Update inference_demo.py --- .../nms/seq2seq-nms/inference_demo.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index e54f9abca3..f3b81a79ba 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -2,14 +2,12 @@ from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes -import datetime import os OPENDR_HOME = os.environ['OPENDR_HOME'] -seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, experiment_name='auth_exp51', app_feats = 'fmod', - fmod_init_path=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/' - 'datasets/PETS/FMoD/pets_edgemap_b.pkl', device='cpu') -seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/auth_exp51/' +seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, experiment_name='pets_exp0', + app_feats='fmod', device='cpu') +seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/pets_exp0/' 'checkpoints/checkpoint_epoch_7', verbose=True) ssd = SingleShotDetectorLearner(device='cuda') ssd.download(".", mode="pretrained") @@ -17,5 +15,5 @@ img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg') if not isinstance(img, Image): img = Image(img) -boxes = ssd.infer(img, threshold=0.6, custom_nms=seq2SeqNMSLearner) +boxes = ssd.infer(img, threshold=0.25, custom_nms=seq2SeqNMSLearner) draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) From cf4b4d44554c0e802e05fc76ed3a67b212c128af Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:50:50 +0200 Subject: [PATCH 069/374] Update nms_dataset.py --- .../nms/utils/nms_dataset.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 325a6f9009..38dc8daf93 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -344,14 +344,15 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic ssd.load("./ssd_default_person", verbose=True) if not os.path.exists(os.path.join(self.path, imgs_split)): self.download('http://images.cocodataset.org/zips/' + imgs_split +'.zip', - download_path=os.path.join(self.path), file_format="zip", + download_path=os.path.join(self.path), file_format = "zip", create_dir=True) pkl_filename = os.path.join(self.path, 'data_' + self.detector + '_' + self.dataset_sets[self.split] + '_coco.pkl') if not os.path.exists(pkl_filename): - if not os.path.exists(os.path.join(self.path, 'annotations', 'instances_' + imgs_split +'.json')): - self.download('http://images.cocodataset.org/annotations/annotations_trainval2014.zip', - download_path=os.path.join(self.path), file_format="zip", create_dir=True) - if not os.path.exists(os.path.join(self.path, 'detections', 'coco_2014_' + self.dataset_sets[self.split]+ '_FRCN_train.pkl')): + if not os.path.exists(os.path.join(self.path, 'annotations', 'instances_' + imgs_split + '.json')): + self.download('http://images.cocodataset.org/annotations/annotations_trainval2014.zip', + download_path=os.path.join(self.path), file_format='zip', create_dir=True) + if not os.path.exists(os.path.join(self.path, 'detections', 'coco_2014_' + self.dataset_sets[self.split] + + '_FRCN_train.pkl')): self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/coco_2014_FRCN.tar.gz', download_path=os.path.join(self.path, 'detections'), file_format='tar.gz', create_dir=True) @@ -371,7 +372,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, nms_topk=6000, post_nms=6000) bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) - if bboxes_list.shape[0]>0: + if bboxes_list.shape[0] > 0: bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] if bboxes_list.shape[0] > 0: bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] @@ -379,16 +380,13 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic for b in range(len(bboxes_list)): dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], bboxes_list[b, 3], bboxes_list[b, 4][0]])) - #if len(dt_boxes) > 0: - # dt_boxes[:, 2] = dt_boxes[:, 0] + dt_boxes[:, 2] - # dt_boxes[:, 3] = dt_boxes[:, 1] + dt_boxes[:, 3] dt_boxes = np.asarray(dt_boxes) annots_in_frame = annots.loadAnns(annots.getAnnIds(imgIds=[dets_default[1][i]], iscrowd=False)) gt_boxes = [] for j in range(len(annots_in_frame)): gt_boxes.append(annots_in_frame[j]['bbox']) gt_boxes = np.asarray(np.asarray(gt_boxes)) - if gt_boxes.shape[0]>0: + if gt_boxes.shape[0] > 0: gt_boxes[:, 2] = gt_boxes[:, 0] + gt_boxes[:, 2] gt_boxes[:, 3] = gt_boxes[:, 1] + gt_boxes[:, 3] self.src_data.append({ @@ -407,6 +405,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic self.src_data = pickle.load(fp_pkl) self.classes = ['background', 'person'] self.class_ids = [-1, 1] + @staticmethod def download( url, download_path, dataset_sub_path=".", file_format="zip", create_dir=False): From 9376f42003dc2518262b817145bba445557f8036 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:51:34 +0200 Subject: [PATCH 070/374] Delete Seq2SeqNMSLearner.py --- .../nms/seq2seq_nms/Seq2SeqNMSLearner.py | 844 ------------------ 1 file changed, 844 deletions(-) delete mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/Seq2SeqNMSLearner.py diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/Seq2SeqNMSLearner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/Seq2SeqNMSLearner.py deleted file mode 100644 index 5d72424551..0000000000 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/Seq2SeqNMSLearner.py +++ /dev/null @@ -1,844 +0,0 @@ - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import torch -import torch.nn.functional as F -import pickle -import numpy as np -import torchvision -import os -from opendr.engine.learners import Learner -from opendr.engine.constants import OPENDR_SERVER_URL -from urllib.request import urlretrieve -import torch.nn as nn -from tensorboardX import SummaryWriter -import torch.optim as optim -from tqdm import tqdm -import collections -import json -from pycocotools.coco import COCO -from pycocotools.cocoeval import COCOeval -import sys -from opendr.engine.target import BoundingBox, BoundingBoxList -from opendr.engine.data import Image -from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet -from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.fmod import FMoD -from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.dataset import Dataset_NMS - - -class Seq2SeqNMSLearner(Learner): - def __init__(self, lr=0.0001, lr_schedule='', checkpoint_after_iter=1, checkpoint_load_iter=0, - experiment_name='default', temp_path='temp', device='cuda', use_fmod=True, - fmod_map_type='EDGEMAP_B', fmod_map_bin=True, dropout=0.02, fmod_roi_pooling_dim=160, - fmod_map_res_dim=800, fmod_pyramid_lvl=3, lq_dim=256, sq_dim=128, app_input_dim=None, - num_JPUs=4, pretrained_demo_model=None, log_after=500, iou_filtering=None, fmod_init_path=None): - super(Seq2SeqNMSLearner, self).__init__(lr=lr, batch_size=1, lr_schedule=lr_schedule, - checkpoint_after_iter=checkpoint_after_iter, - checkpoint_load_iter=checkpoint_load_iter, - temp_path=temp_path, device=device, backbone='default') - self.use_fmod = use_fmod - if self.use_fmod: - self.fmod_normalization = None - self.fmod_map_type = fmod_map_type - self.fmod_roi_pooling_dim = [fmod_roi_pooling_dim, fmod_roi_pooling_dim] - self.fmod_map_res_dim = fmod_map_res_dim - self.fmod_pyramid_lvl = fmod_pyramid_lvl - self.fmod_feats_dim = 0 - for i in range(0, self.fmod_pyramid_lvl): - self.fmod_feats_dim = self.fmod_feats_dim + 15 * (pow(4, i)) - self.fmod_map_bin = fmod_map_bin - self.app_input_dim = self.fmod_feats_dim - else: - if app_input_dim is None: - raise Exception("The dimension of the input appearance-based features is not provided...") - else: - self.app_input_dim = app_input_dim - self.geom_input_dim = 14 - self.lq_dim = lq_dim - self.sq_dim = sq_dim - self.dropout = dropout - self.num_JPUs = num_JPUs - self.parent_dir = temp_path - if not os.path.isdir(self.parent_dir): - os.mkdir(self.parent_dir) - self.experiment_name = experiment_name - if not os.path.isdir(os.path.join(self.parent_dir, self.experiment_name)): - os.mkdir(os.path.join(self.parent_dir, self.experiment_name)) - self.pretrained_demo_model = pretrained_demo_model - self.checkpoint_load_iter = checkpoint_load_iter - self.log_after = log_after - self.iou_filtering = iou_filtering - self.classes = None - self.class_ids = None - self.device = device - self.fMoD = None - if self.use_fmod: - self.fMoD = FMoD(roi_pooling_dim=self.fmod_roi_pooling_dim, pyramid_depth=self.fmod_pyramid_lvl, - resize_dim=self.fmod_map_res_dim, - map_type=self.fmod_map_type, map_bin=self.fmod_map_bin, device=self.device) - if fmod_init_path is not None: - fmod_mean_std = load_FMoD_init(fmod_init_path) - self.fMoD.set_mean_std(mean_values=fmod_mean_std['mean'], std_values=fmod_mean_std['std']) - - def fit(self, dataset, val_dataset=None, epochs=None, logging_path='', logging_flush_secs=30, silent=True, - verbose=True, nms_gt_iou=0.5, boxes_sorted=False, max_dt_boxes=400): - - datasets_folder = './datasets' - dataset_nms = Dataset_NMS(datasets_folder, dataset, split='train') - if self.classes is None: - self.classes = dataset_nms.classes - self.class_ids = dataset_nms.class_ids - - if logging_path != '' and logging_path is not None: - logging = True - file_writer = SummaryWriter(logging_path, flush_secs=logging_flush_secs) - else: - logging = False - file_writer = None - - if self.model is None: - self.init_model() - checkpoints_folder = os.path.join(self.parent_dir, self.experiment_name, 'checkpoints') - if self.checkpoint_after_iter != 0 and not os.path.exists(checkpoints_folder): - os.makedirs(checkpoints_folder) - - if self.pretrained_demo_model is not None: - self.download(mode="weights", verbose=verbose and not silent) - weights_path = None - if self.pretrained_demo_model == 'PETS': - weights_path = os.path.join(self.parent_dir, "seq2seq_pets.pth.tar") - self.checkpoint_load_iter = '?' - elif self.pretrained_demo_model == 'COCO': - weights_path = os.path.join(self.parent_dir, "seq2seq_coco.pth.tar") - self.checkpoint_load_iter = '?' - elif self.pretrained_demo_model == 'CrownHuman': - weights_path = os.path.join(self.parent_dir, "seq2seq_crowdhuman.pth.tar") - self.checkpoint_load_iter = '?' - self.load(path=weights_path, verbose=verbose) - elif self.checkpoint_load_iter != 0: - checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) - checkpoint_full_path = os.path.join(checkpoints_folder, checkpoint_name) - self.load(checkpoint_full_path) - - if not silent and verbose: - print("Model trainable parameters:", self.count_parameters()) - - self.model.train() - if self.device == 'cuda': - self.model = self.model.cuda() - - if epochs is None: - raise ValueError("Training epochs not specified") - elif epochs <= self.checkpoint_load_iter: - raise ValueError("Training epochs are less than those of the loaded model") - - if self.use_fmod: - fmod_mean_std = load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, - map_bin=self.fmod_map_bin, datasets_folder=datasets_folder) - self.fMoD.set_mean_std(mean_values=fmod_mean_std['mean'], std_values=fmod_mean_std['std']) - - start_epoch = 0 - drop_after_epoch = [4, 7] - - train_ids = np.arange(len(dataset_nms.src_data)) - total_loss_iter = 0 - total_loss_epoch = 0 - optimizer = optim.Adam(self.model.parameters(), lr=self.lr, betas=(0.9, 0.99), eps=1e-9) # HERE - scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=drop_after_epoch, gamma=0.1) - - if self.checkpoint_load_iter != 0: - checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) - checkpoint_full_path = os.path.join(checkpoints_folder, checkpoint_name) - self.load(checkpoint_full_path) - - num_iter = 0 - training_weights = compute_class_weights(pos_weights=[0.5, 0.1], max_dets=max_dt_boxes, dataset_nms=dataset_nms) - - for epoch in range(start_epoch, epochs): - pbar = None - if not silent: - pbarDesc = "Epoch #" + str(epoch) + " progress" - pbar = tqdm(desc=pbarDesc, total=len(train_ids)) - np.random.shuffle(train_ids) - for sample_id in train_ids: - image_fln = dataset_nms.src_data[sample_id]['filename'] - loss = 0 - for class_index in range(len(dataset_nms.classes)): - if len(dataset_nms.src_data[sample_id]['dt_boxes'][class_index]) > 0: - dt_boxes = torch.tensor( - dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 0:4]).float() - dt_scores = torch.tensor(dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 4]).float() - if not boxes_sorted: - dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) - dt_boxes = dt_boxes[dt_scores_ids] - else: - continue - gt_boxes = torch.tensor([]).float() - if len(dataset_nms.src_data[sample_id]['gt_boxes'][class_index]) > 0: - gt_boxes = torch.tensor(dataset_nms.src_data[sample_id]['gt_boxes'][class_index]).float() - image_path = os.path.join(datasets_folder, dataset, 'images', image_fln) - img_res = dataset_nms.src_data[sample_id]['resolution'][::-1] - - if self.device == "cuda": - dt_boxes = dt_boxes.cuda() - dt_scores = dt_scores.cuda() - gt_boxes = gt_boxes.cuda() - - val_ids = torch.logical_and((dt_boxes[:, 2] - dt_boxes[:, 0]) > 4, - (dt_boxes[:, 3] - dt_boxes[:, 1]) > 4) - dt_boxes = dt_boxes[val_ids, :] - dt_scores = dt_scores[val_ids] - - dt_boxes, dt_scores = drop_dets(dt_boxes, dt_scores) - if self.iou_filtering is not None and 1.0 > self.iou_filtering > 0: - dt_boxes, dt_scores = apply_torchNMS(boxes=dt_boxes, scores=dt_scores, - iou_thres=self.iou_filtering) - - dt_boxes = dt_boxes[:max_dt_boxes] - dt_scores = dt_scores[:max_dt_boxes] - fmod_feats = None - if self.use_fmod: - img = Image.open(image_path) - img = img.convert(format='channels_last', channel_order='bgr') - self.fMoD.extract_maps(img=img, augm=True) - fmod_feats = self.fMoD.extract_FMoD_feats(dt_boxes) - fmod_feats = torch.unsqueeze(fmod_feats, dim=1) - msk = compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) - q_geom_feats, k_geom_feats = compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, - resolution=img_res) - - optimizer.zero_grad() - preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, - fmod_feats=fmod_feats) - preds = torch.clamp(preds, 0.001, 1 - 0.001) - labels = matching_module(scores=preds, dt_boxes=dt_boxes, gt_boxes=gt_boxes, - iou_thres=nms_gt_iou) - - # weights = (2.92 * labels + 0.932 * (1 - labels)).cuda() - weights = (training_weights[class_index][1] * labels + training_weights[class_index][0] * ( - 1 - labels)).cuda() - - e = torch.distributions.uniform.Uniform(0.02, 0.0205).sample([labels.shape[0], 1]) - if self.device == 'cuda': - e = e.cuda() - labels = labels * (1 - e) + (1 - labels) * e - ce_loss = F.binary_cross_entropy(preds, labels, reduction="none") - loss = loss + (ce_loss * weights).sum() - total_loss_iter = total_loss_iter + loss - total_loss_epoch = total_loss_epoch + loss - loss.backward() - optimizer.step() - num_iter = num_iter + 1 - if self.log_after != 0 and num_iter % self.log_after == 0: - if logging: - file_writer.add_scalar(tag="cross entropy loss", - scalar_value=total_loss_iter / self.log_after, - global_step=num_iter) - if verbose: - print(''.join(['\nEpoch: {}', - ' Iter: {}, cross entropy loss: {}']).format(epoch, num_iter, - total_loss_iter / self.log_after)) - total_loss_iter = 0 - if not silent: - pbar.update(1) - if not silent: - pbar.close() - if verbose: - print(''.join(['Epoch: {}', - ' cross entropy loss: {}\n']).format(epoch, - total_loss_epoch / len(train_ids))) - if self.checkpoint_after_iter != 0 and epoch % self.checkpoint_after_iter == self.checkpoint_after_iter - 1: - snapshot_name = '{}/checkpoint_epoch_{}'.format(checkpoints_folder, epoch) - # Save checkpoint with full information for training state - self.save(path=snapshot_name, optimizer=optimizer, scheduler=scheduler, - current_epoch=epoch, max_dt_boxes=max_dt_boxes) - total_loss_epoch = 0 - scheduler.step() - if logging: - file_writer.close() - # if not silent and verbose: - # print("Model trainable parameters:", self.count_parameters()) - - def eval(self, dataset, verbose=True, split='test', boxes_sorted=False, max_dt_boxes=400, eval_folder=None): - - # Load dataset - datasets_folder = './datasets' - dataset_nms = Dataset_NMS(datasets_folder, dataset, split) - - if self.classes is None: - self.classes = dataset_nms.classes - self.class_ids = dataset_nms.class_ids - - annotations_filename = str.lower(dataset) + '_' + split + '.json' - - if eval_folder is None: - eval_folder = os.path.join(self.parent_dir, self.experiment_name, 'eval') - if not os.path.isdir(eval_folder): - os.mkdir(eval_folder) - output_file = os.path.join(eval_folder, 'detections.json') - - # Model initialization if needed - if self.model is None and self.checkpoint_load_iter != 0: - # No model loaded, initializing new - self.init_model() - checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) - checkpoint_folder = os.path.join(self.parent_dir, self.experiment_name, 'checkpoints') - checkpoint_full_path = os.path.join(checkpoint_folder, checkpoint_name) - self.load(path=checkpoint_full_path, verbose=verbose) - - elif self.model is None: - raise AttributeError("self.model is None. Please load a model or set checkpoint_load_iter.") - - if self.use_fmod and (self.fMoD.mean is None or self.fMoD.std is None): - fmod_mean_std = load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, - datasets_folder=datasets_folder) - self.fMoD.set_mean_std(mean_values=fmod_mean_std['mean'], std_values=fmod_mean_std['std']) - - self.model = self.model.eval() # Change model state to evaluation - if self.device == "cuda": - self.model = self.model.cuda() - - # Change model state to evaluation - self.model = self.model.eval() - if self.device == "cuda": - self.model = self.model.cuda() - - train_ids = np.arange(len(dataset_nms.src_data)) - nms_results = [] - pbar_eval = None - if verbose: - pbarDesc = "Evaluation progress" - pbar_eval = tqdm(desc=pbarDesc, total=len(train_ids)) - for sample_id in train_ids: - image_fln = dataset_nms.src_data[sample_id]['filename'] - - image_path = os.path.join(datasets_folder, dataset, 'images', image_fln) - img_res = dataset_nms.src_data[sample_id]['resolution'][::-1] - - for class_index in range(len(dataset_nms.classes)): - if len(dataset_nms.src_data[sample_id]['dt_boxes'][class_index]) > 0: - dt_boxes = torch.tensor(dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 0:4]).float() - dt_scores = torch.tensor(dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 4]).float() - if not boxes_sorted: - dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) - dt_boxes = dt_boxes[dt_scores_ids] - else: - continue - - if self.device == "cuda": - dt_boxes = dt_boxes.cuda() - dt_scores = dt_scores.cuda() - - val_ids = torch.logical_and((dt_boxes[:, 2] - dt_boxes[:, 0]) > 4, - (dt_boxes[:, 3] - dt_boxes[:, 1]) > 4) - dt_boxes = dt_boxes[val_ids, :] - dt_scores = dt_scores[val_ids] - - if self.iou_filtering is not None and 1.0 > self.iou_filtering > 0: - dt_boxes, dt_scores = apply_torchNMS(boxes=dt_boxes, scores=dt_scores, iou_thres=self.iou_filtering) - - dt_boxes = dt_boxes[:max_dt_boxes] - dt_scores = dt_scores[:max_dt_boxes] - fmod_feats = None - if self.use_fmod: - img = Image.open(image_path) - img = img.convert(format='channels_last', channel_order='bgr') - self.fMoD.extract_maps(img, augm=False) - fmod_feats = self.fMoD.extract_FMoD_feats(dt_boxes) - fmod_feats = torch.unsqueeze(fmod_feats, dim=1) - msk = compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) - q_geom_feats, k_geom_feats = compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, - resolution=img_res) - with torch.no_grad(): - preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, - fmod_feats=fmod_feats).cpu().detach().numpy() - bboxes = dt_boxes.cpu().numpy().astype('float64') - for j in range(len(preds)): - nms_results.append({ - 'image_id': dataset_nms.src_data[sample_id]['id'], - 'bbox': [bboxes[j][0], bboxes[j][1], bboxes[j][2] - bboxes[j][0], bboxes[j][3] - bboxes[j][1]], - 'category_id': dataset_nms.class_ids[dataset_nms.classes[class_index]], - 'score': np.float64(preds[j]) - }) - pbar_eval.update(1) - pbar_eval.close() - if verbose: - print('Writing results json to {}'.format(output_file)) - with open(output_file, 'w') as fid: - json.dump(nms_results, fid, indent=2) - eval_result = run_coco_eval(gt_file_path=os.path.join(dataset_nms.path, 'annotations', annotations_filename), - dt_file_path=output_file, only_classes=[1], - verbose=verbose, max_dets=[max_dt_boxes]) - for i in range(len(eval_result)): - print('Evaluation results (num_dets={})'.format(str(eval_result[i][1]))) - print(eval_result[i][0][0][1]) - print(eval_result[i][0][1][1]) - print(eval_result[i][0][2][1]) - print(eval_result[i][0][3][1]) - print('\n') - - def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoch=None, max_dt_boxes=800): - """ - Method for saving the current model in the path provided - :param path: path for the model to be saved - :type path: str - :param verbose: whether to print a success message or not, defaults to False - :type verbose: bool, optional - :param optimizer: the optimizer used for training - :type optimizer: Optimizer PyTorch object - :param scheduler: the scheduler used for training - :type scheduler: Scheduler PyTorch object - :param current_epoch: the current epoch id - :type current_epoch: int - """ - path = path.split('.')[0] - custom_dict = {'state_dict': self.model.state_dict(), 'optimizer': optimizer.state_dict(), - 'scheduler': scheduler.state_dict(), 'current_epoch': current_epoch} - torch.save(custom_dict, path + '.pth') - - metadata = {"model_paths": [os.path.basename(path) + '.pth'], "framework": "pytorch", "has_data": False, - "inference_params": {}, "optimized": False, "optimizer_info": {}, "backbone": {}, - "format": "pth", "classes": self.classes, "use_fmod": self.use_fmod, - "lq_dim": self.lq_dim, "sq_dim": self.sq_dim, "num_JPUs": self.num_JPUs, - "geom_input_dim": self.geom_input_dim, "app_input_dim": self.app_input_dim, - "max_dt_boxes": max_dt_boxes} - if self.use_fmod: - metadata["fmod_map_type"] = self.fmod_map_type - metadata["fmod_map_bin"] = self.fmod_map_bin - metadata["fmod_roi_pooling_dim"] = self.fmod_roi_pooling_dim - metadata["fmod_map_res_dim"] = self.fmod_map_res_dim - metadata["fmod_pyramid_lvl"] = self.fmod_pyramid_lvl - - with open(path + '.json', 'w', encoding='utf-8') as f: - json.dump(metadata, f, ensure_ascii=False, indent=4) - if verbose: - print("Saved Pytorch model.") - - def init_model(self): - if self.model is None: - self.model = Seq2SeqNet(dropout=self.dropout, use_fmod=self.use_fmod, app_input_dim=self.app_input_dim, - geom_input_dim=self.geom_input_dim, lq_dim=self.lq_dim, sq_dim=self.sq_dim, - num_JPUs=self.num_JPUs) - for p in self.model.parameters(): - if p.dim() > 1: - nn.init.xavier_uniform_(p) - else: - raise UserWarning("Tried to initialize model while model is already initialized.") - - def load(self, path, verbose=False): - """ - Loads the model from inside the path provided, based on the metadata .json file included - :param path: path of the checkpoint file was saved - :type path: str - :param verbose: whether to print success message or not, defaults to 'False' - :type verbose: bool, optional - """ - model_name = os.path.basename(os.path.normpath(path)).split('.')[0] - dir_path = os.path.dirname(os.path.normpath(path)) - - if verbose: - print("Model name:", model_name, "-->", os.path.join(dir_path, model_name + ".json")) - with open(os.path.join(dir_path, model_name + ".json")) as f: - metadata = json.load(f) - pth_path = os.path.join(dir_path, metadata["model_paths"][0]) - if verbose: - print("Loading checkpoint:", pth_path) - try: - checkpoint = torch.load(pth_path, map_location=torch.device(self.device)) - except FileNotFoundError as e: - e.strerror = "File " + pth_path + "not found." - raise e - - self.assign_params(metadata=metadata, verbose=verbose) - self.init_model() - self.load_state(checkpoint) - if self.device == 'cuda': - self.model = self.model.cuda() - if verbose: - print("Loaded parameters and metadata.") - return True - - def assign_params(self, metadata, verbose): - - if verbose and self.geom_input_dim is not None and self.geom_input_dim != metadata["geom_input_dim"]: - print("Incompatible value for the attribute \"geom_input_dim\". It is now set to: " + - str(metadata["geom_input_dim"])) - self.geom_input_dim = metadata["geom_input_dim"] - if verbose and self.app_input_dim is not None and self.app_input_dim != metadata["app_input_dim"]: - print("Incompatible value for the attribute \"app_input_dim\". It is now set to: " + - str(metadata["app_input_dim"])) - self.app_input_dim = metadata["app_input_dim"] - if verbose and self.use_fmod is not None and self.use_fmod != metadata["use_fmod"]: - print("Incompatible value for the attribute \"use_fmod\". It is now set to: " + - str(metadata["use_fmod"])) - self.use_fmod = metadata["use_fmod"] - if verbose and self.fmod_map_type is not None and self.fmod_map_type != metadata["fmod_map_type"]: - print("Incompatible value for the attribute \"fmod_map_type\". It is now set to: " + - str(metadata["fmod_map_type"])) - self.fmod_map_type = metadata["fmod_map_type"] - if verbose and self.fmod_map_bin is not None and self.fmod_map_bin != metadata["fmod_map_bin"]: - print("Incompatible value for the attribute \"fmod_map_bin\". It is now set to: " + - str(metadata["fmod_map_bin"])) - self.fmod_map_bin = metadata["fmod_map_bin"] - if verbose and self.fmod_roi_pooling_dim is not None and \ - self.fmod_roi_pooling_dim != metadata["fmod_roi_pooling_dim"]: - print("Incompatible value for the attribute \"fmod_roi_pooling_dim\". It is now set to: " + - str(metadata["fmod_roi_pooling_dim"])) - self.fmod_roi_pooling_dim = metadata["fmod_roi_pooling_dim"] - if verbose and self.fmod_map_res_dim is not None and \ - self.fmod_map_res_dim != metadata["fmod_map_res_dim"]: - print("Incompatible value for the attribute \"fmod_map_res_dim\". It is now set to: " + - str(metadata["fmod_map_res_dim"])) - self.fmod_map_res_dim = metadata["fmod_map_res_dim"] - if verbose and self.fmod_pyramid_lvl is not None and \ - self.fmod_pyramid_lvl != metadata["fmod_pyramid_lvl"]: - print("Incompatible value for the attribute \"fmod_pyramid_lvl\". It is now set to: " + - str(metadata["fmod_pyramid_lvl"])) - self.fmod_pyramid_lvl = metadata["fmod_pyramid_lvl"] - if verbose and self.lq_dim is not None and \ - self.lq_dim != metadata["lq_dim"]: - print("Incompatible value for the attribute \"lq_dim\". It is now set to: " + - str(metadata["lq_dim"])) - self.lq_dim = metadata["lq_dim"] - if verbose and self.sq_dim is not None and self.sq_dim != metadata["sq_dim"]: - print("Incompatible value for the attribute \"sq_dim\". It is now set to: " + - str(metadata["sq_dim"])) - self.sq_dim = metadata["sq_dim"] - if verbose and self.num_JPUs is not None and self.num_JPUs != metadata["num_JPUs"]: - print("Incompatible value for the attribute \"num_JPUs\". It is now set to: " + - str(metadata["num_JPUs"])) - self.num_JPUs = metadata["num_JPUs"] - if verbose and 'max_dt_boxes' in metadata: - print('Model is trained with as ' + str(metadata['max_dt_boxes']) + 'its maximum number of detections.') - - def load_state(self, checkpoint=None): - if checkpoint is None: - for p in self.model.parameters(): - if p.dim() > 1: - nn.init.xavier_uniform_(p) - else: - try: - source_state = checkpoint['state_dict'] - except KeyError: - source_state = checkpoint - target_state = self.model.state_dict() - new_target_state = collections.OrderedDict() - for target_key, target_value in target_state.items(): - if target_key in source_state and source_state[target_key].size() == target_state[target_key].size(): - new_target_state[target_key] = source_state[target_key] - else: - new_target_state[target_key] = target_state[target_key] - # print('[WARNING] Not found pre-trained parameters for {}'.format(target_key)) - - self.model.load_state_dict(new_target_state) - - def count_parameters(self): - """ - Returns the number of the model's trainable parameters. - :return: number of trainable parameters - :rtype: int - """ - if self.model is None: - raise UserWarning("Model is not initialized, can't count trainable parameters.") - return sum(p.numel() for p in self.model.parameters() if p.requires_grad) - - def download(self, path=None, mode="pretrained", verbose=False, - url=OPENDR_SERVER_URL + "perception/pose_estimation/lightweight_open_pose/"): - print('ToDo') - - def infer(self, classes=None, dets=None, boxes_sorted=False, max_dt_boxes=1200, img_res=None, threshold=0.1): - - for class_index in range(len(classes)): - if len(dets[class_index]) > 0: - dt_boxes = dets[class_index][:, 0:4] - dt_scores = dets[class_index][:, 4] - if not boxes_sorted: - dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) - dt_boxes = dt_boxes[dt_scores_ids] - else: - continue - - if self.device == "cuda": - dt_boxes = dt_boxes.cuda() - dt_scores = dt_scores.cuda() - - val_ids = torch.logical_and((dt_boxes[:, 2] - dt_boxes[:, 0]) > 4, - (dt_boxes[:, 3] - dt_boxes[:, 1]) > 4) - dt_boxes = dt_boxes[val_ids, :] - dt_scores = dt_scores[val_ids] - - if self.iou_filtering is not None and 1.0 > self.iou_filtering > 0: - dt_boxes, dt_scores = apply_torchNMS(boxes=dt_boxes, scores=dt_scores, iou_thres=self.iou_filtering) - - dt_boxes = dt_boxes[:max_dt_boxes] - dt_scores = dt_scores[:max_dt_boxes] - fmod_feats = None - if self.use_fmod: - fmod_feats = self.fMoD.extract_FMoD_feats(dt_boxes) - fmod_feats = torch.unsqueeze(fmod_feats, dim=1) - msk = compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) - q_geom_feats, k_geom_feats = compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, - resolution=img_res) - with torch.no_grad(): - preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, - fmod_feats=fmod_feats).cpu().detach().numpy() - bboxes = dt_boxes.cpu().numpy().astype('float64') - - mask = np.where(preds > threshold)[0] - if mask.size == 0: - return BoundingBoxList([]) - preds = preds[mask] - bboxes = bboxes[mask, :] - - bounding_boxes = BoundingBoxList([]) - for idx, box in enumerate(bboxes): - bbox = BoundingBox(left=box[0], top=box[1], - width=box[2] - box[0], - height=box[3] - box[1], - name=class_index, - score=preds[idx]) - bounding_boxes.data.append(bbox) - return bounding_boxes - - def optimize(self, **kwargs): - """This method is not used in this implementation.""" - raise NotImplementedError - - def reset(self): - """This method is not used in this implementation.""" - return NotImplementedError - - -def apply_torchNMS(boxes, scores, iou_thres): - ids_nms = torchvision.ops.nms(boxes, scores, iou_thres) - scores = scores[ids_nms] - boxes = boxes[ids_nms] - return boxes, scores - - -def compute_mask(boxes=None, iou_thres=0.2, extra=0.1): - relations = filter_iou_boxes(boxes, iou_thres=iou_thres) - mask1 = torch.tril(relations).float() - mask2 = extra * torch.triu(relations, diagonal=1).float() - mask = mask1 + mask2 - return mask - - -def filter_iou_boxes(boxes=None, iou_thres=0.2): - ious = bb_intersection_over_union(boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1), - boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1)) - ids_boxes = ious >= iou_thres - return ids_boxes - - -def bb_intersection_over_union(boxAs=None, boxBs=None): - xA = torch.maximum(boxAs[:, :, 0], boxBs[:, :, 0]) - yA = torch.maximum(boxAs[:, :, 1], boxBs[:, :, 1]) - xB = torch.minimum(boxAs[:, :, 2], boxBs[:, :, 2]) - yB = torch.minimum(boxAs[:, :, 3], boxBs[:, :, 3]) - interAreas = torch.maximum(torch.zeros_like(xB), xB - xA + 1) * torch.maximum(torch.zeros_like(yB), yB - yA + 1) - boxAAreas = (boxAs[:, :, 2] - boxAs[:, :, 0] + 1) * (boxAs[:, :, 3] - boxAs[:, :, 1] + 1) - boxBAreas = (boxBs[:, :, 2] - boxBs[:, :, 0] + 1) * (boxBs[:, :, 3] - boxBs[:, :, 1] + 1) - ious = interAreas / (boxAAreas + boxBAreas - interAreas) - return ious - - -def compute_geometrical_feats(boxes, scores, resolution): - boxBs = boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1) - boxAs = boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1) - scoresBs = scores.unsqueeze(0).unsqueeze(-1).repeat(scores.shape[0], 1, 1) - scoresAs = scores.unsqueeze(1).unsqueeze(1).repeat(1, scores.shape[0], 1) - - scale_div = [resolution[0] / 20, resolution[1] / 20] - dx = ((boxBs[:, :, 0] - boxAs[:, :, 0] + boxBs[:, :, 2] - boxAs[:, :, 2]) / 2).unsqueeze(-1) - dy = ((boxBs[:, :, 1] - boxAs[:, :, 1] + boxBs[:, :, 3] - boxAs[:, :, 3]) / 2).unsqueeze(-1) - dxy = dx * dx + dy * dy - dxy = dxy / (scale_div[0] * scale_div[0] + scale_div[1] * scale_div[1]) - dx = (dx / scale_div[0]) - dy = (dy / scale_div[1]) - sx = boxBs[:, :, 2] - boxBs[:, :, 0] - sx_1 = (sx / (boxAs[:, :, 2] - boxAs[:, :, 0])).unsqueeze(-1) - sx_2 = (sx / scale_div[0]).unsqueeze(-1) - sy = boxBs[:, :, 3] - boxBs[:, :, 1] - sy_1 = (sy / (boxAs[:, :, 3] - boxAs[:, :, 1])).unsqueeze(-1) - sy_2 = (sy / scale_div[1]).unsqueeze(-1) - scl = (boxBs[:, :, 2] - boxBs[:, :, 0]) * (boxBs[:, :, 3] - boxBs[:, :, 1]) - scl_1 = (scl / ((boxAs[:, :, 2] - boxAs[:, :, 0]) * (boxAs[:, :, 3] - boxAs[:, :, 1]))).unsqueeze(-1) - scl_2 = (scl / (scale_div[0] * scale_div[1])).unsqueeze(-1) - del scl - - scr_1 = 5 * scoresBs - scr_2 = scr_1 - 5 * scoresAs - - sr_1 = torch.unsqueeze((boxBs[:, :, 3] - boxBs[:, :, 1]) / (boxBs[:, :, 2] - boxBs[:, :, 0]), dim=-1) - sr_2 = torch.unsqueeze(((boxBs[:, :, 3] - boxBs[:, :, 1]) / (boxBs[:, :, 2] - boxBs[:, :, 0])) / ( - (boxAs[:, :, 3] - boxAs[:, :, 1]) / (boxAs[:, :, 2] - boxAs[:, :, 0])), dim=-1) - - ious = 5 * (bb_intersection_over_union(boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1), - boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1))).unsqueeze(-1) - enc_vers_all = torch.cat((dx, dy, dxy, sx_1, sx_2, sy_1, sy_2, ious, scl_1, scl_2, scr_1, scr_2, sr_1, sr_2), dim=2) - enc_vers = enc_vers_all.diagonal(dim1=0, dim2=1).transpose(0, 1).unsqueeze(1) - return enc_vers, enc_vers_all - - -def matching_module(scores, dt_boxes, gt_boxes, iou_thres, device='cuda'): - sorted_indices = torch.argsort(-scores, dim=0) - labels = torch.zeros(len(dt_boxes)) - assigned_GT = -torch.ones(len(gt_boxes)) - r = torch.tensor([-1, -1, -1, -1]).float().unsqueeze(0).unsqueeze(0) - if device == 'cuda': - r = r.cuda() - labels = labels.cuda() - for s in sorted_indices: - gt_boxes_c = gt_boxes.clone().unsqueeze(0) - gt_boxes_c[0, assigned_GT > -1, :] = r - ious = bb_intersection_over_union(boxAs=dt_boxes[s].clone().unsqueeze(0), boxBs=gt_boxes_c) - annot_iou, annot_box_id = torch.sort(ious.squeeze(), descending=True) - if annot_box_id.ndim > 0: - annot_box_id = annot_box_id[0] - annot_iou = annot_iou[0] - if annot_iou > iou_thres: - assigned_GT[annot_box_id] = s - labels[s] = 1 - return labels.unsqueeze(-1) - - -def run_coco_eval(dt_file_path=None, gt_file_path=None, only_classes=None, max_dets=None, - verbose=False): - if max_dets is None: - max_dets = [200, 400, 600, 800, 1000, 1200] - results = [] - sys.stdout = open(os.devnull, 'w') - for i in range(len(max_dets)): - coco = COCO(gt_file_path) - coco_dt = coco.loadRes(dt_file_path) - cocoEval = COCOeval(coco, coco_dt, 'bbox') - cocoEval.params.iouType = 'bbox' - cocoEval.params.useCats = True - cocoEval.params.catIds = only_classes - cocoEval.params.maxDets = [max_dets[i]] - cocoEval.evaluate() - results.append([summarize_nms(coco_eval=cocoEval, maxDets=max_dets[i]), max_dets[i]]) - # print(results[i]) - del cocoEval, coco_dt, coco - sys.stdout = sys.__stdout__ - return results - - -def summarize_nms(coco_eval=None, maxDets=100): - def summarize(ap=1, iouThr=None, areaRng='all', maxDets=100): - p = coco_eval.params - iStr = ' {:<18} {} @[ IoU={:<9} | area={:>6s} | maxDets={:>3d} ] = {:0.3f}' - titleStr = 'Average Precision' if ap == 1 else 'Average Recall' - typeStr = '(AP)' if ap == 1 else '(AR)' - iouStr = '{:0.2f}:{:0.2f}'.format(p.iouThrs[0], p.iouThrs[-1]) \ - if iouThr is None else '{:0.2f}'.format(iouThr) - aind = [i for i, aRng in enumerate(p.areaRngLbl) if aRng == areaRng] - mind = [i for i, mDet in enumerate(p.maxDets) if mDet == maxDets] - if ap == 1: - # dimension of precision: [TxRxKxAxM] - s = coco_eval.eval['precision'] - # IoU - if iouThr is not None: - t = np.where(iouThr == p.iouThrs)[0] - s = s[t] - s = s[:, :, :, aind, mind] - else: - # dimension of recall: [TxKxAxM] - s = coco_eval.eval['recall'] - if iouThr is not None: - t = np.where(iouThr == p.iouThrs)[0] - s = s[t] - s = s[:, :, aind, mind] - if len(s[s > -1]) == 0: - mean_s = -1 - else: - mean_s = np.mean(s[s > -1]) - stat_str = iStr.format(titleStr, typeStr, iouStr, areaRng, maxDets, mean_s) - return [mean_s, stat_str] - - def summarizeDets(): - stats = [] - stat, stat_str = summarize(1, maxDets=maxDets) - stats.append([stat, stat_str]) - stat, stat_str = summarize(1, iouThr=.5, maxDets=maxDets) - stats.append([stat, stat_str]) - stat, stat_str = summarize(1, iouThr=.75, maxDets=maxDets) - stats.append([stat, stat_str]) - stat, stat_str = summarize(0, maxDets=maxDets) - stats.append([stat, stat_str]) - return stats - - coco_eval.accumulate() - summarized = summarizeDets() - return summarized - - -def drop_dets(boxes, scores, keep_ratio=0.85): - ids = np.arange(len(boxes)) - np.random.shuffle(ids) - ids_keep = ids[0:int(len(boxes) * keep_ratio)] - boxes_new = boxes[ids_keep, :] - scores_new = scores[ids_keep] - return boxes_new, scores_new - - -def load_FMoD_init_from_dataset(dataset=None, map_type='edgemap', datasets_folder='./datasets', map_bin=True): - fmod_dir = os.path.join(datasets_folder, dataset, 'FMoD') - if not os.path.exists(fmod_dir): - os.makedirs(fmod_dir, exist_ok=True) - map_type_c = map_type - if map_bin: - map_type_c = map_type_c + '_B' - fmod_filename = dataset + '_' + map_type_c + '.pkl' - fmod_filename = fmod_filename.lower() - if not os.path.exists(os.path.join(fmod_dir, fmod_filename)): - file_url = os.path.join(OPENDR_SERVER_URL + 'perception/non-maximum_suppression/FMoD', fmod_filename) - try: - urlretrieve(file_url, os.path.join(fmod_dir, fmod_filename)) - except Exception as e: - raise e - fmod_stats = load_FMoD_init(os.path.join(fmod_dir, fmod_filename)) - return fmod_stats - - -def load_FMoD_init(path=None): - try: - with open(path, 'rb') as fp: - fmod_stats = pickle.load(fp) - map_type = list(fmod_stats.keys())[0] - fmod_stats = fmod_stats[map_type] - except EnvironmentError as e: - e.strerror = 'FMoD initialization .pkl file not found' - raise e - return fmod_stats - - -def compute_class_weights(pos_weights, max_dets=400, dataset_nms=None): - num_pos = np.ones([len(dataset_nms.classes), 1]) - num_bg = np.ones([len(dataset_nms.classes), 1]) - weights = np.zeros([len(dataset_nms.classes), 2]) - for i in range(len(dataset_nms.src_data)): - for cls_index in range(len(dataset_nms.classes)): - num_pos[cls_index] = num_pos[cls_index] + \ - min(max_dets, len(dataset_nms.src_data[i]['gt_boxes'][cls_index])) - num_bg[cls_index] = num_bg[cls_index] + max(0, min(max_dets, - len(dataset_nms.src_data[i]['dt_boxes'][cls_index])) - - min(max_dets, len(dataset_nms.src_data[i]['gt_boxes'][cls_index]))) - for class_index in range(len(dataset_nms.classes)): - weights[class_index, 0] = (1 - pos_weights[class_index]) * (num_pos[class_index] + - num_bg[class_index]) / num_bg[class_index] - weights[class_index, 1] = pos_weights[class_index] * (num_pos[class_index] + - num_bg[class_index]) / num_pos[class_index] - return weights From 8721f806023a2dc226d8340585ab12b53c45c4c6 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:53:47 +0200 Subject: [PATCH 071/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 56154096e5..97339dcb44 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -35,6 +35,7 @@ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS import pickle + class Seq2SeqNMSLearner(Learner, NMSCustom): def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', checkpoint_after_iter=0, checkpoint_load_iter=0, log_after=500, variant='medium', experiment_name='default', @@ -147,8 +148,9 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, if self.app_feats == 'fmod' and self.fmod_mean_std is None: self.fmod_mean_std = self.load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, - fmod_pyramid_lvl=self.fmod_pyramid_lvl, - datasets_folder=datasets_folder, verbose=verbose) + fmod_pyramid_lvl=self.fmod_pyramid_lvl, + datasets_folder=datasets_folder, + verbose=verbose) self.fMoD.set_mean_std(mean_values=self.fmod_mean_std['mean'], std_values=self.fmod_mean_std['std']) start_epoch = 0 @@ -313,8 +315,9 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, if self.app_feats == 'fmod' and (self.fmod_mean_std is None): self.fmod_mean_std = self.load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, - fmod_pyramid_lvl=self.fmod_pyramid_lvl, - datasets_folder=datasets_folder, verbose=verbose) + fmod_pyramid_lvl=self.fmod_pyramid_lvl, + datasets_folder=datasets_folder, + verbose=verbose) self.fMoD.set_mean_std(mean_values=self.fmod_mean_std['mean'], std_values=self.fmod_mean_std['std']) self.model = self.model.eval() @@ -422,8 +425,8 @@ def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoc metadata["fmod_roi_pooling_dim"] = self.fmod_roi_pooling_dim metadata["fmod_map_res_dim"] = self.fmod_map_res_dim metadata["fmod_pyramid_lvl"] = self.fmod_pyramid_lvl - metadata["fmod_normalization"] = 'fmod_normalization.pkl' - with open(os.path.join(os.path.dirname(path),'fmod_normalization.pkl'), 'wb') as f: + metadata["fmod_normalization"] = "fmod_normalization.pkl" + with open(os.path.join(os.path.dirname(path), 'fmod_normalization.pkl'), 'wb') as f: pickle.dump(self.fmod_mean_std, f) with open(path + '.json', 'w', encoding='utf-8') as f: json.dump(metadata, f, ensure_ascii=False, indent=4) @@ -539,7 +542,6 @@ def assign_params(self, metadata, verbose): self.fmod_pyramid_lvl != metadata["fmod_mean_std"]: print("Incompatible value for the attribute \"fmod_mean_std\". It is now set to: " + str(metadata["fmod_mean_std"])) - #self.fmod_mean_std = metadata["fmod_mean_std"] def load_state(self, checkpoint=None): if checkpoint is None: From 9dd57d504e4e684ecde01a2d2a44841a2fac36e4 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:59:05 +0200 Subject: [PATCH 072/374] Update nms_dataset.py --- .../object_detection_2d/nms/utils/nms_dataset.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 38dc8daf93..44dbdb720c 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -343,16 +343,16 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) if not os.path.exists(os.path.join(self.path, imgs_split)): - self.download('http://images.cocodataset.org/zips/' + imgs_split +'.zip', - download_path=os.path.join(self.path), file_format = "zip", + self.download('http://images.cocodataset.org/zips/' + imgs_split + '.zip', + download_path=os.path.join(self.path), file_format="zip", create_dir=True) pkl_filename = os.path.join(self.path, 'data_' + self.detector + '_' + self.dataset_sets[self.split] + '_coco.pkl') if not os.path.exists(pkl_filename): if not os.path.exists(os.path.join(self.path, 'annotations', 'instances_' + imgs_split + '.json')): self.download('http://images.cocodataset.org/annotations/annotations_trainval2014.zip', download_path=os.path.join(self.path), file_format='zip', create_dir=True) - if not os.path.exists(os.path.join(self.path, 'detections', 'coco_2014_' + self.dataset_sets[self.split] - + '_FRCN_train.pkl')): + if not os.path.exists(os.path.join(self.path, 'detections', + 'coco_2014_' + self.dataset_sets[self.split] + '_FRCN_train.pkl')): self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/coco_2014_FRCN.tar.gz', download_path=os.path.join(self.path, 'detections'), file_format='tar.gz', create_dir=True) From cbc548a544f65378723a5903d89dab5696af0871 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 18:59:50 +0200 Subject: [PATCH 073/374] Update ssd_learner.py --- src/opendr/perception/object_detection_2d/ssd/ssd_learner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py index 26117cb16a..5fa45c9cd9 100644 --- a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py +++ b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py @@ -1,4 +1,4 @@ -# Copyright 2020-2021 OpenDR European Project +# Copyright 2020-2022 OpenDR European Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + # general imports import os import time From fffaf006e574e663314363e9187925ad8f464b71 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:13:40 +0200 Subject: [PATCH 074/374] Create README.md --- .../object_detection_2d/nms/cluster_nms/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md new file mode 100644 index 0000000000..64f4187cd6 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md @@ -0,0 +1,8 @@ +Cluster-NMS +====== + +This folder contains an implementation of [Cluster-NMS](https://arxiv.org/abs/2005.03572). + +Sources +------ +Large parts of code are taken from [GluonCV's SSD implementation](https://github.com/Zzh-tju/CIoU) with modifications to make it compatible with OpenDR specifications. From 98acc5af66cd0cfbda79cc954bc615ea5b8d4663 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:16:59 +0200 Subject: [PATCH 075/374] Update README.md --- .../object_detection_2d/nms/cluster_nms/README.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md index 64f4187cd6..4819ac3b3a 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md @@ -1,8 +1,12 @@ Cluster-NMS ====== -This folder contains an implementation of [Cluster-NMS](https://arxiv.org/abs/2005.03572). +This folder contains an implementation of [[1]](#cluster_nms-1). +[Cluster-NMS](https://arxiv.org/abs/2005.03572). Sources ------ -Large parts of code are taken from [GluonCV's SSD implementation](https://github.com/Zzh-tju/CIoU) with modifications to make it compatible with OpenDR specifications. +Large parts of code are taken from [here](https://github.com/Zzh-tju/CIoU) with modifications to make it compatible with OpenDR specifications. + +[1] NEnhancing Geometric Factors in Model Learning and Inference for Object Detection and Instance Segmentation, +[ArXiv](https://arxiv.org/abs/2005.03572). From c9e58cdcc119a5cfdf55e2249823637928049c4d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:17:46 +0200 Subject: [PATCH 076/374] Update README.md --- .../perception/object_detection_2d/nms/cluster_nms/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md index 4819ac3b3a..759d7a2b29 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md @@ -1,8 +1,7 @@ Cluster-NMS ====== -This folder contains an implementation of [[1]](#cluster_nms-1). -[Cluster-NMS](https://arxiv.org/abs/2005.03572). +This folder contains an implementation of [Cluster-NMS](#cluster_nms-1). Sources ------ From b24c65162a92f856efddf9bcd50626deaa6c9fb7 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:18:01 +0200 Subject: [PATCH 077/374] Update README.md --- .../perception/object_detection_2d/nms/cluster_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md index 759d7a2b29..71488f6cc4 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md @@ -1,7 +1,7 @@ Cluster-NMS ====== -This folder contains an implementation of [Cluster-NMS](#cluster_nms-1). +This folder contains an implementation of Cluster-NMS [1](#cluster_nms-1). Sources ------ From a95fc34eb88175a2364dd814a8c7005d039bb767 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:18:15 +0200 Subject: [PATCH 078/374] Update README.md --- .../perception/object_detection_2d/nms/cluster_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md index 71488f6cc4..489b247037 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md @@ -1,7 +1,7 @@ Cluster-NMS ====== -This folder contains an implementation of Cluster-NMS [1](#cluster_nms-1). +This folder contains an implementation of Cluster-NMS [[1]](#cluster_nms-1). Sources ------ From e86f0efbd032058cebe47c448f4851e2f468f627 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:18:30 +0200 Subject: [PATCH 079/374] Update README.md --- .../perception/object_detection_2d/nms/cluster_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md index 489b247037..fbe82b2928 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md @@ -7,5 +7,5 @@ Sources ------ Large parts of code are taken from [here](https://github.com/Zzh-tju/CIoU) with modifications to make it compatible with OpenDR specifications. -[1] NEnhancing Geometric Factors in Model Learning and Inference for Object Detection and Instance Segmentation, +[1] Enhancing Geometric Factors in Model Learning and Inference for Object Detection and Instance Segmentation, [ArXiv](https://arxiv.org/abs/2005.03572). From 85bd80c5523c0283c8aa00b3bb19ef304dc995c4 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:19:10 +0200 Subject: [PATCH 080/374] Update ssd_learner.py --- src/opendr/perception/object_detection_2d/ssd/ssd_learner.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py index 5fa45c9cd9..eea1df3b84 100644 --- a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py +++ b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. - # general imports import os import time From 13f16d8ac1facaf7711dd85ad039498f1c13932c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:19:21 +0200 Subject: [PATCH 081/374] Update cluster_nms.py --- .../nms/cluster_nms/cluster_nms.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index 0bfb92f101..cfbea222d5 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -1,3 +1,17 @@ +# Copyright 2020-2022 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard, diou, distance from opendr.engine.target import BoundingBox, BoundingBoxList From 131d9445fa534869a432c9561a2d1b6c97cd7604 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:19:37 +0200 Subject: [PATCH 082/374] Update fast_nms.py --- .../object_detection_2d/nms/fast_nms/fast_nms.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py index 4c82488afe..31de9383c2 100644 --- a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py @@ -1,3 +1,17 @@ +# Copyright 2020-2022 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard from opendr.engine.target import BoundingBox, BoundingBoxList From 5f170e386bc884ac4f7d2133264f31532b297d85 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:19:56 +0200 Subject: [PATCH 083/374] Update soft_nms.py --- .../object_detection_2d/nms/soft_nms/soft_nms.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py index 756bc80243..cd5412ba27 100644 --- a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py @@ -1,3 +1,17 @@ +# Copyright 2020-2022 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard from opendr.engine.target import BoundingBox, BoundingBoxList From 7d5abf31c888933cbd5c8f03c2c77e3e2a43df99 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:20:09 +0200 Subject: [PATCH 084/374] Update nms_custom.py --- .../object_detection_2d/nms/utils/nms_custom.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py index fe8215964d..7d551cd401 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_custom.py @@ -1,3 +1,17 @@ +# Copyright 2020-2022 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from abc import ABC, abstractmethod From b4a431352800baee411116288ac14d46f4ce27e0 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:20:33 +0200 Subject: [PATCH 085/374] Update nms_utils.py --- .../object_detection_2d/nms/utils/nms_utils.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py index f3a7e01110..2340abbf38 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py @@ -1,5 +1,18 @@ -import torch +# Copyright 2020-2022 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +import torch def jaccard(box_a, box_b, iscrowd: bool = False): """Compute the jaccard overlap of two sets of boxes. The jaccard overlap From 13cccf8e08cf88b730b927e5b0248f0827d0d3af Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:22:25 +0200 Subject: [PATCH 086/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 44dbdb720c..f60b2517fe 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -10,7 +10,6 @@ # See the License for the specific language governing permissions and # limitations under the License. - from opendr.engine.datasets import Dataset import os from urllib.request import urlretrieve From 55b9a2e19bd5c93f54e61091d20d9adaec7e4211 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:26:58 +0200 Subject: [PATCH 087/374] Update nms_dataset.py --- .../object_detection_2d/nms/utils/nms_dataset.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index f60b2517fe..39c14d551e 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -1,3 +1,5 @@ +# Copyright 2020-2022 OpenDR European Project +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -10,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + from opendr.engine.datasets import Dataset import os from urllib.request import urlretrieve @@ -465,7 +468,3 @@ def members(tf): os.remove(tar_path) else: raise ValueError("Unsupported file_format: " + file_format) - - # def __prepare_dataset(self): - # seq_root = os.path.join(self.path, "images/train") - # label_root = os.path.join(self.path, "labels/test") From c05fa4ff433d7f73a1347edbc8b08aed83d598bd Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:29:06 +0200 Subject: [PATCH 088/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 97339dcb44..6db9646898 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -1,3 +1,5 @@ +# Copyright 2020-2022 OpenDR European Project +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at From ba0dd1a285cd9908422dadf92e48c92669c67cfa Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:29:26 +0200 Subject: [PATCH 089/374] Update dataset.py --- .../object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py index b836289d5c..9103b0b46f 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py @@ -1,4 +1,5 @@ - +# Copyright 2020-2022 OpenDR European Project +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at From 0267f9caa3734678127a7b1ebbe109327aceab8a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:29:43 +0200 Subject: [PATCH 090/374] Update fmod.py --- .../object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py index aee4f2f8aa..aa25d28383 100755 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py @@ -1,4 +1,5 @@ - +# Copyright 2020-2022 OpenDR European Project +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at From 5ad6ab89a2b523c071163b648ef1344f7c084626 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:30:02 +0200 Subject: [PATCH 091/374] Update seq2seq_model.py --- .../nms/seq2seq_nms/algorithm/seq2seq_model.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py index fa4d1e1e06..275827fbce 100755 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py @@ -1,4 +1,5 @@ - +# Copyright 2020-2022 OpenDR European Project +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at From fc34d1b13b80e720f8bc0a3707ba1746ff145ef2 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 19:33:18 +0200 Subject: [PATCH 092/374] Update transforms.py --- .../perception/object_detection_2d/datasets/transforms.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/datasets/transforms.py b/src/opendr/perception/object_detection_2d/datasets/transforms.py index 09e75aefad..98a87e4d61 100644 --- a/src/opendr/perception/object_detection_2d/datasets/transforms.py +++ b/src/opendr/perception/object_detection_2d/datasets/transforms.py @@ -1,4 +1,4 @@ -# Copyright 2020-2021 OpenDR European Project +# Copyright 2020-2022 OpenDR European Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + import cv2 import numpy as np import mxnet as mx From 946bd1141750381bb1f71307476d53c3670dcc08 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 21:23:36 +0200 Subject: [PATCH 093/374] Update inference_demo.py --- .../nms/soft_nms/inference_demo.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py index ba7c1c012c..004fa5f41e 100644 --- a/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py @@ -1,3 +1,18 @@ +# Copyright 2020-2022 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + from opendr.perception.object_detection_2d.nms.soft_nms.soft_nms import SoftNMS from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner From 38b84764b5b7b611788f8892e3b4857fab2434c7 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 21:23:49 +0200 Subject: [PATCH 094/374] Update inference_demo.py --- .../nms/fast_nms/inference_demo.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py index 4927df45a2..0c0648a921 100644 --- a/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py @@ -1,3 +1,18 @@ +# Copyright 2020-2022 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + from opendr.perception.object_detection_2d.nms.fast_nms.fast_nms import FastNMS from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner From 7cd5549f0c67257e9ef642ba5213c8182954910b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 21:24:07 +0200 Subject: [PATCH 095/374] Update inference_demo.py --- .../nms/cluster_nms/inference_demo.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py index b916a23755..f4655f9105 100644 --- a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py @@ -1,3 +1,18 @@ +# Copyright 2020-2022 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + from opendr.perception.object_detection_2d.nms.cluster_nms.cluster_nms import ClusterNMS from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner From a24ca773fbb600f89d716f1ba4ab9d8318615cdb Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 21:24:21 +0200 Subject: [PATCH 096/374] Update inference_demo.py --- .../nms/seq2seq-nms/inference_demo.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index f3b81a79ba..ca2e07bc36 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -1,3 +1,18 @@ +# Copyright 2020-2022 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner From 299dd92090e96e7319796be502a1b8f1409b6655 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 21:31:24 +0200 Subject: [PATCH 097/374] Update inference_demo.py --- .../object_detection_2d/nms/seq2seq-nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index ca2e07bc36..f0c87a23cf 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -20,7 +20,7 @@ import os OPENDR_HOME = os.environ['OPENDR_HOME'] -seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, experiment_name='pets_exp0', +seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=0.8, experiment_name='pets_exp0', app_feats='fmod', device='cpu') seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/pets_exp0/' 'checkpoints/checkpoint_epoch_7', verbose=True) From 8705b07e1540958c3b2c18312d195d4bae1102b7 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 21:31:46 +0200 Subject: [PATCH 098/374] Update nms_utils.py --- .../perception/object_detection_2d/nms/utils/nms_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py index 2340abbf38..1dfc954a00 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py @@ -12,8 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. + import torch + def jaccard(box_a, box_b, iscrowd: bool = False): """Compute the jaccard overlap of two sets of boxes. The jaccard overlap is simply the intersection over union of two boxes. Here we operate on From 81cf6dee3d28f2846c2e8f6d0d8ea1a094b4215c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 21:35:57 +0200 Subject: [PATCH 099/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 6db9646898..3b6edd7b7c 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -486,7 +486,7 @@ def load(self, path, verbose=False): def assign_params(self, metadata, verbose): - if verbose and self.geom_input_dim is not None and self.geom_input_dim != metadata["variant"]: + if verbose and self.variant is not None and self.variant != metadata["variant"]: print("Incompatible value for the attribute \"variant\". It is now set to: " + str(metadata["variant"])) self.variant = metadata["variant"] @@ -539,11 +539,7 @@ def assign_params(self, metadata, verbose): str(metadata["num_JPUs"])) self.num_JPUs = metadata["num_JPUs"] if verbose and 'max_dt_boxes' in metadata: - print('Model is trained with as ' + str(metadata['max_dt_boxes']) + 'its maximum number of detections.') - if verbose and self.fmod_pyramid_lvl is not None and \ - self.fmod_pyramid_lvl != metadata["fmod_mean_std"]: - print("Incompatible value for the attribute \"fmod_mean_std\". It is now set to: " + - str(metadata["fmod_mean_std"])) + print('Model is trained with as ' + str(metadata['max_dt_boxes']) + ' the maximum number of detections.') def load_state(self, checkpoint=None): if checkpoint is None: From 1354945f835b2e3370f9fadd2a4b1816958beaea Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 23:10:26 +0200 Subject: [PATCH 100/374] Update soft_nms.py --- .../nms/soft_nms/soft_nms.py | 102 ------------------ 1 file changed, 102 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py index cd5412ba27..539de5388f 100644 --- a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py @@ -78,11 +78,8 @@ def run_nms(self, boxes=None, scores=None, threshold=0.2, img=None): dets = torch.cat((boxes, scores.unsqueeze(-1)), dim=1) - retained_box = [] i = 0 while dets.shape[0] > 0: - max_idx = np.argmax(dets[:, 4], axis=0) - # dets[[0, max_idx], :] = dets[[max_idx, 0], :] scores[i] = dets[0, 4] iou = jaccard(dets[:1, :-1], dets[1:, :-1]).triu_(diagonal=0).squeeze(0) weight = torch.ones_like(iou) @@ -92,7 +89,6 @@ def run_nms(self, boxes=None, scores=None, threshold=0.2, img=None): weight = np.exp(-(iou * iou) / self.nms_thres) dets[1:, 4] *= weight - # retained_idx = torch.where(dets[1:, 4] >= 0)[0] dets = dets[1:, :] i = i + 1 keep_ids = torch.where(scores > threshold) @@ -109,101 +105,3 @@ def run_nms(self, boxes=None, scores=None, threshold=0.2, img=None): bounding_boxes.data.append(bbox) return bounding_boxes, [boxes, classes, scores] - - -def fast_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): - scores, idx = scores.sort(1, descending=True) - boxes = boxes[idx, :] - - scores = scores[:, :top_k] - boxes = boxes[:, :top_k] - - num_classes, num_dets = scores.shape - - boxes = boxes.view(num_classes, num_dets, 4) - - iou = jaccard(boxes, boxes).triu_(diagonal=1) - iou_max, _ = iou.max(dim=1) - - keep = (iou_max <= iou_thres) - keep *= (scores > 0.01) - classes = torch.arange(num_classes, device=boxes.device)[:, None].expand_as(keep) - classes = classes[keep] - - boxes = boxes[keep] - scores = scores[keep] - - scores, idx = scores.sort(0, descending=True) - idx = idx[:post_k] - scores = scores[:post_k] - - classes = classes[idx] - boxes = boxes[idx] - return boxes, classes, scores - - -def cc_fast_nms(boxes=None, scores=None, iou_thres=0.45, top_k=400, post_k=200): - scores, classes = scores.max(dim=0) - _, idx = scores.sort(0, descending=True) - idx = idx[:top_k] - boxes = boxes[idx] - scores = scores[idx] - classes = classes[idx] - iou = jaccard(boxes, boxes).triu_(diagonal=1) - maxA, _ = torch.max(iou, dim=0) - - idx_out = torch.where(maxA > iou_thres) - scores[idx_out] = 0 - scores, idx = scores.sort(0, descending=True) - idx = idx[:post_k] - scores = scores[:post_k] - classes = classes[idx] - boxes = boxes[idx] - return boxes, classes, scores - - -def py_soft_nms(dets, method='linear', iou_thr=0.3, sigma=0.5, score_thr=0.001): - - if method not in ('linear', 'gaussian', 'greedy'): - raise ValueError('method must be linear, gaussian or greedy') - - x1 = dets[:, 0] - y1 = dets[:, 1] - x2 = dets[:, 2] - y2 = dets[:, 3] - - areas = (x2 - x1 + 1) * (y2 - y1 + 1) - # expand dets with areas, and the second dimension is - # x1, y1, x2, y2, score, area - dets = np.concatenate((dets, areas[:, None]), axis=1) - - retained_box = [] - while dets.size > 0: - max_idx = np.argmax(dets[:, 4], axis=0) - dets[[0, max_idx], :] = dets[[max_idx, 0], :] - retained_box.append(dets[0, :-1]) - - xx1 = np.maximum(dets[0, 0], dets[1:, 0]) - yy1 = np.maximum(dets[0, 1], dets[1:, 1]) - xx2 = np.minimum(dets[0, 2], dets[1:, 2]) - yy2 = np.minimum(dets[0, 3], dets[1:, 3]) - - w = np.maximum(xx2 - xx1 + 1, 0.0) - h = np.maximum(yy2 - yy1 + 1, 0.0) - inter = w * h - iou = inter / (dets[0, 5] + dets[1:, 5] - inter) - - if method == 'linear': - weight = np.ones_like(iou) - weight[iou > iou_thr] -= iou[iou > iou_thr] - elif method == 'gaussian': - weight = np.exp(-(iou * iou) / sigma) - else: # traditional nms - weight = np.ones_like(iou) - weight[iou > iou_thr] = 0 - - dets[1:, 4] *= weight - retained_idx = np.where(dets[1:, 4] >= score_thr)[0] - dets = dets[retained_idx + 1, :] - - return np.vstack(retained_box) From e21afb44b5af9fd905f6799f040869334f08c1ae Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 23:11:00 +0200 Subject: [PATCH 101/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 3b6edd7b7c..a0d6b2335b 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -35,7 +35,6 @@ from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS -import pickle class Seq2SeqNMSLearner(Learner, NMSCustom): From fd945f80f4c64700fe5073462d75eba44371d878 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 23:11:36 +0200 Subject: [PATCH 102/374] Update transforms.py --- .../perception/object_detection_2d/datasets/transforms.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/datasets/transforms.py b/src/opendr/perception/object_detection_2d/datasets/transforms.py index 98a87e4d61..c308e32a12 100644 --- a/src/opendr/perception/object_detection_2d/datasets/transforms.py +++ b/src/opendr/perception/object_detection_2d/datasets/transforms.py @@ -146,11 +146,9 @@ def transform_test(imgs, mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)): def pad_test(img, min_size=512): h_pad_size = 0 - pad_dim = 0 min_dim = 2 + np.argmin([img.shape[2:4]]) img_padded = img if img.shape[min_dim] < min_size: - pad_dim = min_dim h_pad_size = int((min_size - img.shape[min_dim]) / 2.0) if min_dim == 2: img_padded = mx.nd.pad(img, mode="constant", constant_value=0, From 018793c6a425d520bddd47c8a05e48f94be1e93e Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 23:21:33 +0200 Subject: [PATCH 103/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index a0d6b2335b..16fb7219dd 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -147,8 +147,9 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, elif self.epochs <= self.checkpoint_load_iter: raise ValueError("Training epochs are less than those of the loaded model") - if self.app_feats == 'fmod' and self.fmod_mean_std is None: - self.fmod_mean_std = self.load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, + if self.app_feats == 'fmod': + if self.fmod_mean_std is None: + self.fmod_mean_std = self.load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, fmod_pyramid_lvl=self.fmod_pyramid_lvl, datasets_folder=datasets_folder, verbose=verbose) @@ -314,8 +315,9 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, elif self.model is None: raise AttributeError("self.model is None. Please load a model or set checkpoint_load_iter.") - if self.app_feats == 'fmod' and (self.fmod_mean_std is None): - self.fmod_mean_std = self.load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, + if self.app_feats == 'fmod': + if self.fmod_mean_std is None: + self.fmod_mean_std = self.load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, fmod_pyramid_lvl=self.fmod_pyramid_lvl, datasets_folder=datasets_folder, verbose=verbose) From 7171df9aadd1332e7741d2ee56045216ae0053a6 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 23:23:38 +0200 Subject: [PATCH 104/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 16fb7219dd..b7e47c5788 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -472,6 +472,7 @@ def load(self, path, verbose=False): try: with open(pkl_fmod, 'rb') as f: self.fmod_mean_std = pickle.load(f) + self.fMoD.set_mean_std(mean_values=self.fmod_mean_std['mean'], std_values=self.fmod_mean_std['std']) except FileNotFoundError as e: e.strerror = "File " + pkl_fmod + "not found." raise e From 9268cd4247f4cfc4371217662c9dc84b589faa27 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 9 Mar 2022 23:27:25 +0200 Subject: [PATCH 105/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index b7e47c5788..1b5b9f1b2e 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -150,9 +150,9 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, if self.app_feats == 'fmod': if self.fmod_mean_std is None: self.fmod_mean_std = self.load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, - fmod_pyramid_lvl=self.fmod_pyramid_lvl, - datasets_folder=datasets_folder, - verbose=verbose) + fmod_pyramid_lvl=self.fmod_pyramid_lvl, + datasets_folder=datasets_folder, + verbose=verbose) self.fMoD.set_mean_std(mean_values=self.fmod_mean_std['mean'], std_values=self.fmod_mean_std['std']) start_epoch = 0 @@ -318,9 +318,9 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, if self.app_feats == 'fmod': if self.fmod_mean_std is None: self.fmod_mean_std = self.load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, - fmod_pyramid_lvl=self.fmod_pyramid_lvl, - datasets_folder=datasets_folder, - verbose=verbose) + fmod_pyramid_lvl=self.fmod_pyramid_lvl, + datasets_folder=datasets_folder, + verbose=verbose) self.fMoD.set_mean_std(mean_values=self.fmod_mean_std['mean'], std_values=self.fmod_mean_std['std']) self.model = self.model.eval() From c9929f83117fefb3c83600bc01feaaa827c5a2e5 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 10 Mar 2022 13:19:18 +0200 Subject: [PATCH 106/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 1b5b9f1b2e..4e968aa38a 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -182,9 +182,6 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, np.random.shuffle(train_ids) for sample_id in train_ids: image_fln = dataset_nms.src_data[sample_id]['filename'] - loss = torch.tensor([0.0], requires_grad=True) - if self.device == 'cuda': - loss = loss.cuda() if len(dataset_nms.src_data[sample_id]['dt_boxes'][class_index]) > 0: dt_boxes = torch.tensor( dataset_nms.src_data[sample_id]['dt_boxes'][class_index][:, 0:4]).float() @@ -243,7 +240,6 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, labels = det_matching(scores=preds, dt_boxes=dt_boxes, gt_boxes=gt_boxes, iou_thres=nms_gt_iou) - # weights = (2.92 * labels + 0.932 * (1 - labels)).cuda() weights = (training_weights[class_index][1] * labels + training_weights[class_index][0] * ( 1 - labels)).cuda() @@ -252,7 +248,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, e = e.cuda() labels = labels * (1 - e) + (1 - labels) * e ce_loss = F.binary_cross_entropy(preds, labels, reduction="none") - loss = loss + (ce_loss * weights).sum() + loss = (ce_loss * weights).sum() total_loss_iter = total_loss_iter + loss total_loss_epoch = total_loss_epoch + loss loss.backward() From 1aa5765bea98705a8b6d3f9fabf526e8ceed03d4 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 10 Mar 2022 17:11:06 +0200 Subject: [PATCH 107/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 4e968aa38a..f18f20ad71 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -223,7 +223,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, app_feats = self.fMoD.extract_FMoD_feats(dt_boxes) app_feats = torch.unsqueeze(app_feats, dim=1) elif self.app_feats == 'zeros': - app_feats = torch.zeros([dt_boxes.shape[0], self.app_input_dim]) + app_feats = torch.zeros([dt_boxes.shape[0], 1, self.app_input_dim]) if self.device == 'cuda': app_feats = app_feats.cuda() elif self.app_feats == 'custom': @@ -370,7 +370,7 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, app_feats = self.fMoD.extract_FMoD_feats(dt_boxes) app_feats = torch.unsqueeze(app_feats, dim=1) elif self.app_feats == 'zeros': - app_feats = torch.zeros([dt_boxes.shape[0], self.app_input_dim]) + app_feats = torch.zeros([dt_boxes.shape[0], 1, self.app_input_dim]) if self.device == 'cuda': app_feats = app_feats.cuda() elif self.app_feats == 'custom': @@ -625,7 +625,7 @@ def infer(self, boxes=None, scores=None, boxes_sorted=False, max_dt_boxes=400, i app_feats = self.fMoD.extract_FMoD_feats(boxes) app_feats = torch.unsqueeze(app_feats, dim=1) elif self.app_feats == 'zeros': - app_feats = torch.zeros([boxes.shape[0], self.app_input_dim]) + app_feats = torch.zeros([boxes.shape[0], 1, self.app_input_dim]) if self.device == 'cuda': app_feats = app_feats.cuda() elif self.app_feats == 'custom': From 254d41f6f82c9fbb5d401ad9097840ac09069b48 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 10 Mar 2022 18:31:43 +0200 Subject: [PATCH 108/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index f18f20ad71..fae29e87fb 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -232,20 +232,19 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, msk = self.compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) q_geom_feats, k_geom_feats = self.compute_geometrical_feats(boxes=dt_boxes, scores=dt_scores, resolution=img_res) - - optimizer.zero_grad() preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, app_feats=app_feats) preds = torch.clamp(preds, 0.001, 1 - 0.001) labels = det_matching(scores=preds, dt_boxes=dt_boxes, gt_boxes=gt_boxes, - iou_thres=nms_gt_iou) + iou_thres=nms_gt_iou, device=self.device) weights = (training_weights[class_index][1] * labels + training_weights[class_index][0] * ( - 1 - labels)).cuda() + 1 - labels)) e = torch.distributions.uniform.Uniform(0.02, 0.0205).sample([labels.shape[0], 1]) if self.device == 'cuda': e = e.cuda() + weights = weights.cuda() labels = labels * (1 - e) + (1 - labels) * e ce_loss = F.binary_cross_entropy(preds, labels, reduction="none") loss = (ce_loss * weights).sum() From c6e6014aece010b0f5e60bd09e29693bfab0aec2 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 10 Mar 2022 19:03:30 +0200 Subject: [PATCH 109/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index fae29e87fb..3bfc4e6569 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -248,10 +248,15 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, labels = labels * (1 - e) + (1 - labels) * e ce_loss = F.binary_cross_entropy(preds, labels, reduction="none") loss = (ce_loss * weights).sum() - total_loss_iter = total_loss_iter + loss - total_loss_epoch = total_loss_epoch + loss + loss.backward() + optimizer.zero_grad() optimizer.step() + # Memory leak if not loss not detached in total_loss_iter and total_loss_epoch computations + loss_t = loss.detach().cpu().numpy() + total_loss_iter = total_loss_iter + loss_t + total_loss_epoch = total_loss_epoch + loss_t + num_iter = num_iter + 1 if self.log_after != 0 and num_iter % self.log_after == 0: if logging: From 24a4a01e1173211baa43386580689bb3181525b9 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 10 Mar 2022 19:20:18 +0200 Subject: [PATCH 110/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 3bfc4e6569..bc68748dce 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -249,8 +249,8 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, ce_loss = F.binary_cross_entropy(preds, labels, reduction="none") loss = (ce_loss * weights).sum() - loss.backward() optimizer.zero_grad() + loss.backward() optimizer.step() # Memory leak if not loss not detached in total_loss_iter and total_loss_epoch computations loss_t = loss.detach().cpu().numpy() From 44819851d8c51a561f4ce478d885ba08dfbdd6cc Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 10 Mar 2022 22:25:58 +0200 Subject: [PATCH 111/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index bc68748dce..3af22aea13 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -189,6 +189,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) dt_boxes = dt_boxes[dt_scores_ids] else: + pbar.update(1) continue gt_boxes = torch.tensor([]).float() if len(dataset_nms.src_data[sample_id]['gt_boxes'][class_index]) > 0: @@ -208,6 +209,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, dt_boxes, dt_scores = drop_dets(dt_boxes, dt_scores) if dt_boxes.shape[0] < 1: + pbar.update(1) continue if self.iou_filtering is not None and 1.0 > self.iou_filtering > 0: dt_boxes, dt_scores = apply_torchNMS(boxes=dt_boxes, scores=dt_scores, @@ -256,7 +258,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, loss_t = loss.detach().cpu().numpy() total_loss_iter = total_loss_iter + loss_t total_loss_epoch = total_loss_epoch + loss_t - + num_iter = num_iter + 1 if self.log_after != 0 and num_iter % self.log_after == 0: if logging: From cc54bfe8175f8025946e4f363980733e80fd35dc Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 11:24:26 +0200 Subject: [PATCH 112/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 41 +++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 3af22aea13..43b2fa6fa4 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -35,11 +35,11 @@ from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS - +import gc class Seq2SeqNMSLearner(Learner, NMSCustom): def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', checkpoint_after_iter=0, - checkpoint_load_iter=0, log_after=500, variant='medium', experiment_name='default', + checkpoint_load_iter=0, log_after=10000, variant='medium', experiment_name='default', iou_filtering=0.8, dropout=0.05, pretrained_demo_model=None, app_feats='fmod', fmod_map_type='EDGEMAP', fmod_map_bin=True, app_input_dim=None): super(Seq2SeqNMSLearner, self).__init__(lr=lr, batch_size=1, @@ -52,6 +52,11 @@ def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', check self.use_app_feats = False if self.app_feats is not None: self.use_app_feats = True + self.fmod_map_type=None + self.fmod_map_bin=None + self.fmod_map_res_dim = None + self.fmod_pyramid_lvl = None + self.fmod_roi_pooling_dim = None if self.app_feats == 'fmod': self.fmod_map_type = fmod_map_type self.fmod_roi_pooling_dim = 160 @@ -237,16 +242,16 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, app_feats=app_feats) preds = torch.clamp(preds, 0.001, 1 - 0.001) + labels = det_matching(scores=preds, dt_boxes=dt_boxes, gt_boxes=gt_boxes, iou_thres=nms_gt_iou, device=self.device) - weights = (training_weights[class_index][1] * labels + training_weights[class_index][0] * ( 1 - labels)) e = torch.distributions.uniform.Uniform(0.02, 0.0205).sample([labels.shape[0], 1]) if self.device == 'cuda': - e = e.cuda() weights = weights.cuda() + e = e.cuda() labels = labels * (1 - e) + (1 - labels) * e ce_loss = F.binary_cross_entropy(preds, labels, reduction="none") loss = (ce_loss * weights).sum() @@ -258,17 +263,16 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, loss_t = loss.detach().cpu().numpy() total_loss_iter = total_loss_iter + loss_t total_loss_epoch = total_loss_epoch + loss_t - num_iter = num_iter + 1 if self.log_after != 0 and num_iter % self.log_after == 0: if logging: file_writer.add_scalar(tag="cross_entropy_loss", - scalar_value=total_loss_iter / self.log_after, + scalar_value=total_loss_iter/self.log_after, global_step=num_iter) if verbose: print(''.join(['\nEpoch: {}', ' Iter: {}, cross_entropy_loss: {}']).format(epoch, num_iter, - total_loss_iter / self.log_after)) + total_loss_iter/self.log_after)) total_loss_iter = 0 if not silent: pbar.update(1) @@ -277,8 +281,8 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, if verbose: print(''.join(['\nEpoch: {}', ' cross_entropy_loss: {}\n']).format(epoch, - total_loss_epoch / len(train_ids))) - training_dict['cross_entropy_loss'].append(total_loss_epoch / len(train_ids)) + total_loss_epoch/len(train_ids))) + training_dict['cross_entropy_loss'].append(total_loss_epoch/len(train_ids)) if self.checkpoint_after_iter != 0 and epoch % self.checkpoint_after_iter == self.checkpoint_after_iter - 1: snapshot_name = '{}/checkpoint_epoch_{}'.format(checkpoints_folder, epoch) self.save(path=snapshot_name, optimizer=optimizer, scheduler=scheduler, @@ -467,7 +471,7 @@ def load(self, path, verbose=False): except FileNotFoundError as e: e.strerror = "File " + pth_path + "not found." raise e - if metadata['fmod_normalization']: + if 'fmod_normalization' in metadata: pkl_fmod = os.path.join(dir_path, metadata["fmod_normalization"]) if verbose: print("Loading FMoD normalization values:", pkl_fmod) @@ -509,26 +513,31 @@ def assign_params(self, metadata, verbose): if verbose and self.fmod_map_type is not None and self.fmod_map_type != metadata["fmod_map_type"]: print("Incompatible value for the attribute \"fmod_map_type\". It is now set to: " + str(metadata["fmod_map_type"])) - self.fmod_map_type = metadata["fmod_map_type"] + if "fmod_map_type" in metadata: + self.fmod_map_type = metadata["fmod_map_type"] if verbose and self.fmod_map_bin is not None and self.fmod_map_bin != metadata["fmod_map_bin"]: print("Incompatible value for the attribute \"fmod_map_bin\". It is now set to: " + str(metadata["fmod_map_bin"])) - self.fmod_map_bin = metadata["fmod_map_bin"] + if "fmod_map_bin" in metadata: + self.fmod_map_bin = metadata["fmod_map_bin"] if verbose and self.fmod_roi_pooling_dim is not None and \ self.fmod_roi_pooling_dim != metadata["fmod_roi_pooling_dim"]: print("Incompatible value for the attribute \"fmod_roi_pooling_dim\". It is now set to: " + str(metadata["fmod_roi_pooling_dim"])) - self.fmod_roi_pooling_dim = metadata["fmod_roi_pooling_dim"] + if "fmod_roi_pooling_dim" in metadata: + self.fmod_roi_pooling_dim = metadata["fmod_roi_pooling_dim"] if verbose and self.fmod_map_res_dim is not None and \ self.fmod_map_res_dim != metadata["fmod_map_res_dim"]: print("Incompatible value for the attribute \"fmod_map_res_dim\". It is now set to: " + str(metadata["fmod_map_res_dim"])) - self.fmod_map_res_dim = metadata["fmod_map_res_dim"] + if "fmod_roi_pooling_dim" in metadata: + self.fmod_roi_pooling_dim = metadata["fmod_roi_pooling_dim"] if verbose and self.fmod_pyramid_lvl is not None and \ self.fmod_pyramid_lvl != metadata["fmod_pyramid_lvl"]: print("Incompatible value for the attribute \"fmod_pyramid_lvl\". It is now set to: " + str(metadata["fmod_pyramid_lvl"])) - self.fmod_pyramid_lvl = metadata["fmod_pyramid_lvl"] + if "fmod_pyramid_lvl" in metadata: + self.fmod_pyramid_lvl = metadata["fmod_pyramid_lvl"] if verbose and self.lq_dim is not None and \ self.lq_dim != metadata["lq_dim"]: print("Incompatible value for the attribute \"lq_dim\". It is now set to: " + @@ -543,7 +552,7 @@ def assign_params(self, metadata, verbose): str(metadata["num_JPUs"])) self.num_JPUs = metadata["num_JPUs"] if verbose and 'max_dt_boxes' in metadata: - print('Model is trained with as ' + str(metadata['max_dt_boxes']) + ' the maximum number of detections.') + print('Model is trained with ' + str(metadata['max_dt_boxes']) + ' as the maximum number of detections.') def load_state(self, checkpoint=None): if checkpoint is None: From 74d77776d09099e3b0ad601998cdc2b9e00156cc Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 12:27:37 +0200 Subject: [PATCH 113/374] Update nms_dataset.py --- .../nms/utils/nms_dataset.py | 152 ++++-------------- 1 file changed, 30 insertions(+), 122 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 39c14d551e..b4b99f000f 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -1,5 +1,3 @@ -# Copyright 2020-2022 OpenDR European Project -# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -20,8 +18,6 @@ import time from zipfile import ZipFile import tarfile -import gdown -import shutil import pickle import numpy as np import math @@ -36,7 +32,7 @@ class Dataset_NMS(Dataset): def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, device='cuda'): super().__init__() - available_dataset = ['COCO', 'PETS', 'CrowdHuman'] + available_dataset = ['COCO', 'PETS',] self.dataset_sets = {'train': None, 'val': None, 'test': None} @@ -219,123 +215,18 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic self.classes = ['background', 'human'] self.class_ids = [-1, 1] - - elif self.dataset_name == "CrowdHuman": - splits = ['train', 'val'] - if self.split not in splits: - raise ValueError(self.split + ' split is not available...') - self.detector = 'YOLOv4' - self.detector_type = 'default' - if use_ssd: - self.detector = 'SSD' - self.detector_type = 'custom' - if not os.path.exists(os.path.join(self.path, 'images/train')): - os.makedirs(os.path.join(self.path, 'images/train'), exist_ok=True) - urls = ['https://drive.google.com/file/d/134QOvaatwKdy0iIeNqA_p-xkAhkV4F8Y/view?usp=sharing', - 'https://drive.google.com/u/0/uc?id=17evzPh7gc1JBNvnW1ENXLy5Kr4Q_Nnla', - 'https://drive.google.com/u/0/uc?id=1tdp0UCgxrqy1B6p8LkR-Iy0aIJ8l4fJW'] - outputs = [os.path.join(self.path, 'CrowdHuman_train01.zip'), 'CrowdHuman_train02.zip', - 'CrowdHuman_train03.zip'] - for i in range(0, len(urls)): - gdown.download(urls[i], outputs[i], quiet=False) - zip_path = os.path.join('.', outputs[i]) - with ZipFile(zip_path, 'r') as zip_ref: - download_path = os.path.join(self.path, 'images', 'train') - zip_ref.extractall(download_path) - os.remove(zip_path) - - if not os.path.exists(os.path.join(self.path, 'images/val')): - os.makedirs(os.path.join(self.path, 'images/val'), exist_ok=True) - url = 'https://drive.google.com/u/0/uc?id=18jFI789CoHTppQ7vmRSFEdnGaSQZ4YzO' - output = 'CrowdHuman_val.zip' - gdown.download(url, output, quiet=False) - zip_path = os.path.join('.', output) - with ZipFile(zip_path, 'r') as zip_ref: - download_path = os.path.join(self.path, 'images', 'val') - zip_ref.extractall(download_path) - os.remove(zip_path) - - if not os.path.exists( - os.path.join(self.path, 'data_' + self.detector + '_' + self.split + '_crowdhuman.pkl')): - # Download detections from FTP server - ssd = None - if use_ssd: - ssd = SingleShotDetectorLearner(device=device) - ssd.download(".", mode="pretrained") - ssd.load("./ssd_default_person", verbose=True) - - # Download annotations from official CrowdHuman GoogleDrive repo - if not os.path.exists(os.path.join(self.path, 'annotations', 'annotation_' + self.split + '.odgt')): - os.makedirs(os.path.join(self.path, 'annotations'), exist_ok=True) - url = None - if self.split == 'train': - url = 'https://drive.google.com/u/0/uc?id=1UUTea5mYqvlUObsC1Z8CFldHJAtLtMX3&export=download' - elif self.split == 'val': - url = 'https://drive.google.com/u/0/uc?id=10WIRwu8ju8GRLuCkZ_vT6hnNxs5ptwoL&export=download' - output = 'annotation_' + self.split + '.odgt' - gdown.download(url, output, quiet=False) - shutil.move(os.path.join('.', output), - os.path.join('.', 'datasets', 'CrowdHuman', 'annotations', self.split)) - - with open(os.path.join(self.path, 'annotations', 'annotation_' + self.split + '.odgt')) as fp_gt: - data_dt = None - if self.detector_type == 'default': - fp_dt = open( - os.path.join(self.path, 'detections', 'det_data_' + self.split + '_crowdhuman.pkl'), 'rb') - data_dt = pickle.load(fp_dt) - line = fp_gt.readline() - i = 0 - while line: - annotations = json.loads(line) - img = Image.open(os.path.join(self.path, 'images/' + self.split, annotations['ID'] + '.jpg')) - dt_boxes = [] - if self.detector_type == 'default' and data_dt[i]['id'] != annotations['ID']: - continue - elif self.detector_type == 'default': - dt_boxes = data_dt[i]['dt_boxes'] - elif self.detector_type == 'custom' and self.detector == 'SSD': - bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, - nms_topk=10000, post_nms=10000) - bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) - bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] - bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] - bboxes_list = bboxes_list[:8000, :] - for b in range(len(bboxes_list)): - dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], - bboxes_list[b, 3], bboxes_list[b, 4][0]])) - gt_boxes = [] - for j in range(len(annotations['gtboxes'])): - if annotations['gtboxes'][j]['tag'] == 'person': - gt_box = annotations['gtboxes'][j]['fbox'] - gt_box[2] = gt_box[2] + gt_box[0] - gt_box[3] = gt_box[3] + gt_box[1] - gt_boxes.append(gt_box) - self.src_data.append({ - 'id': annotations['ID'], - 'filename': annotations['ID'] + '.jpg', - 'resolution': img.opencv().shape[0:2][::-1], - 'gt_boxes': [np.asarray([]), np.asarray(gt_boxes)], - 'dt_boxes': [np.asarray([]), np.asarray(dt_boxes)] - }) - line = fp_gt.readline() - i = i + 1 - with open(os.path.join(self.path, 'data_' + self.split + '_crowdhuman.pkl'), 'wb') as handle: - pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) - else: - with open(os.path.join(self.path, 'data_' + self.split + '_crowdhuman.pkl'), 'rb') as fp_dt: - self.src_data = pickle.load(fp_dt) + self.annotation_file = 'instances_' + self.dataset_sets[self.split] + '.json' elif self.dataset_name == "COCO": self.dataset_sets['train'] = 'train' self.dataset_sets['val'] = 'minival' self.dataset_sets['test'] = 'valminusminival' - imgs_split = None if self.dataset_sets[self.split] is None: raise ValueError(self.split + ' split is not available...') elif self.dataset_sets[self.split] == 'train': imgs_split = 'train2014' else: imgs_split = 'val2014' - self.detector = 'YOLOv4' + self.detector = 'FRCN' self.detector_type = 'default' ssd = None if use_ssd: @@ -345,23 +236,39 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) if not os.path.exists(os.path.join(self.path, imgs_split)): - self.download('http://images.cocodataset.org/zips/' + imgs_split + '.zip', + self.download('http://images.cocodataset.org/zips/' + imgs_split +'.zip', download_path=os.path.join(self.path), file_format="zip", create_dir=True) - pkl_filename = os.path.join(self.path, 'data_' + self.detector + '_' + self.dataset_sets[self.split] + '_coco.pkl') + pkl_filename = os.path.join(self.path, 'data_' + self.detector + '_' + + self.dataset_sets[self.split] + '_coco.pkl') if not os.path.exists(pkl_filename): - if not os.path.exists(os.path.join(self.path, 'annotations', 'instances_' + imgs_split + '.json')): - self.download('http://images.cocodataset.org/annotations/annotations_trainval2014.zip', - download_path=os.path.join(self.path), file_format='zip', create_dir=True) - if not os.path.exists(os.path.join(self.path, 'detections', - 'coco_2014_' + self.dataset_sets[self.split] + '_FRCN_train.pkl')): + if not os.path.exists(os.path.join(self.path, 'annotations', 'instances_' + + self.dataset_sets[self.split] + + '2014.json')): + if self.dataset_sets[self.split] == 'train': + ann_url = 'http://images.cocodataset.org/annotations/annotations_trainval2014.zip' + self.download(ann_url, download_path=os.path.join(self.path), file_format="zip", + create_dir=True) + else: + if self.dataset_sets[self.split] == 'val': + ann_url = 'https://dl.dropboxusercontent.com/s/o43o90bna78omob/' \ + 'instances_minival2014.json.zip?dl=0' + else: + ann_url = 'https://dl.dropboxusercontent.com/s/s3tw5zcg7395368/' \ + 'instances_valminusminival2014.json.zip?dl=0' + self.download(ann_url, download_path=os.path.join(self.path, 'annotations'), file_format="zip", + create_dir=True) + if not os.path.exists(os.path.join(self.path, 'detections', 'coco_2014_' + + self.dataset_sets[self.split] + + '_FRCN_train.pkl')): self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/coco_2014_FRCN.tar.gz', download_path=os.path.join(self.path, 'detections'), file_format='tar.gz', create_dir=True) with open(os.path.join(self.path, 'detections', 'coco_2014_' + self.dataset_sets[self.split] + '_FRCN_train.pkl'), 'rb') as f: dets_default = pickle.load(f, encoding='latin1') - annots = COCO(annotation_file=os.path.join(self.path, 'annotations', 'instances_' + imgs_split + '.json')) + annots = COCO(annotation_file=os.path.join(self.path, 'annotations', 'instances_' + + self.dataset_sets[self.split] + '2014.json')) pbarDesc = "Overall progress" pbar = tqdm(desc=pbarDesc, total=len(dets_default[1])) for i in range(len(dets_default[1])): @@ -374,7 +281,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, nms_topk=6000, post_nms=6000) bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) - if bboxes_list.shape[0] > 0: + if bboxes_list.shape[0]>0: bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] if bboxes_list.shape[0] > 0: bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] @@ -388,7 +295,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic for j in range(len(annots_in_frame)): gt_boxes.append(annots_in_frame[j]['bbox']) gt_boxes = np.asarray(np.asarray(gt_boxes)) - if gt_boxes.shape[0] > 0: + if gt_boxes.shape[0]>0: gt_boxes[:, 2] = gt_boxes[:, 0] + gt_boxes[:, 2] gt_boxes[:, 3] = gt_boxes[:, 1] + gt_boxes[:, 3] self.src_data.append({ @@ -407,6 +314,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic self.src_data = pickle.load(fp_pkl) self.classes = ['background', 'person'] self.class_ids = [-1, 1] + self.annotation_file = 'instances_' + self.dataset_sets[self.split] + '2014.json' @staticmethod def download( From 6e8890bc773484d2a271318471f4f87caa67a2c8 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 13:40:14 +0200 Subject: [PATCH 114/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index b4b99f000f..ea8147b7a8 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -236,7 +236,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) if not os.path.exists(os.path.join(self.path, imgs_split)): - self.download('http://images.cocodataset.org/zips/' + imgs_split +'.zip', + self.download('http://images.cocodataset.org/zips/' + imgs_split + '.zip', download_path=os.path.join(self.path), file_format="zip", create_dir=True) pkl_filename = os.path.join(self.path, 'data_' + self.detector + '_' + @@ -281,7 +281,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic bboxes_list = ssd.infer(img, threshold=0.0, custom_nms=None, nms_thresh=0.975, nms_topk=6000, post_nms=6000) bboxes_list = BoundingBoxListToNumpyArray()(bboxes_list) - if bboxes_list.shape[0]>0: + if bboxes_list.shape[0] > 0: bboxes_list = bboxes_list[bboxes_list[:, 4] > 0.015] if bboxes_list.shape[0] > 0: bboxes_list = bboxes_list[np.argsort(bboxes_list[:, 4]), :][::-1] @@ -295,7 +295,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic for j in range(len(annots_in_frame)): gt_boxes.append(annots_in_frame[j]['bbox']) gt_boxes = np.asarray(np.asarray(gt_boxes)) - if gt_boxes.shape[0]>0: + if gt_boxes.shape[0] > 0: gt_boxes[:, 2] = gt_boxes[:, 0] + gt_boxes[:, 2] gt_boxes[:, 3] = gt_boxes[:, 1] + gt_boxes[:, 3] self.src_data.append({ From f1e4c642a56efef9cd0e1ee6a3ba978435438cd0 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 13:40:34 +0200 Subject: [PATCH 115/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 43b2fa6fa4..025a44be92 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -35,7 +35,7 @@ from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS -import gc + class Seq2SeqNMSLearner(Learner, NMSCustom): def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', checkpoint_after_iter=0, @@ -52,8 +52,8 @@ def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', check self.use_app_feats = False if self.app_feats is not None: self.use_app_feats = True - self.fmod_map_type=None - self.fmod_map_bin=None + self.fmod_map_type = None + self.fmod_map_bin = None self.fmod_map_res_dim = None self.fmod_pyramid_lvl = None self.fmod_roi_pooling_dim = None @@ -195,6 +195,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, dt_boxes = dt_boxes[dt_scores_ids] else: pbar.update(1) + num_iter = num_iter + 1 continue gt_boxes = torch.tensor([]).float() if len(dataset_nms.src_data[sample_id]['gt_boxes'][class_index]) > 0: @@ -215,6 +216,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, dt_boxes, dt_scores = drop_dets(dt_boxes, dt_scores) if dt_boxes.shape[0] < 1: pbar.update(1) + num_iter = num_iter + 1 continue if self.iou_filtering is not None and 1.0 > self.iou_filtering > 0: dt_boxes, dt_scores = apply_torchNMS(boxes=dt_boxes, scores=dt_scores, @@ -302,7 +304,7 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, self.classes = dataset_nms.classes self.class_ids = dataset_nms.class_ids - annotations_filename = str.lower(dataset) + '_' + split + '.json' + annotations_filename = dataset_nms.annotation_file eval_folder = os.path.join(self.parent_dir, self.experiment_name, 'eval') if not os.path.isdir(os.path.join(self.parent_dir, self.experiment_name)): From 39ff38b0e4a886f40696133cbf321f8e063569ca Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 13:46:47 +0200 Subject: [PATCH 116/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index ea8147b7a8..47fa5c0817 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -32,7 +32,7 @@ class Dataset_NMS(Dataset): def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, device='cuda'): super().__init__() - available_dataset = ['COCO', 'PETS',] + available_dataset = ['COCO', 'PETS'] self.dataset_sets = {'train': None, 'val': None, 'test': None} From 82e585b8640b869dbfb31d2036a0175d1e0f0851 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 14:24:09 +0200 Subject: [PATCH 117/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 025a44be92..fc06f9b83e 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -186,6 +186,18 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, pbar = tqdm(desc=pbarDesc, total=len(train_ids)) np.random.shuffle(train_ids) for sample_id in train_ids: + + if self.log_after != 0 and num_iter>0 and num_iter % self.log_after == 0: + if logging: + file_writer.add_scalar(tag="cross_entropy_loss", + scalar_value=total_loss_iter/self.log_after, + global_step=num_iter) + if verbose: + print(''.join(['\nEpoch: {}', + ' Iter: {}, cross_entropy_loss: {}']).format(epoch, num_iter, + total_loss_iter/self.log_after)) + total_loss_iter = 0 + image_fln = dataset_nms.src_data[sample_id]['filename'] if len(dataset_nms.src_data[sample_id]['dt_boxes'][class_index]) > 0: dt_boxes = torch.tensor( @@ -266,16 +278,6 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, total_loss_iter = total_loss_iter + loss_t total_loss_epoch = total_loss_epoch + loss_t num_iter = num_iter + 1 - if self.log_after != 0 and num_iter % self.log_after == 0: - if logging: - file_writer.add_scalar(tag="cross_entropy_loss", - scalar_value=total_loss_iter/self.log_after, - global_step=num_iter) - if verbose: - print(''.join(['\nEpoch: {}', - ' Iter: {}, cross_entropy_loss: {}']).format(epoch, num_iter, - total_loss_iter/self.log_after)) - total_loss_iter = 0 if not silent: pbar.update(1) if not silent: From 0f955d892ad10cc87a883a4b4cd1e631533643ba Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 14:52:57 +0200 Subject: [PATCH 118/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index fc06f9b83e..41ffee8166 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -187,7 +187,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, np.random.shuffle(train_ids) for sample_id in train_ids: - if self.log_after != 0 and num_iter>0 and num_iter % self.log_after == 0: + if self.log_after != 0 and num_iter > 0 and (num_iter+2) % self.log_after == 0: if logging: file_writer.add_scalar(tag="cross_entropy_loss", scalar_value=total_loss_iter/self.log_after, From 818af311f19723ff5a40007a9fd472c49bfa00cb Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 14:58:45 +0200 Subject: [PATCH 119/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 41ffee8166..7aeb2afbf1 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -39,7 +39,7 @@ class Seq2SeqNMSLearner(Learner, NMSCustom): def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', checkpoint_after_iter=0, - checkpoint_load_iter=0, log_after=10000, variant='medium', experiment_name='default', + checkpoint_load_iter=0, log_after=100, variant='medium', experiment_name='default', iou_filtering=0.8, dropout=0.05, pretrained_demo_model=None, app_feats='fmod', fmod_map_type='EDGEMAP', fmod_map_bin=True, app_input_dim=None): super(Seq2SeqNMSLearner, self).__init__(lr=lr, batch_size=1, @@ -187,7 +187,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, np.random.shuffle(train_ids) for sample_id in train_ids: - if self.log_after != 0 and num_iter > 0 and (num_iter+2) % self.log_after == 0: + if self.log_after != 0 and (num_iter ) > 0 and (num_iter ) % self.log_after == 0: if logging: file_writer.add_scalar(tag="cross_entropy_loss", scalar_value=total_loss_iter/self.log_after, @@ -206,7 +206,8 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) dt_boxes = dt_boxes[dt_scores_ids] else: - pbar.update(1) + if not silent: + pbar.update(1) num_iter = num_iter + 1 continue gt_boxes = torch.tensor([]).float() @@ -227,7 +228,8 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, dt_boxes, dt_scores = drop_dets(dt_boxes, dt_scores) if dt_boxes.shape[0] < 1: - pbar.update(1) + if not silent: + pbar.update(1) num_iter = num_iter + 1 continue if self.iou_filtering is not None and 1.0 > self.iou_filtering > 0: From 6c76ee1b751a1a507a7742dfb801fa16838057ce Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 14:59:10 +0200 Subject: [PATCH 120/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 7aeb2afbf1..b75c4242c0 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -39,7 +39,7 @@ class Seq2SeqNMSLearner(Learner, NMSCustom): def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', checkpoint_after_iter=0, - checkpoint_load_iter=0, log_after=100, variant='medium', experiment_name='default', + checkpoint_load_iter=0, log_after=10000, variant='medium', experiment_name='default', iou_filtering=0.8, dropout=0.05, pretrained_demo_model=None, app_feats='fmod', fmod_map_type='EDGEMAP', fmod_map_bin=True, app_input_dim=None): super(Seq2SeqNMSLearner, self).__init__(lr=lr, batch_size=1, From f0e4a99679303994a4f10e0f71d233d3cb962a6b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 15:19:57 +0200 Subject: [PATCH 121/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index b75c4242c0..a2f420d7aa 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -39,7 +39,7 @@ class Seq2SeqNMSLearner(Learner, NMSCustom): def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', checkpoint_after_iter=0, - checkpoint_load_iter=0, log_after=10000, variant='medium', experiment_name='default', + checkpoint_load_iter=0, log_after=100, variant='medium', experiment_name='default', iou_filtering=0.8, dropout=0.05, pretrained_demo_model=None, app_feats='fmod', fmod_map_type='EDGEMAP', fmod_map_bin=True, app_input_dim=None): super(Seq2SeqNMSLearner, self).__init__(lr=lr, batch_size=1, @@ -187,7 +187,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, np.random.shuffle(train_ids) for sample_id in train_ids: - if self.log_after != 0 and (num_iter ) > 0 and (num_iter ) % self.log_after == 0: + if self.log_after != 0 and num_iter > 0 and num_iter % self.log_after == 0: if logging: file_writer.add_scalar(tag="cross_entropy_loss", scalar_value=total_loss_iter/self.log_after, From 43b28a474399b4851d76aa175dc2778ebc073229 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 15:20:46 +0200 Subject: [PATCH 122/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index a2f420d7aa..c510e689fb 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -39,7 +39,7 @@ class Seq2SeqNMSLearner(Learner, NMSCustom): def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', checkpoint_after_iter=0, - checkpoint_load_iter=0, log_after=100, variant='medium', experiment_name='default', + checkpoint_load_iter=0, log_after=10000, variant='medium', experiment_name='default', iou_filtering=0.8, dropout=0.05, pretrained_demo_model=None, app_feats='fmod', fmod_map_type='EDGEMAP', fmod_map_bin=True, app_input_dim=None): super(Seq2SeqNMSLearner, self).__init__(lr=lr, batch_size=1, From c281f03778a469cac63768dbc05b0afaaa9b41b8 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 16:57:07 +0200 Subject: [PATCH 123/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index c510e689fb..10eefbe899 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -11,8 +11,7 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. - - +import cv2.cv2 import torch import torch.nn.functional as F import pickle @@ -275,6 +274,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, optimizer.zero_grad() loss.backward() optimizer.step() + # Memory leak if not loss not detached in total_loss_iter and total_loss_epoch computations loss_t = loss.detach().cpu().numpy() total_loss_iter = total_loss_iter + loss_t From cc311cb6e8ff3631d3329acbddb5ab7ec60476ba Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 16:57:22 +0200 Subject: [PATCH 124/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 47fa5c0817..62537e0bab 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -25,7 +25,6 @@ from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.engine.data import Image from opendr.perception.object_detection_2d.datasets.transforms import BoundingBoxListToNumpyArray -import json from pycocotools.coco import COCO @@ -290,7 +289,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], bboxes_list[b, 3], bboxes_list[b, 4][0]])) dt_boxes = np.asarray(dt_boxes) - annots_in_frame = annots.loadAnns(annots.getAnnIds(imgIds=[dets_default[1][i]], iscrowd=False)) + annots_in_frame = annots.loadAnns(annots.getAnnIds(imgIds=[dets_default[1][i]], catIds=[1], iscrowd=False)) gt_boxes = [] for j in range(len(annots_in_frame)): gt_boxes.append(annots_in_frame[j]['bbox']) From 231e3bc21bff4f31d5de75d6a5e8dfb29288ca26 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 17:02:04 +0200 Subject: [PATCH 125/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 10eefbe899..84a97bbe59 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -11,7 +11,6 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -import cv2.cv2 import torch import torch.nn.functional as F import pickle From 1a8091d0584a7558ea09747326a6f19e2a9c6872 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 11 Mar 2022 17:21:54 +0200 Subject: [PATCH 126/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 62537e0bab..97c6834825 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -1,3 +1,5 @@ +# Copyright 2020-2022 OpenDR European Project +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at From 61e188d1de9fc46e940ba1ec3dcbe11220781cf2 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 12 Mar 2022 15:37:50 +0200 Subject: [PATCH 127/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 97c6834825..1f0eb50781 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. - from opendr.engine.datasets import Dataset import os from urllib.request import urlretrieve From a1bec71f82f103ce2d52e96ba6a0f8bc1ed7c23a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 12 Mar 2022 15:38:02 +0200 Subject: [PATCH 128/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 84a97bbe59..407fd8a381 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -361,6 +361,7 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, dt_scores, dt_scores_ids = torch.sort(dt_scores, descending=True) dt_boxes = dt_boxes[dt_scores_ids] else: + pbar_eval.update(1) continue if self.device == "cuda": From ba81d8cf570c78d8bbcee2580dab1b5b3cb2e643 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 14 Mar 2022 11:05:08 +0200 Subject: [PATCH 129/374] Update nms_dataset.py --- .../nms/utils/nms_dataset.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 1f0eb50781..8e739991ba 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -32,7 +32,7 @@ class Dataset_NMS(Dataset): def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, device='cuda'): super().__init__() - available_dataset = ['COCO', 'PETS'] + available_dataset = ['COCO', 'PETS', 'TEST_MODULE'] self.dataset_sets = {'train': None, 'val': None, 'test': None} @@ -315,6 +315,22 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic self.classes = ['background', 'person'] self.class_ids = [-1, 1] self.annotation_file = 'instances_' + self.dataset_sets[self.split] + '2014.json' + elif self.dataset_name == "TEST_MODULE": + self.dataset_sets['train'] = 'test' + self.dataset_sets['val'] = 'test' + self.dataset_sets['test'] = 'test' + if self.dataset_sets[self.split] is None: + raise ValueError(self.split + ' split is not available...') + pkl_filename = os.path.join(self.path, 'test_module.pkl') + if not os.path.exists(pkl_filename): + data_url = '***.zip' + self.download(data_url, download_path=os.path.join(self.path), file_format="zip", + create_dir=True) + with open(pkl_filename, 'rb') as fp_pkl: + self.src_data = pickle.load(fp_pkl) + self.classes = ['background', 'person'] + self.class_ids = [-1, 1] + self.annotation_file = 'test_module_anns.json' @staticmethod def download( From 0d394f81d66887a3e6b97b54dce44304b87bb35b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 14 Mar 2022 11:10:44 +0200 Subject: [PATCH 130/374] Update nms_dataset.py --- .../object_detection_2d/nms/utils/nms_dataset.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 8e739991ba..c658c344dc 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -13,6 +13,11 @@ # limitations under the License. from opendr.engine.datasets import Dataset +from opendr.perception.object_detection_2d import SingleShotDetectorLearner +from opendr.engine.data import Image +from opendr.perception.object_detection_2d.datasets.transforms import BoundingBoxListToNumpyArray +from opendr.engine.constants import OPENDR_SERVER_URL +from pycocotools.coco import COCO import os from urllib.request import urlretrieve import ssl @@ -23,11 +28,6 @@ import numpy as np import math from tqdm import tqdm -from opendr.perception.object_detection_2d import SingleShotDetectorLearner -from opendr.engine.data import Image -from opendr.perception.object_detection_2d.datasets.transforms import BoundingBoxListToNumpyArray -from pycocotools.coco import COCO - class Dataset_NMS(Dataset): def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, device='cuda'): @@ -323,7 +323,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic raise ValueError(self.split + ' split is not available...') pkl_filename = os.path.join(self.path, 'test_module.pkl') if not os.path.exists(pkl_filename): - data_url = '***.zip' + data_url = OPENDR_SERVER_URL + '/perception/object_detection_2d/nms/datasets/test_module.zip' self.download(data_url, download_path=os.path.join(self.path), file_format="zip", create_dir=True) with open(pkl_filename, 'rb') as fp_pkl: From 70294ce2b21d8ec942da08e610325a0bb72858e1 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 14 Mar 2022 11:28:19 +0200 Subject: [PATCH 131/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index c658c344dc..8ca601ce6e 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -250,7 +250,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic self.download(ann_url, download_path=os.path.join(self.path), file_format="zip", create_dir=True) else: - if self.dataset_sets[self.split] == 'val': + if self.dataset_sets[self.split] == 'minival': ann_url = 'https://dl.dropboxusercontent.com/s/o43o90bna78omob/' \ 'instances_minival2014.json.zip?dl=0' else: From f253ec5ce94589a5b71be4f566669bcdf01961cb Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 11:37:33 +0200 Subject: [PATCH 132/374] Add files via upload --- .../object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py | 3 +-- .../nms/seq2seq_nms/algorithm/seq2seq_model.py | 4 +--- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py index aa25d28383..aee4f2f8aa 100755 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py @@ -1,5 +1,4 @@ -# Copyright 2020-2022 OpenDR European Project -# + # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py index 275827fbce..f41a9ba50b 100755 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py @@ -1,5 +1,4 @@ -# Copyright 2020-2022 OpenDR European Project -# + # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -183,7 +182,6 @@ def forward(self, q, k, v, mask=None): q = torch.matmul(scores, v) q = q.transpose(1, 2).contiguous().view(samples_dim, -1, self.s_dim) q = self.q_out(q) - return q From f3a42c1202fad435c6dbdd988b59cfe30d1b3a47 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 11:38:10 +0200 Subject: [PATCH 133/374] Add files via upload --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 119 +++++++----------- 1 file changed, 45 insertions(+), 74 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 407fd8a381..caf7b55f98 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -11,13 +11,22 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + +from opendr.engine.learners import Learner +from opendr.engine.constants import OPENDR_SERVER_URL +from opendr.engine.target import BoundingBox, BoundingBoxList +from opendr.engine.data import Image +from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet +from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.fmod import FMoD +from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ + run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS import torch import torch.nn.functional as F import pickle import numpy as np import os -from opendr.engine.learners import Learner -from opendr.engine.constants import OPENDR_SERVER_URL from urllib.request import urlretrieve import torch.nn as nn from tensorboardX import SummaryWriter @@ -25,20 +34,13 @@ from tqdm import tqdm import collections import json -from opendr.engine.target import BoundingBox, BoundingBoxList -from opendr.engine.data import Image -from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet -from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.fmod import FMoD -from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom -from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ - run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS +import zipfile class Seq2SeqNMSLearner(Learner, NMSCustom): def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', checkpoint_after_iter=0, - checkpoint_load_iter=0, log_after=10000, variant='medium', experiment_name='default', - iou_filtering=0.8, dropout=0.05, pretrained_demo_model=None, app_feats='fmod', + checkpoint_load_iter=0, log_after=10000, variant='medium', + iou_filtering=0.8, dropout=0.05, app_feats='fmod', fmod_map_type='EDGEMAP', fmod_map_bin=True, app_input_dim=None): super(Seq2SeqNMSLearner, self).__init__(lr=lr, batch_size=1, checkpoint_after_iter=checkpoint_after_iter, @@ -81,13 +83,9 @@ def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', check self.geom_input_dim = 14 self.set_architecture() self.dropout = dropout - self.parent_dir = temp_path - if not os.path.isdir(self.parent_dir): - os.mkdir(self.parent_dir) - self.experiment_name = experiment_name - if not os.path.isdir(os.path.join(self.parent_dir, self.experiment_name)): - os.mkdir(os.path.join(self.parent_dir, self.experiment_name)) - self.pretrained_demo_model = pretrained_demo_model + self.temp_path = temp_path + if not os.path.isdir(self.temp_path): + os.mkdir(self.temp_path) self.checkpoint_load_iter = checkpoint_load_iter self.log_after = log_after self.iou_filtering = iou_filtering @@ -99,6 +97,9 @@ def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', check self.fMoD = FMoD(roi_pooling_dim=self.fmod_roi_pooling_dim, pyramid_depth=self.fmod_pyramid_lvl, resize_dim=self.fmod_map_res_dim, map_type=self.fmod_map_type, map_bin=self.fmod_map_bin, device=self.device) + self.init_model() + if self.device == 'cuda': + self.model = self.model.cuda() def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, verbose=True, nms_gt_iou=0.5, max_dt_boxes=400, datasets_folder='./datasets', @@ -116,27 +117,10 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, logging = False file_writer = None - if self.model is None: - self.init_model() - checkpoints_folder = os.path.join(self.parent_dir, self.experiment_name, 'checkpoints') + checkpoints_folder = os.path.join(self.temp_path, 'checkpoints') if self.checkpoint_after_iter != 0 and not os.path.exists(checkpoints_folder): os.makedirs(checkpoints_folder) - if self.pretrained_demo_model is not None: - self.download(path=self.temp_path, model_name=self.pretrained_demo_model, - verbose=verbose and not silent) - weights_path = None - if self.pretrained_demo_model == 'PETS': - weights_path = os.path.join(checkpoints_folder, self.pretrained_demo_model) - self.checkpoint_load_iter = 7 - elif self.pretrained_demo_model == 'COCO': - weights_path = os.path.join(checkpoints_folder, "seq2seq_coco.pth") - self.checkpoint_load_iter = '?' - self.load(path=weights_path, verbose=verbose) - elif self.checkpoint_load_iter != 0: - checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) - checkpoint_full_path = os.path.join(checkpoints_folder, checkpoint_name) - self.load(checkpoint_full_path) if not silent and verbose: print("Model trainable parameters:", self.count_parameters()) @@ -159,7 +143,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, self.fMoD.set_mean_std(mean_values=self.fmod_mean_std['mean'], std_values=self.fmod_mean_std['std']) start_epoch = 0 - drop_after_epoch = [4, 6] + drop_after_epoch = [5, 8] train_ids = np.arange(len(dataset_nms.src_data)) total_loss_iter = 0 @@ -167,11 +151,6 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, optimizer = optim.Adam(self.model.parameters(), lr=self.lr, betas=(0.9, 0.99), eps=1e-9) # HERE scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=drop_after_epoch, gamma=0.1) - if self.checkpoint_load_iter != 0: - checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) - checkpoint_full_path = os.path.join(checkpoints_folder, checkpoint_name) - self.load(checkpoint_full_path) - num_iter = 0 training_weights = compute_class_weights(pos_weights=[0.9, 0.1], max_dets=max_dt_boxes, dataset_nms=dataset_nms) # Single class NMS only. @@ -292,6 +271,9 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, snapshot_name = '{}/checkpoint_epoch_{}'.format(checkpoints_folder, epoch) self.save(path=snapshot_name, optimizer=optimizer, scheduler=scheduler, current_epoch=epoch, max_dt_boxes=max_dt_boxes) + snapshot_name_lw = '{}/last_weights'.format(checkpoints_folder) + self.save(path=snapshot_name_lw, optimizer=optimizer, scheduler=scheduler, + current_epoch=epoch, max_dt_boxes=max_dt_boxes) total_loss_epoch = 0 scheduler.step() if logging: @@ -309,23 +291,13 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, annotations_filename = dataset_nms.annotation_file - eval_folder = os.path.join(self.parent_dir, self.experiment_name, 'eval') - if not os.path.isdir(os.path.join(self.parent_dir, self.experiment_name)): - os.mkdir(os.path.join(self.parent_dir, self.experiment_name)) + eval_folder = os.path.join(self.temp_path, 'eval') + if not os.path.isdir(os.path.join(self.temp_path)): + os.mkdir(os.path.join(self.temp_path)) if not os.path.isdir(eval_folder): os.mkdir(eval_folder) output_file = os.path.join(eval_folder, 'detections.json') - if self.model is None and self.checkpoint_load_iter != 0: - self.init_model() - checkpoint_name = "checkpoint_epoch_" + str(self.checkpoint_load_iter) - checkpoint_folder = os.path.join(self.parent_dir, self.experiment_name, 'checkpoints') - checkpoint_full_path = os.path.join(checkpoint_folder, checkpoint_name) - self.load(path=checkpoint_full_path, verbose=verbose) - - elif self.model is None: - raise AttributeError("self.model is None. Please load a model or set checkpoint_load_iter.") - if self.app_feats == 'fmod': if self.fmod_mean_std is None: self.fmod_mean_std = self.load_FMoD_init_from_dataset(dataset=dataset, map_type=self.fmod_map_type, @@ -382,7 +354,7 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, if self.app_feats == 'fmod': img = Image.open(image_path) img = img.convert(format='channels_last', channel_order='bgr') - self.fMoD.extract_maps(img=img, augm=True) + self.fMoD.extract_maps(img=img, augm=False) app_feats = self.fMoD.extract_FMoD_feats(dt_boxes) app_feats = torch.unsqueeze(app_feats, dim=1) elif self.app_feats == 'zeros': @@ -421,6 +393,7 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, print(eval_result[i][0][2][1]) print(eval_result[i][0][3][1]) print('\n') + return eval_result def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoch=None, max_dt_boxes=400): path = path.split('.')[0] @@ -462,12 +435,16 @@ def init_model(self): def load(self, path, verbose=False): - model_name = os.path.basename(os.path.normpath(path)).split('.')[0] - dir_path = os.path.dirname(os.path.normpath(path)) + if os.path.isdir(path): + model_name = os.path.join(path, 'last_weights') + dir_path = path + else: + model_name = os.path.basename(os.path.normpath(path)).split('.')[0] + dir_path = os.path.dirname(os.path.normpath(path)) if verbose: print("Model name:", model_name, "-->", os.path.join(dir_path, model_name + ".json")) - with open(os.path.join(dir_path, model_name + ".json")) as f: + with open(os.path.join(dir_path, model_name + ".json"), encoding='utf-8-sig') as f: metadata = json.load(f) pth_path = os.path.join(dir_path, metadata["model_paths"][0]) if verbose: @@ -490,10 +467,7 @@ def load(self, path, verbose=False): raise e self.assign_params(metadata=metadata, verbose=verbose) - self.init_model() self.load_state(checkpoint) - if self.device == 'cuda': - self.model = self.model.cuda() if verbose: print("Loaded parameters and metadata.") return True @@ -586,8 +560,8 @@ def count_parameters(self): raise UserWarning("Model is not initialized, can't count trainable parameters.") return sum(p.numel() for p in self.model.parameters() if p.requires_grad) - def download(self, path=None, model_name='seq2seq_medium_pets_jpd_fmod_3', verbose=False, - url=OPENDR_SERVER_URL + "perception/object_detection_2d/nms/pretrained/"): + def download(self, path=None, model_name='seq2seq_pets_jpd', verbose=False, + url=OPENDR_SERVER_URL + "perception/object_detection_2d/nms/"): if path is None: path = self.temp_path @@ -595,18 +569,15 @@ def download(self, path=None, model_name='seq2seq_medium_pets_jpd_fmod_3', verbo if not os.path.exists(path): os.makedirs(path) - path = os.path.join(path, model_name) - if not os.path.exists(path): - os.makedirs(path) - if verbose: print("Downloading pretrained model...") - file_url_json = os.path.join(url, "pretrained", model_name + '.json') - file_url_pth = os.path.join(url, "pretrained", model_name + '.pth') + file_url = os.path.join(url, "pretrained", model_name + '.zip') try: - urlretrieve(file_url_json, os.path.join(path, model_name + '.json')) - urlretrieve(file_url_pth, os.path.join(path, model_name + '.pth')) + urlretrieve(file_url, os.path.join(path, model_name + '.zip')) + with zipfile.ZipFile(os.path.join(path, model_name + '.zip'), 'r') as zip_ref: + zip_ref.extractall(path) + os.remove(os.path.join(path, model_name + '.zip')) except: raise UserWarning('Pretrained model not found on server.') @@ -745,7 +716,7 @@ def compute_geometrical_feats(self, boxes, scores, resolution): scoresBs = scores.unsqueeze(0).unsqueeze(-1).repeat(scores.shape[0], 1, 1) scoresAs = scores.unsqueeze(1).unsqueeze(1).repeat(1, scores.shape[0], 1) - scale_div = [resolution[0] / 20, resolution[1] / 20] + scale_div = [resolution[1] / 20, resolution[0] / 20] dx = ((boxBs[:, :, 0] - boxAs[:, :, 0] + boxBs[:, :, 2] - boxAs[:, :, 2]) / 2).unsqueeze(-1) dy = ((boxBs[:, :, 1] - boxAs[:, :, 1] + boxBs[:, :, 3] - boxAs[:, :, 3]) / 2).unsqueeze(-1) dxy = dx * dx + dy * dy From ef447091fcf3c7c1f743713115caced03fac2474 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 11:52:50 +0200 Subject: [PATCH 134/374] Add files via upload --- .../nms/seq2seq_nms/test_seq2seq_nms.py | 141 ++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py new file mode 100644 index 0000000000..1324feaa83 --- /dev/null +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -0,0 +1,141 @@ +# Copyright 2020-2021 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import unittest +import gc +import shutil +import os +import numpy as np +from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner +from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS +from opendr.engine.data import Image + + +def rmfile(path): + try: + os.remove(path) + except OSError as e: + print("Error: %s - %s." % (e.filename, e.strerror)) + + +def rmdir(_dir): + try: + shutil.rmtree(_dir) + except OSError as e: + print("Error: %s - %s." % (e.filename, e.strerror)) + + +class TestSeq2SeqNMS(unittest.TestCase): + + + @classmethod + def setUpClass(cls): + print("\n\n**********************************\nTEST Seq2Seq-NMS Learner\n" + "**********************************") + + cls.temp_dir = os.path.join(".", "tests", "sources", "tools", "perception", "object_detection_2d", + "nms", "seq2seq_nms", "temp") + cls.seq2SeqNMSLearner = Seq2SeqNMSLearner(iou_filtering=None, app_feats='fmod', temp_path=cls.temp_dir, + device='cpu', checkpoint_after_iter=1, epochs=1) + + # Download all required files for testing + cls.seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd', path=cls.temp_dir) + @classmethod + def tearDownClass(cls): + print('Removing temporary directories for Seq2Seq-NMS...') + # Clean up downloaded files + rmfile(os.path.join(cls.temp_dir, "TEST-MODULE", "test_module.pkl")) + rmfile(os.path.join(cls.temp_dir, "TEST-MODULE", "val2014", "COCO_val2014_000000262148.jpg")) + rmfile(os.path.join(cls.temp_dir, "TEST-MODULE", "FMoD", "coco_edgemap_b_3.pkl")) + rmfile(os.path.join(cls.temp_dir, "TEST-MODULE", "annotations", "test_module_anns.json")) + rmdir(os.path.join(cls.temp_dir, "TEST-MODULE", "val2014")) + rmdir(os.path.join(cls.temp_dir, "TEST-MODULE", "FMoD")) + rmdir(os.path.join(cls.temp_dir, "TEST-MODULE", "val2014")) + + rmfile(os.path.join(cls.temp_dir, "seq2seq_pets_jpd", "fmod_normalization.pkl")) + rmfile(os.path.join(cls.temp_dir, "seq2seq_pets_jpd", "last_weights.json")) + rmfile(os.path.join(cls.temp_dir, "seq2seq_pets_jpd", "last_weights.pth")) + rmdir(os.path.join(cls.temp_dir, "seq2seq_pets_jpd")) + + rmdir(os.path.join(cls.temp_dir)) + + del cls.seq2SeqNMSLearner + gc.collect() + print('Finished cleaning for Seq2Seq-NMS...') + + def test_fit(self): + print('Starting training test for Seq2Seq-NMS...') + + m = list(self.seq2SeqNMSLearner.model.collect_params().values())[2].data().asnumpy().copy() + self.seq2SeqNMSLearner.fit(dataset='TEST-MODULE', use_ssd=False, + datasets_folder=self.temp_dir + '/datasets', + logging_path=None, silent=False, verbose=True, nms_gt_iou=0.50, + max_dt_boxes=200) + n = list(self.seq2SeqNMSLearner.model.collect_params().values())[2].data().asnumpy() + self.assertFalse(np.array_equal(m, n), + msg="Model parameters did not change after running fit.") + del m, n + gc.collect() + print('Finished training test for Seq2Seq-NMS...') + + def test_eval(self): + print('Starting evaluation test for Seq2Seq-NMS...') + self.seq2SeqNMSLearner.load(self.temp_dir + '/seq2seq_pets_jpd/', verbose=True) + results_dict = self.seq2SeqNMSLearner.eval(dataset='PETS', split='test', max_dt_boxes=800, + datasets_folder=self.temp_dir + '/datasets', + use_ssd=False) + if results_dict is None: + self.assertIsNotNone(results_dict, + msg="Eval results dictionary not returned.") + else: + self.assertGreater(results_dict[0][0][1][0], 0.58) + del results_dict + gc.collect() + print('Finished evaluation test for Seq2Seq-NMS...') + + def test_infer(self): + print('Starting inference test for Seq2Seq-NMS...') + self.seq2SeqNMSLearner.load(self.temp_dir + '/seq2seq_pets_jpd/', verbose=True) + + dataset_nms = Dataset_NMS(path=self.temp_dir + '/datasets', dataset_name='TEST-MODULE', split='train', use_ssd=False) + image_fln = dataset_nms.src_data[0]['filename'] + img = Image(image_fln) + boxes = dataset_nms.src_data[0]['dt_boxes'][1][:, 0:4] + scores = dataset_nms.src_data[0]['dt_boxes'][1][:, 4] + + bounding_box_list = self.seq2SeqNMSLearner.run_nms(boxes=boxes, scores=scores, img=img, threshold=0.5) + + self.assertIsNotNone(bounding_box_list, + msg="Returned empty BoundingBoxList.") + del img + del bounding_box_list + del boxes + del scores + del dataset_nms + gc.collect() + print('Finished inference test for SSD...') + + def test_save_load(self): + print('Starting save/load test for Seq2Seq-NMS...') + self.seq2SeqNMSLearner.save(os.path.join(self.temp_dir, "test_model"), current_epoch=0) + self.seq2SeqNMSLearner.model = None + self.seq2SeqNMSLearner.load(os.path.join(self.temp_dir, "test_model")) + self.assertIsNotNone(self.seq2SeqNMSLearner.model, "model is None after loading model.") + # Cleanup + rmdir(os.path.join(self.temp_dir, "test_model")) + print('Finished save/load test for Seq2Seq-NMS...') + + +if __name__ == "__main__": + unittest.main() From d10ff2028cc93448c007b494d4bf8ce15dce4239 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 13:55:43 +0200 Subject: [PATCH 135/374] Create __init__.py --- .../sources/tools/perception/object_detection_2d/nms/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/sources/tools/perception/object_detection_2d/nms/__init__.py diff --git a/tests/sources/tools/perception/object_detection_2d/nms/__init__.py b/tests/sources/tools/perception/object_detection_2d/nms/__init__.py new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/tests/sources/tools/perception/object_detection_2d/nms/__init__.py @@ -0,0 +1 @@ + From 4b5ba7c74046083480189d760cdf6d294d50efd1 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 13:56:08 +0200 Subject: [PATCH 136/374] Create __init__.py --- .../perception/object_detection_2d/nms/seq2seq_nms/__init__.py | 1 + 1 file changed, 1 insertion(+) create mode 100644 tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/__init__.py diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/__init__.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/__init__.py new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/__init__.py @@ -0,0 +1 @@ + From 18744a283bc3326f218a4ad496ad0dc10be8ed6c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 13:57:09 +0200 Subject: [PATCH 137/374] Add files via upload --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index caf7b55f98..3c04a6ce4c 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -121,7 +121,6 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, if self.checkpoint_after_iter != 0 and not os.path.exists(checkpoints_folder): os.makedirs(checkpoints_folder) - if not silent and verbose: print("Model trainable parameters:", self.count_parameters()) @@ -143,7 +142,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, self.fMoD.set_mean_std(mean_values=self.fmod_mean_std['mean'], std_values=self.fmod_mean_std['std']) start_epoch = 0 - drop_after_epoch = [5, 8] + drop_after_epoch = [4, 6] train_ids = np.arange(len(dataset_nms.src_data)) total_loss_iter = 0 From 3c46bf064f843b804269ee38ace0f4c529cf70c1 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 13:57:42 +0200 Subject: [PATCH 138/374] Add files via upload --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 8ca601ce6e..aabeebbe49 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -29,6 +29,7 @@ import math from tqdm import tqdm + class Dataset_NMS(Dataset): def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, device='cuda'): super().__init__() @@ -215,7 +216,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic self.classes = ['background', 'human'] self.class_ids = [-1, 1] - self.annotation_file = 'instances_' + self.dataset_sets[self.split] + '.json' + self.annotation_file = 'pets_' + self.dataset_sets[self.split] + '.json' elif self.dataset_name == "COCO": self.dataset_sets['train'] = 'train' self.dataset_sets['val'] = 'minival' @@ -290,7 +291,8 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic dt_boxes.append(np.array([bboxes_list[b, 0], bboxes_list[b, 1], bboxes_list[b, 2], bboxes_list[b, 3], bboxes_list[b, 4][0]])) dt_boxes = np.asarray(dt_boxes) - annots_in_frame = annots.loadAnns(annots.getAnnIds(imgIds=[dets_default[1][i]], catIds=[1], iscrowd=False)) + annots_in_frame = annots.loadAnns( + annots.getAnnIds(imgIds=[dets_default[1][i]], catIds=[1], iscrowd=False)) gt_boxes = [] for j in range(len(annots_in_frame)): gt_boxes.append(annots_in_frame[j]['bbox']) From 33e55b5a3dea4d4ac519341bbafef42a948914fb Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 13:58:28 +0200 Subject: [PATCH 139/374] Add files via upload --- .../nms/seq2seq_nms/test_seq2seq_nms.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index 1324feaa83..17236a1c0d 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -38,7 +38,6 @@ def rmdir(_dir): class TestSeq2SeqNMS(unittest.TestCase): - @classmethod def setUpClass(cls): print("\n\n**********************************\nTEST Seq2Seq-NMS Learner\n" @@ -51,6 +50,7 @@ def setUpClass(cls): # Download all required files for testing cls.seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd', path=cls.temp_dir) + @classmethod def tearDownClass(cls): print('Removing temporary directories for Seq2Seq-NMS...') @@ -79,9 +79,9 @@ def test_fit(self): m = list(self.seq2SeqNMSLearner.model.collect_params().values())[2].data().asnumpy().copy() self.seq2SeqNMSLearner.fit(dataset='TEST-MODULE', use_ssd=False, - datasets_folder=self.temp_dir + '/datasets', - logging_path=None, silent=False, verbose=True, nms_gt_iou=0.50, - max_dt_boxes=200) + datasets_folder=self.temp_dir + '/datasets', + logging_path=None, silent=False, verbose=True, nms_gt_iou=0.50, + max_dt_boxes=200) n = list(self.seq2SeqNMSLearner.model.collect_params().values())[2].data().asnumpy() self.assertFalse(np.array_equal(m, n), msg="Model parameters did not change after running fit.") @@ -97,7 +97,7 @@ def test_eval(self): use_ssd=False) if results_dict is None: self.assertIsNotNone(results_dict, - msg="Eval results dictionary not returned.") + msg="Eval results dictionary not returned.") else: self.assertGreater(results_dict[0][0][1][0], 0.58) del results_dict From 2df0505133d2980f0081ce03801c7acdb30e4663 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 14:02:09 +0200 Subject: [PATCH 140/374] Update __init__.py From 192a51448a8469abdddf9353a681e1c6c76c302d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 14:02:37 +0200 Subject: [PATCH 141/374] Update __init__.py From 4d998ba5275962e4f165f7d23b77b9d282975ea4 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 14:03:26 +0200 Subject: [PATCH 142/374] Update __init__.py From 04f30b0c3d02521a840e4e49627bc79ec880d154 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 14:03:39 +0200 Subject: [PATCH 143/374] Update __init__.py From 244591a78f18c187865d25ada60f2543b16abe23 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 14:18:01 +0200 Subject: [PATCH 144/374] Delete __init__.py --- .../sources/tools/perception/object_detection_2d/nms/__init__.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 tests/sources/tools/perception/object_detection_2d/nms/__init__.py diff --git a/tests/sources/tools/perception/object_detection_2d/nms/__init__.py b/tests/sources/tools/perception/object_detection_2d/nms/__init__.py deleted file mode 100644 index 8b13789179..0000000000 --- a/tests/sources/tools/perception/object_detection_2d/nms/__init__.py +++ /dev/null @@ -1 +0,0 @@ - From 4e293dcbed9105db831396599f33836b8b14be3e Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 14:18:12 +0200 Subject: [PATCH 145/374] Delete __init__.py --- .../perception/object_detection_2d/nms/seq2seq_nms/__init__.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/__init__.py diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/__init__.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/__init__.py deleted file mode 100644 index 8b13789179..0000000000 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/__init__.py +++ /dev/null @@ -1 +0,0 @@ - From ef46d4b91aa9f95fa4ee1aec71515be9adf1dea2 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 15:06:50 +0200 Subject: [PATCH 146/374] Update nms_utils.py --- .../nms/utils/nms_utils.py | 215 +++++++++++++----- 1 file changed, 157 insertions(+), 58 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py index 1dfc954a00..e0ceb7adb8 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py @@ -1,33 +1,13 @@ -# Copyright 2020-2022 OpenDR European Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - import torch +import torchvision +import numpy as np +from pycocotools.coco import COCO +from pycocotools.cocoeval import COCOeval +import sys +import os def jaccard(box_a, box_b, iscrowd: bool = False): - """Compute the jaccard overlap of two sets of boxes. The jaccard overlap - is simply the intersection over union of two boxes. Here we operate on - ground truth boxes and default boxes. If iscrowd=True, put the crowd in box_b. - E.g.: - A ∩ B / A ∪ B = A ∩ B / (area(A) + area(B) - A ∩ B) - Args: - box_a: (tensor) Ground truth bounding boxes, Shape: [num_objects,4] - box_b: (tensor) Prior boxes from priorbox layers, Shape: [num_priors,4] - Return: - jaccard overlap: (tensor) Shape: [box_a.size(0), box_b.size(0)] - """ use_batch = True if box_a.dim() == 2: use_batch = False @@ -46,16 +26,6 @@ def jaccard(box_a, box_b, iscrowd: bool = False): def intersect(box_a, box_b): - """ We resize both tensors to [A,B,2] without new malloc: - [A,2] -> [A,1,2] -> [A,B,2] - [B,2] -> [1,B,2] -> [A,B,2] - Then we compute the area of intersect between box_a and box_b. - Args: - box_a: (tensor) bounding boxes, Shape: [n,A,4]. - box_b: (tensor) bounding boxes, Shape: [n,B,4]. - Return: - (tensor) intersection area, Shape: [n,A,B]. - """ n = box_a.size(0) A = box_a.size(1) B = box_b.size(1) @@ -67,17 +37,6 @@ def intersect(box_a, box_b): def diou(box_a, box_b, iscrowd: bool = False): - """Compute the jaccard overlap of two sets of boxes. The jaccard overlap - is simply the intersection over union of two boxes. Here we operate on - ground truth boxes and default boxes. If iscrowd=True, put the crowd in box_b. - E.g.: - A ∩ B / A ∪ B = A ∩ B / (area(A) + area(B) - A ∩ B) - Args: - box_a: (tensor) Ground truth bounding boxes, Shape: [num_objects,4] - box_b: (tensor) Prior boxes from priorbox layers, Shape: [num_priors,4] - Return: - jaccard overlap: (tensor) Shape: [box_a.size(0), box_b.size(0)] - """ use_batch = True if box_a.dim() == 2: use_batch = False @@ -114,17 +73,6 @@ def diou(box_a, box_b, iscrowd: bool = False): def distance(box_a, box_b, iscrowd: bool = False): - """Compute the jaccard overlap of two sets of boxes. The jaccard overlap - is simply the intersection over union of two boxes. Here we operate on - ground truth boxes and default boxes. If iscrowd=True, put the crowd in box_b. - E.g.: - A ∩ B / A ∪ B = A ∩ B / (area(A) + area(B) - A ∩ B) - Args: - box_a: (tensor) Ground truth bounding boxes, Shape: [num_objects,4] - box_b: (tensor) Prior boxes from priorbox layers, Shape: [num_priors,4] - Return: - jaccard overlap: (tensor) Shape: [box_a.size(0), box_b.size(0)] - """ use_batch = True if box_a.dim() == 2: use_batch = False @@ -154,3 +102,154 @@ def distance(box_a, box_b, iscrowd: bool = False): D = (((x2 - x1) ** 2 + (y2 - y1) ** 2) / ((cr - cl) ** 2 + (cb - ct) ** 2 + 1e-7)) ** 0.6 out = D if iscrowd else D return out if use_batch else out.squeeze(0) + + +def det_matching(scores, dt_boxes, gt_boxes, iou_thres, device='cuda'): + sorted_indices = torch.argsort(-scores, dim=0) + labels = torch.zeros(len(dt_boxes)) + if device == 'cuda': + labels = labels.cuda() + if gt_boxes.shape[0] == 0: + return labels.unsqueeze(-1) + assigned_GT = -torch.ones(len(gt_boxes)) + r = torch.tensor([-1, -1, -1, -1]).float().unsqueeze(0).unsqueeze(0) + if device == 'cuda': + r = r.cuda() + for s in sorted_indices: + gt_boxes_c = gt_boxes.clone().unsqueeze(0) + gt_boxes_c[0, assigned_GT > -1, :] = r + ious = bb_intersection_over_union(boxAs=dt_boxes[s].clone().unsqueeze(0), boxBs=gt_boxes_c) + annot_iou, annot_box_id = torch.sort(ious.squeeze(), descending=True) + if annot_box_id.ndim > 0: + annot_box_id = annot_box_id[0] + annot_iou = annot_iou[0] + if annot_iou > iou_thres: + assigned_GT[annot_box_id] = s + labels[s] = 1 + return labels.unsqueeze(-1) + + +def run_coco_eval(dt_file_path=None, gt_file_path=None, only_classes=None, max_dets=None, + verbose=False): + if max_dets is None: + max_dets = [200, 400, 600, 800, 1000, 1200] + results = [] + sys.stdout = open(os.devnull, 'w') + for i in range(len(max_dets)): + coco = COCO(gt_file_path) + coco_dt = coco.loadRes(dt_file_path) + cocoEval = COCOeval(coco, coco_dt, 'bbox') + cocoEval.params.iouType = 'bbox' + cocoEval.params.useCats = True + cocoEval.params.catIds = only_classes + cocoEval.params.maxDets = [max_dets[i]] + cocoEval.evaluate() + results.append([summarize_nms(coco_eval=cocoEval, maxDets=max_dets[i]), max_dets[i]]) + # print(results[i]) + del cocoEval, coco_dt, coco + sys.stdout = sys.__stdout__ + return results + + +def summarize_nms(coco_eval=None, maxDets=100): + def summarize(ap=1, iouThr=None, areaRng='all', maxDets=100): + p = coco_eval.params + iStr = ' {:<18} {} @[ IoU={:<9} | area={:>6s} | maxDets={:>3d} ] = {:0.3f}' + titleStr = 'Average Precision' if ap == 1 else 'Average Recall' + typeStr = '(AP)' if ap == 1 else '(AR)' + iouStr = '{:0.2f}:{:0.2f}'.format(p.iouThrs[0], p.iouThrs[-1]) \ + if iouThr is None else '{:0.2f}'.format(iouThr) + aind = [i for i, aRng in enumerate(p.areaRngLbl) if aRng == areaRng] + mind = [i for i, mDet in enumerate(p.maxDets) if mDet == maxDets] + if ap == 1: + # dimension of precision: [TxRxKxAxM] + s = coco_eval.eval['precision'] + # IoU + if iouThr is not None: + t = np.where(iouThr == p.iouThrs)[0] + s = s[t] + s = s[:, :, :, aind, mind] + else: + # dimension of recall: [TxKxAxM] + s = coco_eval.eval['recall'] + if iouThr is not None: + t = np.where(iouThr == p.iouThrs)[0] + s = s[t] + s = s[:, :, aind, mind] + if len(s[s > -1]) == 0: + mean_s = -1 + else: + mean_s = np.mean(s[s > -1]) + stat_str = iStr.format(titleStr, typeStr, iouStr, areaRng, maxDets, mean_s) + return [mean_s, stat_str] + + def summarizeDets(): + stats = [] + stat, stat_str = summarize(1, maxDets=maxDets) + stats.append([stat, stat_str]) + stat, stat_str = summarize(1, iouThr=.5, maxDets=maxDets) + stats.append([stat, stat_str]) + stat, stat_str = summarize(1, iouThr=.75, maxDets=maxDets) + stats.append([stat, stat_str]) + stat, stat_str = summarize(0, maxDets=maxDets) + stats.append([stat, stat_str]) + return stats + + coco_eval.accumulate() + summarized = summarizeDets() + return summarized + + +def drop_dets(boxes, scores, keep_ratio=0.85): + ids = np.arange(len(boxes)) + np.random.shuffle(ids) + ids_keep = ids[0:int(len(boxes) * keep_ratio)] + boxes_new = boxes[ids_keep, :] + scores_new = scores[ids_keep] + return boxes_new, scores_new + + +def filter_iou_boxes(boxes=None, iou_thres=0.2): + ious = bb_intersection_over_union(boxes.unsqueeze(1).repeat(1, boxes.shape[0], 1), + boxes.clone().unsqueeze(0).repeat(boxes.shape[0], 1, 1)) + ids_boxes = ious >= iou_thres + return ids_boxes + + +def bb_intersection_over_union(boxAs=None, boxBs=None): + xA = torch.maximum(boxAs[:, :, 0], boxBs[:, :, 0]) + yA = torch.maximum(boxAs[:, :, 1], boxBs[:, :, 1]) + xB = torch.minimum(boxAs[:, :, 2], boxBs[:, :, 2]) + yB = torch.minimum(boxAs[:, :, 3], boxBs[:, :, 3]) + interAreas = torch.maximum(torch.zeros_like(xB), xB - xA + 1) * torch.maximum(torch.zeros_like(yB), yB - yA + 1) + boxAAreas = (boxAs[:, :, 2] - boxAs[:, :, 0] + 1) * (boxAs[:, :, 3] - boxAs[:, :, 1] + 1) + boxBAreas = (boxBs[:, :, 2] - boxBs[:, :, 0] + 1) * (boxBs[:, :, 3] - boxBs[:, :, 1] + 1) + ious = interAreas / (boxAAreas + boxBAreas - interAreas) + return ious + + +def compute_class_weights(pos_weights, max_dets=400, dataset_nms=None): + num_pos = np.ones([len(dataset_nms.classes), 1]) + num_bg = np.ones([len(dataset_nms.classes), 1]) + weights = np.zeros([len(dataset_nms.classes), 2]) + for i in range(len(dataset_nms.src_data)): + for cls_index in range(len(dataset_nms.classes)): + num_pos[cls_index] = num_pos[cls_index] + \ + min(max_dets, len(dataset_nms.src_data[i]['gt_boxes'][cls_index])) + num_bg[cls_index] = num_bg[cls_index] + max(0, min(max_dets, + len(dataset_nms.src_data[i]['dt_boxes'][cls_index])) - + min(max_dets, + len(dataset_nms.src_data[i]['gt_boxes'][cls_index]))) + for class_index in range(len(dataset_nms.classes)): + weights[class_index, 0] = (1 - pos_weights[class_index]) * (num_pos[class_index] + + num_bg[class_index]) / num_bg[class_index] + weights[class_index, 1] = pos_weights[class_index] * (num_pos[class_index] + + num_bg[class_index]) / num_pos[class_index] + return weights + + +def apply_torchNMS(boxes, scores, iou_thres): + ids_nms = torchvision.ops.nms(boxes, scores, iou_thres) + scores = scores[ids_nms] + boxes = boxes[ids_nms] + return boxes, scores From 764ef82f01058fb42d5f66886b8ea2633d9dd6bb Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 15:15:44 +0200 Subject: [PATCH 147/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 3c04a6ce4c..9bd47a006f 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -435,7 +435,7 @@ def init_model(self): def load(self, path, verbose=False): if os.path.isdir(path): - model_name = os.path.join(path, 'last_weights') + model_name = 'last_weights' dir_path = path else: model_name = os.path.basename(os.path.normpath(path)).split('.')[0] From db37f6facf04bd20425c412bddd69f8df3bb4ff0 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 15:19:29 +0200 Subject: [PATCH 148/374] Update test_seq2seq_nms.py --- .../object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index 17236a1c0d..2ef02ee376 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -92,7 +92,7 @@ def test_fit(self): def test_eval(self): print('Starting evaluation test for Seq2Seq-NMS...') self.seq2SeqNMSLearner.load(self.temp_dir + '/seq2seq_pets_jpd/', verbose=True) - results_dict = self.seq2SeqNMSLearner.eval(dataset='PETS', split='test', max_dt_boxes=800, + results_dict = self.seq2SeqNMSLearner.eval(dataset='TEST-MODULE', split='test', max_dt_boxes=800, datasets_folder=self.temp_dir + '/datasets', use_ssd=False) if results_dict is None: From 6928dd3cebf3b5a762636fc41b5516fcbe6fe9ca Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 15:36:35 +0200 Subject: [PATCH 149/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index aabeebbe49..24ac7a0f2f 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -326,7 +326,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic pkl_filename = os.path.join(self.path, 'test_module.pkl') if not os.path.exists(pkl_filename): data_url = OPENDR_SERVER_URL + '/perception/object_detection_2d/nms/datasets/test_module.zip' - self.download(data_url, download_path=os.path.join(self.path), file_format="zip", + self.download(data_url, download_path=os.path.join(self.path).replace("TEST_MODULE",""), file_format="zip", create_dir=True) with open(pkl_filename, 'rb') as fp_pkl: self.src_data = pickle.load(fp_pkl) From 6d7b2677d386316e013a14d85c39baf23b7c422d Mon Sep 17 00:00:00 2001 From: charsyme Date: Wed, 16 Mar 2022 18:46:52 +0200 Subject: [PATCH 150/374] tests --- .../object_detection_2d/nms/__init__.py | 0 .../nms/seq2seq_nms/__init__.py | 0 .../nms/seq2seq_nms/test_seq2seq_nms.py | 39 +++++++++---------- 3 files changed, 19 insertions(+), 20 deletions(-) create mode 100644 tests/sources/tools/perception/object_detection_2d/nms/__init__.py create mode 100644 tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/__init__.py diff --git a/tests/sources/tools/perception/object_detection_2d/nms/__init__.py b/tests/sources/tools/perception/object_detection_2d/nms/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/__init__.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index 2ef02ee376..2a119c5d1e 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -55,14 +55,12 @@ def setUpClass(cls): def tearDownClass(cls): print('Removing temporary directories for Seq2Seq-NMS...') # Clean up downloaded files - rmfile(os.path.join(cls.temp_dir, "TEST-MODULE", "test_module.pkl")) - rmfile(os.path.join(cls.temp_dir, "TEST-MODULE", "val2014", "COCO_val2014_000000262148.jpg")) - rmfile(os.path.join(cls.temp_dir, "TEST-MODULE", "FMoD", "coco_edgemap_b_3.pkl")) - rmfile(os.path.join(cls.temp_dir, "TEST-MODULE", "annotations", "test_module_anns.json")) - rmdir(os.path.join(cls.temp_dir, "TEST-MODULE", "val2014")) - rmdir(os.path.join(cls.temp_dir, "TEST-MODULE", "FMoD")) - rmdir(os.path.join(cls.temp_dir, "TEST-MODULE", "val2014")) - + rmfile(os.path.join(cls.temp_dir, "datasets", "TEST_MODULE", "test_module.pkl")) + rmfile(os.path.join(cls.temp_dir, "datasets", "TEST_MODULE", "val2014", "COCO_val2014_000000262148.jpg")) + rmfile(os.path.join(cls.temp_dir, "datasets", "TEST_MODULE", "FMoD", "coco_edgemap_b_3.pkl")) + rmfile(os.path.join(cls.temp_dir, "datasets", "TEST_MODULE", "annotations", "test_module_anns.json")) + rmdir(os.path.join(cls.temp_dir, "datasets", "TEST_MODULE", "val2014")) + rmdir(os.path.join(cls.temp_dir, "datasets", "TEST_MODULE", "FMoD")) rmfile(os.path.join(cls.temp_dir, "seq2seq_pets_jpd", "fmod_normalization.pkl")) rmfile(os.path.join(cls.temp_dir, "seq2seq_pets_jpd", "last_weights.json")) rmfile(os.path.join(cls.temp_dir, "seq2seq_pets_jpd", "last_weights.pth")) @@ -77,12 +75,12 @@ def tearDownClass(cls): def test_fit(self): print('Starting training test for Seq2Seq-NMS...') - m = list(self.seq2SeqNMSLearner.model.collect_params().values())[2].data().asnumpy().copy() - self.seq2SeqNMSLearner.fit(dataset='TEST-MODULE', use_ssd=False, + m = list(self.seq2SeqNMSLearner.model.parameters())[0].clone() + self.seq2SeqNMSLearner.fit(dataset='TEST_MODULE', use_ssd=False, datasets_folder=self.temp_dir + '/datasets', logging_path=None, silent=False, verbose=True, nms_gt_iou=0.50, max_dt_boxes=200) - n = list(self.seq2SeqNMSLearner.model.collect_params().values())[2].data().asnumpy() + n = list(self.seq2SeqNMSLearner.model.parameters())[0].clone() self.assertFalse(np.array_equal(m, n), msg="Model parameters did not change after running fit.") del m, n @@ -92,14 +90,14 @@ def test_fit(self): def test_eval(self): print('Starting evaluation test for Seq2Seq-NMS...') self.seq2SeqNMSLearner.load(self.temp_dir + '/seq2seq_pets_jpd/', verbose=True) - results_dict = self.seq2SeqNMSLearner.eval(dataset='TEST-MODULE', split='test', max_dt_boxes=800, + results_dict = self.seq2SeqNMSLearner.eval(dataset='TEST_MODULE', split='test', max_dt_boxes=800, datasets_folder=self.temp_dir + '/datasets', use_ssd=False) if results_dict is None: self.assertIsNotNone(results_dict, msg="Eval results dictionary not returned.") else: - self.assertGreater(results_dict[0][0][1][0], 0.58) + self.assertGreater(results_dict[0][0][1][0], 0.4) del results_dict gc.collect() print('Finished evaluation test for Seq2Seq-NMS...') @@ -107,12 +105,11 @@ def test_eval(self): def test_infer(self): print('Starting inference test for Seq2Seq-NMS...') self.seq2SeqNMSLearner.load(self.temp_dir + '/seq2seq_pets_jpd/', verbose=True) - - dataset_nms = Dataset_NMS(path=self.temp_dir + '/datasets', dataset_name='TEST-MODULE', split='train', use_ssd=False) + dataset_nms = Dataset_NMS(path=self.temp_dir + '/datasets', dataset_name='TEST_MODULE', split='train', use_ssd=False) image_fln = dataset_nms.src_data[0]['filename'] - img = Image(image_fln) + img = Image.open(os.path.join(self.temp_dir, 'datasets', 'TEST_MODULE', image_fln)) boxes = dataset_nms.src_data[0]['dt_boxes'][1][:, 0:4] - scores = dataset_nms.src_data[0]['dt_boxes'][1][:, 4] + scores = np.expand_dims(dataset_nms.src_data[0]['dt_boxes'][1][:, 4], axis=-1) bounding_box_list = self.seq2SeqNMSLearner.run_nms(boxes=boxes, scores=scores, img=img, threshold=0.5) @@ -124,13 +121,14 @@ def test_infer(self): del scores del dataset_nms gc.collect() - print('Finished inference test for SSD...') + print('Finished inference test for Seq2Seq-NMS...') def test_save_load(self): print('Starting save/load test for Seq2Seq-NMS...') - self.seq2SeqNMSLearner.save(os.path.join(self.temp_dir, "test_model"), current_epoch=0) + self.seq2SeqNMSLearner.save(os.path.join(self.temp_dir, "test_model", "checkpoints", "last_weights"), current_epoch=0) self.seq2SeqNMSLearner.model = None - self.seq2SeqNMSLearner.load(os.path.join(self.temp_dir, "test_model")) + self.seq2SeqNMSLearner.init_model() + self.seq2SeqNMSLearner.load(os.path.join(self.temp_dir, "test_model", 'checkpoints')) self.assertIsNotNone(self.seq2SeqNMSLearner.model, "model is None after loading model.") # Cleanup rmdir(os.path.join(self.temp_dir, "test_model")) @@ -139,3 +137,4 @@ def test_save_load(self): if __name__ == "__main__": unittest.main() + From 9bb4cfb40162834c09ece9ca4f0d887b79afd88a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 18:55:30 +0200 Subject: [PATCH 151/374] Update test_seq2seq_nms.py --- .../object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index 2a119c5d1e..f25e0ec744 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + import unittest import gc import shutil From 98cc30b6e0c484c6de1f7211399b8500b597a90b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 18:55:47 +0200 Subject: [PATCH 152/374] Update test_seq2seq_nms.py --- .../object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index f25e0ec744..2a119c5d1e 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. - import unittest import gc import shutil From f78c52b6faa59cdbbdb9f99a8e2763217aa00bd3 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 19:04:06 +0200 Subject: [PATCH 153/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 24ac7a0f2f..a4ea722319 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -326,7 +326,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic pkl_filename = os.path.join(self.path, 'test_module.pkl') if not os.path.exists(pkl_filename): data_url = OPENDR_SERVER_URL + '/perception/object_detection_2d/nms/datasets/test_module.zip' - self.download(data_url, download_path=os.path.join(self.path).replace("TEST_MODULE",""), file_format="zip", + self.download(data_url, download_path=os.path.join(self.path).replace("TEST_MODULE", ""), file_format="zip", create_dir=True) with open(pkl_filename, 'rb') as fp_pkl: self.src_data = pickle.load(fp_pkl) From 75736f9e8ffefddedfb7289166f9350562e64fd5 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 19:04:23 +0200 Subject: [PATCH 154/374] Update test_seq2seq_nms.py --- .../object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index 2a119c5d1e..38310f0e90 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -137,4 +137,3 @@ def test_save_load(self): if __name__ == "__main__": unittest.main() - From 3bed27fc1e16ab1699e264e6b040b77ea61c18e8 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 19:16:06 +0200 Subject: [PATCH 155/374] Update nms_utils.py --- .../object_detection_2d/nms/utils/nms_utils.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py index e0ceb7adb8..0d1d45e96c 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py @@ -1,3 +1,17 @@ +# Copyright 2020-2022 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + import torch import torchvision import numpy as np From 48767783eb611541343a3aa4bd32591346be72bb Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 21:22:44 +0200 Subject: [PATCH 156/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 9bd47a006f..0e8f6a1f9d 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -12,6 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. + from opendr.engine.learners import Learner from opendr.engine.constants import OPENDR_SERVER_URL from opendr.engine.target import BoundingBox, BoundingBoxList From 87238166824f28d598d58a8c358dff9f71424276 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 21:22:52 +0200 Subject: [PATCH 157/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 0e8f6a1f9d..9bd47a006f 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. - from opendr.engine.learners import Learner from opendr.engine.constants import OPENDR_SERVER_URL from opendr.engine.target import BoundingBox, BoundingBoxList From 1d25997b3984aecc24ed9da0132bf9dcfb5cc794 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 21:27:50 +0200 Subject: [PATCH 158/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 9bd47a006f..79c43548c0 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -396,8 +396,11 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoch=None, max_dt_boxes=400): path = path.split('.')[0] - custom_dict = {'state_dict': self.model.state_dict(), 'optimizer': optimizer.state_dict(), - 'scheduler': scheduler.state_dict(), 'current_epoch': current_epoch} + custom_dict = {'state_dict': self.model.state_dict(), 'current_epoch': current_epoch} + if optimizer is not None: + custom_dict['optimizer'] = optimizer.state_dict() + if scheduler is not None: + custom_dict['scheduler'] = scheduler.state_dict() torch.save(custom_dict, path + '.pth') metadata = {"model_paths": [os.path.basename(path) + '.pth'], "framework": "pytorch", "has_data": False, From 3d185950715a9d4e0eaed152f580b3fb2b99eb39 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 21:37:40 +0200 Subject: [PATCH 159/374] Update fmod.py --- .../object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py index aee4f2f8aa..aa25d28383 100755 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py @@ -1,4 +1,5 @@ - +# Copyright 2020-2022 OpenDR European Project +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at From 3ef887b09029f6652f070d921a05d404c52a99eb Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 21:38:02 +0200 Subject: [PATCH 160/374] Update seq2seq_model.py --- .../nms/seq2seq_nms/algorithm/seq2seq_model.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py index f41a9ba50b..9322937ced 100755 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py @@ -1,4 +1,5 @@ - +# Copyright 2020-2022 OpenDR European Project +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at @@ -11,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. - import torch.nn as nn import torch import math From 75b99d183b093b0546e0a48c2c6b28479f791ede Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 21:38:12 +0200 Subject: [PATCH 161/374] Update fmod.py --- .../object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py index aa25d28383..1c1cef8365 100755 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py @@ -12,7 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. - import torch import torchvision import numpy as np From 0e25a81d1488267882606f5f57c428bf36253283 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 22:19:03 +0200 Subject: [PATCH 162/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 79c43548c0..34c5e55fff 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -395,7 +395,10 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, return eval_result def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoch=None, max_dt_boxes=400): - path = path.split('.')[0] + fname = path.split('/')[-1] + dir_name = path.replace('/'+fname,'') + if not os.path.isdir(dir_name): + os.makedirs(dir_name) custom_dict = {'state_dict': self.model.state_dict(), 'current_epoch': current_epoch} if optimizer is not None: custom_dict['optimizer'] = optimizer.state_dict() @@ -403,7 +406,7 @@ def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoc custom_dict['scheduler'] = scheduler.state_dict() torch.save(custom_dict, path + '.pth') - metadata = {"model_paths": [os.path.basename(path) + '.pth'], "framework": "pytorch", "has_data": False, + metadata = {"model_paths": [fname + '.pth'], "framework": "pytorch", "has_data": False, "inference_params": {}, "optimized": False, "optimizer_info": {}, "backbone": {}, "format": "pth", "classes": self.classes, "app_feats": self.app_feats, "lq_dim": self.lq_dim, "sq_dim": self.sq_dim, "num_JPUs": self.num_JPUs, @@ -416,7 +419,7 @@ def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoc metadata["fmod_map_res_dim"] = self.fmod_map_res_dim metadata["fmod_pyramid_lvl"] = self.fmod_pyramid_lvl metadata["fmod_normalization"] = "fmod_normalization.pkl" - with open(os.path.join(os.path.dirname(path), 'fmod_normalization.pkl'), 'wb') as f: + with open(os.path.join(dir_name, 'fmod_normalization.pkl'), 'wb') as f: pickle.dump(self.fmod_mean_std, f) with open(path + '.json', 'w', encoding='utf-8') as f: json.dump(metadata, f, ensure_ascii=False, indent=4) @@ -436,7 +439,6 @@ def init_model(self): raise UserWarning("Tried to initialize model while model is already initialized.") def load(self, path, verbose=False): - if os.path.isdir(path): model_name = 'last_weights' dir_path = path @@ -473,7 +475,7 @@ def load(self, path, verbose=False): if verbose: print("Loaded parameters and metadata.") return True - + def assign_params(self, metadata, verbose): if verbose and self.variant is not None and self.variant != metadata["variant"]: From d3cc9dc302f59be6ffc10541fe37c425e15c1373 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 16 Mar 2022 22:25:11 +0200 Subject: [PATCH 163/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 34c5e55fff..a1b868090a 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -395,8 +395,8 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, return eval_result def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoch=None, max_dt_boxes=400): - fname = path.split('/')[-1] - dir_name = path.replace('/'+fname,'') + fname = path.split('/')[-1] + dir_name = path.replace('/' + fname, '') if not os.path.isdir(dir_name): os.makedirs(dir_name) custom_dict = {'state_dict': self.model.state_dict(), 'current_epoch': current_epoch} @@ -475,7 +475,7 @@ def load(self, path, verbose=False): if verbose: print("Loaded parameters and metadata.") return True - + def assign_params(self, metadata, verbose): if verbose and self.variant is not None and self.variant != metadata["variant"]: From ded32139d7b61d212e827eb67479c43a22ec2ab8 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 11:37:01 +0200 Subject: [PATCH 164/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index a1b868090a..653f4d00f9 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -40,7 +40,7 @@ class Seq2SeqNMSLearner(Learner, NMSCustom): def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', checkpoint_after_iter=0, checkpoint_load_iter=0, log_after=10000, variant='medium', - iou_filtering=0.8, dropout=0.05, app_feats='fmod', + iou_filtering=0.8, dropout=0.025, app_feats='fmod', fmod_map_type='EDGEMAP', fmod_map_bin=True, app_input_dim=None): super(Seq2SeqNMSLearner, self).__init__(lr=lr, batch_size=1, checkpoint_after_iter=checkpoint_after_iter, @@ -117,7 +117,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, logging = False file_writer = None - checkpoints_folder = os.path.join(self.temp_path, 'checkpoints') + checkpoints_folder = self.temp_path if self.checkpoint_after_iter != 0 and not os.path.exists(checkpoints_folder): os.makedirs(checkpoints_folder) @@ -240,7 +240,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, weights = (training_weights[class_index][1] * labels + training_weights[class_index][0] * ( 1 - labels)) - e = torch.distributions.uniform.Uniform(0.02, 0.0205).sample([labels.shape[0], 1]) + e = torch.distributions.uniform.Uniform(0.05, 0.055).sample([labels.shape[0], 1]) if self.device == 'cuda': weights = weights.cuda() e = e.cuda() @@ -290,7 +290,7 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, annotations_filename = dataset_nms.annotation_file - eval_folder = os.path.join(self.temp_path, 'eval') + eval_folder = self.temp_path if not os.path.isdir(os.path.join(self.temp_path)): os.mkdir(os.path.join(self.temp_path)) if not os.path.isdir(eval_folder): @@ -385,6 +385,7 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, eval_result = run_coco_eval(gt_file_path=os.path.join(dataset_nms.path, 'annotations', annotations_filename), dt_file_path=output_file, only_classes=[1], verbose=verbose, max_dets=[max_dt_boxes]) + os.remove(output_file) for i in range(len(eval_result)): print('Evaluation results (num_dets={})'.format(str(eval_result[i][1]))) print(eval_result[i][0][0][1]) From 63025fa8db0c622ca6783cb52761acebe67b5f18 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 11:45:45 +0200 Subject: [PATCH 165/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../object-detection-2d-nms-seq2seq_nms.md | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index c24c51c953..cd58800d23 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -12,8 +12,8 @@ public methods: #### `Seq2SeqNMSLearner` constructor ```python -Seq2SeqNMSLearner(self, lr, epochs, device, temp_path, checkpoint_after_iter, checkpoint_load_iter, log_after, variant, experiment_name, - iou_filtering, dropout, pretrained_demo_model, app_feats, fmod_map_type, fmod_map_bin, app_input_dim) +Seq2SeqNMSLearner(self, lr, epochs, device, temp_path, checkpoint_after_iter, checkpoint_load_iter, log_after, variant, + iou_filtering, dropout, app_feats, fmod_map_type, fmod_map_bin, app_input_dim) ``` Constructor parameters: @@ -34,14 +34,10 @@ Constructor parameters: Specifies interval (in iterations/batches) between information logging on *stdout*. - **variant**: *{'light', 'medium', 'full'}, default='medium'*\ Specifies the variant of seq2seq-nms model. -- **experiment_name**: *str, default='default'*\ - Specifies the name of the experiment. - **iou_filtering**: *float, default=0.8*\ Specifies the IoU threshold used for filtering RoIs before provided by the seq2seq-nms model.If set to values <0 or >1, no filtering is applied. -- **dropout**: *float, default=0.05*\ +- **dropout**: *float, default=0.025*\ Specifies the dropout rate. -- **pretrained_demo_model**: *{'PETS_JPD_medium', 'COCO_FRCN_medium' , defualt=None*\ -- Specifies the name of the pretrained model - **app_feats**: *{'fmod', 'zeros', 'custom'}, default='fmod'*\ Specifies the type of the appearance-based features of RoIs used in the model. - **fmod_map_type**: *{'EDGEMAP', 'FAST', 'AKAZE', 'BRISK', 'ORB'}, default='EDGEMAP'*\ @@ -218,15 +214,15 @@ Parameters: import os OPENDR_HOME = os.environ['OPENDR_HOME'] - seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=0.8, experiment_name='pets_exp0', - app_feats='fmod', checkpoint_after_iter=1, - temp_path=OPENDR_HOME + '/src/opendr/perception/' + seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=0.8, + app_feats='fmod', checkpoint_after_iter=1, + temp_path=OPENDR_HOME + '/src/opendr/perception/' 'object_detection_2d/nms/seq2seq_nms/temp', - epochs=8) + epochs=8) seq2SeqNMSLearner.fit(dataset='PETS', use_ssd=False, - datasets_folder=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/datasets', - logging_path='./logs_pets_exp1', silent=False, verbose=True, nms_gt_iou=0.50, - max_dt_boxes=500) + datasets_folder=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/datasets', + logging_path='./logs_pets_exp1', silent=False, verbose=True, nms_gt_iou=0.50, + max_dt_boxes=500) ``` * **Inference and result drawing example on a test .jpg image using OpenCV.** @@ -239,10 +235,10 @@ Parameters: import os OPENDR_HOME = os.environ['OPENDR_HOME'] - seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, experiment_name='pets_exp0', + seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, app_feats='fmod', device='cpu') - seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/pets_exp0/' - 'checkpoints/checkpoint_epoch_7', verbose=True) + seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/pets_exp0/' + 'checkpoint_epoch_7', verbose=True) ssd = SingleShotDetectorLearner(device='cuda') ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) From 94935e6e0d0c250f4a70bdea4978bab4e9a691fb Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 11:47:41 +0200 Subject: [PATCH 166/374] Update test_seq2seq_nms.py --- .../object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index 38310f0e90..2c20980d0c 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -125,10 +125,10 @@ def test_infer(self): def test_save_load(self): print('Starting save/load test for Seq2Seq-NMS...') - self.seq2SeqNMSLearner.save(os.path.join(self.temp_dir, "test_model", "checkpoints", "last_weights"), current_epoch=0) + self.seq2SeqNMSLearner.save(os.path.join(self.temp_dir, "test_model", "last_weights"), current_epoch=0) self.seq2SeqNMSLearner.model = None self.seq2SeqNMSLearner.init_model() - self.seq2SeqNMSLearner.load(os.path.join(self.temp_dir, "test_model", 'checkpoints')) + self.seq2SeqNMSLearner.load(os.path.join(self.temp_dir, "test_model")) self.assertIsNotNone(self.seq2SeqNMSLearner.model, "model is None after loading model.") # Cleanup rmdir(os.path.join(self.temp_dir, "test_model")) From f70020f25c6027beb5c4dc61782a198be5472fdc Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 12:17:24 +0200 Subject: [PATCH 167/374] Update object_detection_2d_ssd.py --- .../scripts/object_detection_2d_ssd.py | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py index 6f643e61cf..509bf81efb 100755 --- a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py +++ b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py @@ -26,7 +26,7 @@ class ObjectDetectionSSDNode: def __init__(self, input_image_topic="/usb_cam/image_raw", output_image_topic="/opendr/image_boxes_annotated", - detections_topic="/opendr/objects", device="cuda", backbone="vgg16_atrous"): + detections_topic="/opendr/objects", device="cuda", backbone="vgg16_atrous", nms_type='default'): """ Creates a ROS Node for face detection :param input_image_topic: Topic from which we are reading the input image @@ -41,6 +41,8 @@ def __init__(self, input_image_topic="/usb_cam/image_raw", output_image_topic="/ :type device: str :param backbone: backbone network :type backbone: str + :param ms_type: type of NMS method + :type nms_type: str """ # Initialize the face detector @@ -48,7 +50,21 @@ def __init__(self, input_image_topic="/usb_cam/image_raw", output_image_topic="/ self.object_detector.download(path=".", verbose=True) self.object_detector.load("ssd_default_person") self.class_names = self.object_detector.classes - + self.custom_nms = None + + # Initialize Seq2Seq-NMS if selected + if nms_type == 'seq2seq-nms': + self.custom_nms = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, + app_feats='fmod', device='cpu') + self.custom_nms.download(model_name='seq2seq_pets_jpd', path=.) + self.custom_nms.load(./seq2seq_pets_jpd/', verbose=True) + elif nms_type == 'soft-nms': + self.custom_nms = SoftNMS(nms_thres=0.45, device='cpu) + elif nms_type == 'fast-nms': + self.custom_nms = FastNMS(nms_thres=0.45, device='cpu) + elif nms_type == 'cluster-nms': + self.custom_nms = ClusterNMS(nms_thres=0.45, device='cpu) + # Initialize OpenDR ROSBridge object self.bridge = ROSBridge() @@ -76,7 +92,7 @@ def callback(self, data): image = self.bridge.from_ros_image(data, encoding='bgr8') # Run pose estimation - boxes = self.object_detector.infer(image, threshold=0.45, keep_size=False) + boxes = self.object_detector.infer(image, threshold=0.45, keep_size=False, custom_nms=self.custom_nms) # Get an OpenCV image back image = np.float32(image.opencv()) From ef5054dcbfcece4868605126690aafae02927d04 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 12:19:28 +0200 Subject: [PATCH 168/374] Update object_detection_2d_ssd.py --- .../src/perception/scripts/object_detection_2d_ssd.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py index 509bf81efb..21fb95fd5d 100755 --- a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py +++ b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py @@ -55,15 +55,15 @@ def __init__(self, input_image_topic="/usb_cam/image_raw", output_image_topic="/ # Initialize Seq2Seq-NMS if selected if nms_type == 'seq2seq-nms': self.custom_nms = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, - app_feats='fmod', device='cpu') + app_feats='fmod', device=self.device) self.custom_nms.download(model_name='seq2seq_pets_jpd', path=.) self.custom_nms.load(./seq2seq_pets_jpd/', verbose=True) elif nms_type == 'soft-nms': - self.custom_nms = SoftNMS(nms_thres=0.45, device='cpu) + self.custom_nms = SoftNMS(nms_thres=0.45, device=self.device) elif nms_type == 'fast-nms': - self.custom_nms = FastNMS(nms_thres=0.45, device='cpu) + self.custom_nms = FastNMS(nms_thres=0.45, device=self.device) elif nms_type == 'cluster-nms': - self.custom_nms = ClusterNMS(nms_thres=0.45, device='cpu) + self.custom_nms = ClusterNMS(nms_thres=0.45, device=self.device) # Initialize OpenDR ROSBridge object self.bridge = ROSBridge() From e12644dc146f83763283769312747e58edd5bc01 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 12:30:33 +0200 Subject: [PATCH 169/374] Update object_detection_2d_ssd.py --- .../src/perception/scripts/object_detection_2d_ssd.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py index 21fb95fd5d..2fca6e2a5a 100755 --- a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py +++ b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py @@ -51,20 +51,20 @@ def __init__(self, input_image_topic="/usb_cam/image_raw", output_image_topic="/ self.object_detector.load("ssd_default_person") self.class_names = self.object_detector.classes self.custom_nms = None - + # Initialize Seq2Seq-NMS if selected if nms_type == 'seq2seq-nms': - self.custom_nms = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, + self.custom_nms = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=0.8, app_feats='fmod', device=self.device) - self.custom_nms.download(model_name='seq2seq_pets_jpd', path=.) - self.custom_nms.load(./seq2seq_pets_jpd/', verbose=True) + self.custom_nms.download(model_name='seq2seq_pets_jpd', path='.') + self.custom_nms.load('./seq2seq_pets_jpd/', verbose=True) elif nms_type == 'soft-nms': self.custom_nms = SoftNMS(nms_thres=0.45, device=self.device) elif nms_type == 'fast-nms': self.custom_nms = FastNMS(nms_thres=0.45, device=self.device) elif nms_type == 'cluster-nms': self.custom_nms = ClusterNMS(nms_thres=0.45, device=self.device) - + # Initialize OpenDR ROSBridge object self.bridge = ROSBridge() From 4425c720f3470cc2b6473d240f248c501d4983a8 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 12:35:08 +0200 Subject: [PATCH 170/374] Update object_detection_2d_ssd.py --- .../src/perception/scripts/object_detection_2d_ssd.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py index 2fca6e2a5a..f8a89ba94d 100755 --- a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py +++ b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py @@ -61,9 +61,9 @@ def __init__(self, input_image_topic="/usb_cam/image_raw", output_image_topic="/ elif nms_type == 'soft-nms': self.custom_nms = SoftNMS(nms_thres=0.45, device=self.device) elif nms_type == 'fast-nms': - self.custom_nms = FastNMS(nms_thres=0.45, device=self.device) + self.custom_nms = FastNMS(nms_thres=0.45, device=self.device) elif nms_type == 'cluster-nms': - self.custom_nms = ClusterNMS(nms_thres=0.45, device=self.device) + self.custom_nms = ClusterNMS(nms_thres=0.45, device=self.device) # Initialize OpenDR ROSBridge object self.bridge = ROSBridge() From b505105e46064e3a4464464c25837f2352d80338 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 12:43:53 +0200 Subject: [PATCH 171/374] Update object_detection_2d_ssd.py --- .../src/perception/scripts/object_detection_2d_ssd.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py index f8a89ba94d..6cd9e05026 100755 --- a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py +++ b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py @@ -22,6 +22,10 @@ from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes +from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner +from opendr.perception.object_detection_2d.nms.soft_nms.soft_nms import SoftNMS +from opendr.perception.object_detection_2d.nms.fast_nms.fast_nms import FastNMS +from opendr.perception.object_detection_2d.nms.cluster_nms.cluster_nms import ClusterNMS class ObjectDetectionSSDNode: From 8e0c8629b1dd27a02c78fcea16fb049640387d5a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 14:15:49 +0200 Subject: [PATCH 172/374] Create README.md --- .../perception/object_detection_2d/nms/fast_nms/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/opendr/perception/object_detection_2d/nms/fast_nms/README.md diff --git a/src/opendr/perception/object_detection_2d/nms/fast_nms/README.md b/src/opendr/perception/object_detection_2d/nms/fast_nms/README.md new file mode 100644 index 0000000000..14102d9549 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/fast_nms/README.md @@ -0,0 +1,8 @@ +# Fast-NMS Demos + +This folder contains minimal code usage examples that showcase the basic functionality of the Fast-NMS implementation +provided by OpenDR. Specifically the following examples are provided: +1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. + +2. eval_demo.py: Perform evaluation on the `PETS` dataset, implemented in OpenDR format. + Setting `--device cpu` performs evaluation on CPU. From a06f65453af64d0ca98f524de22274f8a688421f Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 14:16:45 +0200 Subject: [PATCH 173/374] Create README.md --- .../perception/object_detection_2d/nms/soft_nms/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/opendr/perception/object_detection_2d/nms/soft_nms/README.md diff --git a/src/opendr/perception/object_detection_2d/nms/soft_nms/README.md b/src/opendr/perception/object_detection_2d/nms/soft_nms/README.md new file mode 100644 index 0000000000..ad2a9d8b19 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/soft_nms/README.md @@ -0,0 +1,8 @@ +# Soft-NMS Demos + +This folder contains minimal code usage examples that showcase the basic functionality of the Soft-NMS implementation +provided by OpenDR. Specifically the following examples are provided: +1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. + +2. eval_demo.py: Perform evaluation on the `PETS` dataset, implemented in OpenDR format. + Setting `--device cpu` performs evaluation on CPU. From dd814a9c0eb0742591193fbe86865e334bcc790e Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 14:22:30 +0200 Subject: [PATCH 174/374] Update README.md --- .../object_detection_2d/nms/fast_nms/README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/fast_nms/README.md b/src/opendr/perception/object_detection_2d/nms/fast_nms/README.md index 14102d9549..8060c78898 100644 --- a/src/opendr/perception/object_detection_2d/nms/fast_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/fast_nms/README.md @@ -1,8 +1,11 @@ -# Fast-NMS Demos +Fast-NMS +====== -This folder contains minimal code usage examples that showcase the basic functionality of the Fast-NMS implementation -provided by OpenDR. Specifically the following examples are provided: -1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. +This folder contains an implementation of Fast-NMS [[1]](#fast_nms-1). -2. eval_demo.py: Perform evaluation on the `PETS` dataset, implemented in OpenDR format. - Setting `--device cpu` performs evaluation on CPU. +Sources +------ +Large parts of code are taken from [here](https://github.com/Zzh-tju/CIoU) with modifications to make it compatible with OpenDR specifications. + +[1] YOLACT: Real-time Instance Segmentation, +[ArXiv](https://arxiv.org/abs/1904.02689). From 9aa775e449c8d4792914145f86effbb8121a7170 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 14:25:19 +0200 Subject: [PATCH 175/374] Update README.md --- .../object_detection_2d/nms/soft_nms/README.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/soft_nms/README.md b/src/opendr/perception/object_detection_2d/nms/soft_nms/README.md index ad2a9d8b19..3dfc265ff2 100644 --- a/src/opendr/perception/object_detection_2d/nms/soft_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/soft_nms/README.md @@ -1,8 +1,11 @@ -# Soft-NMS Demos +Soft-NMS +====== -This folder contains minimal code usage examples that showcase the basic functionality of the Soft-NMS implementation -provided by OpenDR. Specifically the following examples are provided: -1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. +This folder contains an implementation of Soft-NMS [[1]](#soft_nms-1). -2. eval_demo.py: Perform evaluation on the `PETS` dataset, implemented in OpenDR format. - Setting `--device cpu` performs evaluation on CPU. +Sources +------ +Large parts of code are taken from [here](https://github.com/DocF/Soft-NMS) with modifications to make it compatible with OpenDR specifications. + +[1] Soft-NMS -- Improving Object Detection With One Line of Code, +[ArXiv](https://arxiv.org/abs/1704.04503). From 4e9abc6f10da7c585db4924284a5f25319c63da2 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 14:27:13 +0200 Subject: [PATCH 176/374] Create README.md --- .../object_detection_2d/nms/seq2seq_nms/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md new file mode 100644 index 0000000000..ea4fc82121 --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -0,0 +1,8 @@ +Seq2Seq-NMS +====== + +This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). + + +[1] Neural Attention-driven Non-Maximum Suppressionfor Person Detection, +[ArXiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). From c077e4b54d5c6bfaf93d6c020be042378d5e99ec Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 14:27:32 +0200 Subject: [PATCH 177/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index ea4fc82121..bcd45fe378 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -4,5 +4,5 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). -[1] Neural Attention-driven Non-Maximum Suppressionfor Person Detection, +[1] Neural Attention-driven Non-Maximum Suppression for Person Detection, [ArXiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). From 514b7120314f5d34d69ecbb4e3d31dcc9790d564 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 14:42:52 +0200 Subject: [PATCH 178/374] Update ssd_learner.py --- .../object_detection_2d/ssd/ssd_learner.py | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py index eea1df3b84..46a2620d50 100644 --- a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py +++ b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py @@ -456,18 +456,27 @@ def __get_lr_at(self, epoch): else: return self.lr - def eval(self, dataset, use_subset=False, subset_size=100, verbose=False): + def eval(self, dataset, use_subset=False, subset_size=100, verbose=False, + nms_thresh=0.45, nms_topk=400, post_nms=100): """ This method performs evaluation on a given dataset and returns a dictionary with the evaluation results. :param dataset: dataset object, to perform evaluation on :type dataset: opendr.perception.object_detection_2d.datasets.DetectionDataset or opendr.engine.data.ExternalDataset - :return: dictionary containing evaluation metric names nad values :param use_subset: if True, only a subset of the dataset is evaluated, defaults to False :type use_subset: bool, optional :param subset_size: if use_subset is True, subset_size controls the size of the subset to be evaluated :type subset_size: int, optional :param verbose: if True, additional information is printed on stdout :type verbose: bool, optional + :param nms_thresh: Non-maximum suppression threshold. You can specify < 0 or > 1 to disable NMS. + :type nms_thresh: float, default is 0.45 + :param nms_topk: Apply NMS to top k detection results, use -1 to disable so that every Detection result is used in NMS. + :type nms_topk: int, default is 400 + :param post_nms: Only return top post_nms detection results, the rest is discarded. + The number is based on COCO dataset which has maximum 100 objects per image. You can adjust this number if + expecting more objects. You can use -1 to return all detections. + :type post_nms: int, default is 100 + :return: dictionary containing evaluation metric names nad values :rtype: dict """ autograd.set_training(False) @@ -486,7 +495,7 @@ def eval(self, dataset, use_subset=False, subset_size=100, verbose=False): self._model.initialize() self._model.collect_params().reset_ctx(ctx) self._model.hybridize(static_alloc=True, static_shape=True) - self._model.set_nms(nms_thresh=0.45, nms_topk=400) + self._model.set_nms(nms_thresh=nms_thresh, nms_topk=nms_topk, post_nms=post_nms) dataset, eval_metric = self.__prepare_val_dataset(dataset, data_shape=self.img_size) @@ -551,6 +560,16 @@ def infer(self, img, threshold=0.2, keep_size=False, custom_nms: NMSCustom=None, :type threshold: float, optional :param keep_size: if True, the image is not resized to fit the data shape used during training :type keep_size: bool, optional + :param custom_nms: Custom NMS method to be employed on inference + :type perception.object_detection_2d.nms.utils.nms_custom.NMSCustom + :param nms_thresh: Non-maximum suppression threshold. You can specify < 0 or > 1 to disable NMS. + :type nms_thresh: float, default is 0.45 + :param nms_topk: Apply NMS to top k detection results, use -1 to disable so that every Detection result is used in NMS. + :type nms_topk: int, default is 400 + :param post_nms: Only return top post_nms detection results, the rest is discarded. + The number is based on COCO dataset which has maximum 100 objects per image. You can adjust this number if + expecting more objects. You can use -1 to return all detections. + :type post_nms: int, default is 100 :return: list of bounding boxes :rtype: BoundingBoxList """ From db195f58bbfdc177ce5caa00bf35adad1f43ccb8 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 15:06:22 +0200 Subject: [PATCH 179/374] Update ssd_learner.py --- .../perception/object_detection_2d/ssd/ssd_learner.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py index 46a2620d50..c7e64fab9c 100644 --- a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py +++ b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py @@ -456,7 +456,7 @@ def __get_lr_at(self, epoch): else: return self.lr - def eval(self, dataset, use_subset=False, subset_size=100, verbose=False, + def eval(self, dataset, use_subset=False, subset_size=100, verbose=False, nms_thresh=0.45, nms_topk=400, post_nms=100): """ This method performs evaluation on a given dataset and returns a dictionary with the evaluation results. @@ -473,7 +473,7 @@ def eval(self, dataset, use_subset=False, subset_size=100, verbose=False, :param nms_topk: Apply NMS to top k detection results, use -1 to disable so that every Detection result is used in NMS. :type nms_topk: int, default is 400 :param post_nms: Only return top post_nms detection results, the rest is discarded. - The number is based on COCO dataset which has maximum 100 objects per image. You can adjust this number if + The number is based on COCO dataset which has maximum 100 objects per image. You can adjust this number if expecting more objects. You can use -1 to return all detections. :type post_nms: int, default is 100 :return: dictionary containing evaluation metric names nad values @@ -567,7 +567,7 @@ def infer(self, img, threshold=0.2, keep_size=False, custom_nms: NMSCustom=None, :param nms_topk: Apply NMS to top k detection results, use -1 to disable so that every Detection result is used in NMS. :type nms_topk: int, default is 400 :param post_nms: Only return top post_nms detection results, the rest is discarded. - The number is based on COCO dataset which has maximum 100 objects per image. You can adjust this number if + The number is based on COCO dataset which has maximum 100 objects per image. You can adjust this number if expecting more objects. You can use -1 to return all detections. :type post_nms: int, default is 100 :return: list of bounding boxes From 34bf134e072d61df6b82ced9f5c27addbfa4e4e5 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 15:06:56 +0200 Subject: [PATCH 180/374] Update nms_utils.py --- .../perception/object_detection_2d/nms/utils/nms_utils.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py index 0d1d45e96c..7e69b49927 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py @@ -220,6 +220,8 @@ def drop_dets(boxes, scores, keep_ratio=0.85): ids_keep = ids[0:int(len(boxes) * keep_ratio)] boxes_new = boxes[ids_keep, :] scores_new = scores[ids_keep] + scores_new, scores_new_ids = torch.sort(scores_new, descending=True) + boxes_new = boxes_new[scores_new_ids] return boxes_new, scores_new From 949bcc1203d1c35b95b97e5f03a6c96d55d2e242 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 15:51:47 +0200 Subject: [PATCH 181/374] Update inference_demo.py --- .../object_detection_2d/nms/cluster_nms/inference_demo.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py index f4655f9105..f8273b0582 100644 --- a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py @@ -17,7 +17,6 @@ from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes -import datetime import os OPENDR_HOME = os.environ['OPENDR_HOME'] @@ -27,7 +26,6 @@ img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg') if not isinstance(img, Image): img = Image(img) -start_time = datetime.datetime.now() cluster_nms = ClusterNMS(device='cuda', nms_type='default', cross_class=True) boxes = ssd.infer(img, threshold=0.3, custom_nms=cluster_nms) draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) From b8d0ca6b1f5af4b53a74d941e73cf326136bfd89 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 15:54:21 +0200 Subject: [PATCH 182/374] Update inference_demo.py --- .../nms/seq2seq-nms/inference_demo.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index f0c87a23cf..63a96b0637 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -20,15 +20,16 @@ import os OPENDR_HOME = os.environ['OPENDR_HOME'] -seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=0.8, experiment_name='pets_exp0', +seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, app_feats='fmod', device='cpu') -seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/pets_exp0/' - 'checkpoints/checkpoint_epoch_7', verbose=True) +seq2_seq_tmp_dir = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp' +seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd', path=seq2_seq_tmp_dir) +seq2SeqNMSLearner.load(os.path.join(seq2_seq_tmp_dir, 'seq2seq_pets_jpd'), verbose=True) ssd = SingleShotDetectorLearner(device='cuda') ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg') if not isinstance(img, Image): img = Image(img) -boxes = ssd.infer(img, threshold=0.25, custom_nms=seq2SeqNMSLearner) +boxes = ssd.infer(img, threshold=0.3, custom_nms=seq2SeqNMSLearner) draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) From e598ac96186c2820cd5a6acf310ca31dbfad08ab Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 15:57:01 +0200 Subject: [PATCH 183/374] Update README.md --- .../perception/object_detection_2d/nms/cluster_nms/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/cluster_nms/README.md b/projects/perception/object_detection_2d/nms/cluster_nms/README.md index baefd8e7b3..0ff5c5fd9c 100644 --- a/projects/perception/object_detection_2d/nms/cluster_nms/README.md +++ b/projects/perception/object_detection_2d/nms/cluster_nms/README.md @@ -2,7 +2,6 @@ This folder contains minimal code usage examples that showcase the basic functionality of the Cluster-NMS implementation provided by OpenDR. Specifically the following examples are provided: + 1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. -2. eval_demo.py: Perform evaluation on the `PETS` dataset, implemented in OpenDR format. - Setting `--device cpu` performs evaluation on CPU. From 08483d2955e20335b41157ff1ef7c1a7e8758b67 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:08:21 +0200 Subject: [PATCH 184/374] Update README.md --- projects/perception/object_detection_2d/nms/fast_nms/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/fast_nms/README.md b/projects/perception/object_detection_2d/nms/fast_nms/README.md index 08541d321e..5a1ccb3fd6 100644 --- a/projects/perception/object_detection_2d/nms/fast_nms/README.md +++ b/projects/perception/object_detection_2d/nms/fast_nms/README.md @@ -3,6 +3,3 @@ This folder contains minimal code usage examples that showcase the basic functionality of the Fast-NMS implementation provided by OpenDR. Specifically the following examples are provided: 1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. - -2. eval_demo.py: Perform evaluation on the `PETS` dataset, implemented in OpenDR format. - Setting `--device cpu` performs evaluation on CPU. From 743f851317212d950277fe8de416a1fc170d6e17 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:08:39 +0200 Subject: [PATCH 185/374] Update README.md --- projects/perception/object_detection_2d/nms/soft_nms/README.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/soft_nms/README.md b/projects/perception/object_detection_2d/nms/soft_nms/README.md index 0d1d3bd0ea..a4c778f35c 100644 --- a/projects/perception/object_detection_2d/nms/soft_nms/README.md +++ b/projects/perception/object_detection_2d/nms/soft_nms/README.md @@ -3,6 +3,3 @@ This folder contains minimal code usage examples that showcase the basic functionality of the Soft-NMS implementation provided by OpenDR. Specifically the following examples are provided: 1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. - -2. eval_demo.py: Perform evaluation on the `PETS` dataset, implemented in OpenDR format. - Setting `--device cpu` performs evaluation on CPU. From 7d53dfdc8e8dcbf77629d3135b374fb21c187af9 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:11:14 +0200 Subject: [PATCH 186/374] Create README.md --- .../nms/seq2seq-nms/README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 projects/perception/object_detection_2d/nms/seq2seq-nms/README.md diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/README.md b/projects/perception/object_detection_2d/nms/seq2seq-nms/README.md new file mode 100644 index 0000000000..c831924349 --- /dev/null +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/README.md @@ -0,0 +1,17 @@ +# Seq2Seq-NMS Demos + +This folder contains minimal code usage examples that showcase the basic functionality of the Seq2Seq-NMS implementation +provided by OpenDR. Specifically the following examples are provided: + +1. inference_demo.py: Perform inference on a single image. Setting `--device cpu` performs inference on CPU. + +2. eval_demo.py: Perform evaluation on the `WiderPersonDataset`, implemented in OpenDR format. The user must first download + the dataset and provide the path to the dataset root via `--data-root /path/to/wider_person`. + Setting `--device cpu` performs evaluation on CPU. + +3. train_demo.py: Fit learner to dataset. PASCAL VOC and COCO datasets are supported via `ExternalDataset` class and any + `DetectionDataset` can be used as well. Provided is an example of training on `WiderPersonDataset`. The user must set the + dataset type using the `--dataset` argument and provide the dataset root path with the `--data-root` argument. + Setting `--device cpu` performs training on CPU. Additional command line arguments can be set to change various training + hyperparameters, and running `python3 train_demo.py -h` prints information about them on stdout. + From 0de953f0528a014a80940b07809afb4e2b8bd808 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:18:17 +0200 Subject: [PATCH 187/374] Update inference_demo.py --- .../object_detection_2d/nms/seq2seq-nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index 63a96b0637..9f03339366 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -20,7 +20,7 @@ import os OPENDR_HOME = os.environ['OPENDR_HOME'] -seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, +seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=0.8, app_feats='fmod', device='cpu') seq2_seq_tmp_dir = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp' seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd', path=seq2_seq_tmp_dir) From 118ec1a1646fc4b323331000e42ef9d52d5f40cc Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:48:42 +0200 Subject: [PATCH 188/374] Create training_demo.py --- .../nms/seq2seq-nms/training_demo.py | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py new file mode 100644 index 0000000000..f8c16bf861 --- /dev/null +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py @@ -0,0 +1,10 @@ +from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner +import os +OPENDR_HOME = os.environ['OPENDR_HOME'] +temp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/coco_own3' +seq2SeqNMSLearner = Seq2SeqNMSLearner(iou_filtering=None, app_feats='fmod', + temp_path=temp_path, device='cuda') +seq2SeqNMSLearner.load(temp_path + '/checkpoints/checkpoint_epoch_0', verbose=True) +seq2SeqNMSLearner.eval(dataset='COCO', split='val', max_dt_boxes=800, + datasets_folder=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/datasets', + use_ssd=False) From 3adb275a28c1314170758ecfbe03ae7d3ecf9f29 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:49:38 +0200 Subject: [PATCH 189/374] Update training_demo.py --- .../nms/seq2seq-nms/training_demo.py | 30 ++++++++++++++----- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py index f8c16bf861..3796d79728 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py @@ -1,10 +1,26 @@ +# Copyright 2020-2022 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner import os OPENDR_HOME = os.environ['OPENDR_HOME'] -temp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp/coco_own3' -seq2SeqNMSLearner = Seq2SeqNMSLearner(iou_filtering=None, app_feats='fmod', - temp_path=temp_path, device='cuda') -seq2SeqNMSLearner.load(temp_path + '/checkpoints/checkpoint_epoch_0', verbose=True) -seq2SeqNMSLearner.eval(dataset='COCO', split='val', max_dt_boxes=800, - datasets_folder=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/datasets', - use_ssd=False) + +seq2seq_tmp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/coco_tmp' +seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=None, app_feats='fmod', + checkpoint_after_iter=1, temp_path=seq2seq_tmp_path, epochs=8) +seq2SeqNMSLearner.fit(dataset='COCO', use_ssd=False, + datasets_folder=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/datasets', + logging_path='./logs_coco_own3', silent=False, verbose=True, nms_gt_iou=0.50, + max_dt_boxes=450) From 4251b6a1092f1823c50568ac531e0c7a752dd10b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:51:33 +0200 Subject: [PATCH 190/374] Update training_demo.py --- .../object_detection_2d/nms/seq2seq-nms/training_demo.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py index 3796d79728..36f2401c8e 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py @@ -18,9 +18,11 @@ OPENDR_HOME = os.environ['OPENDR_HOME'] seq2seq_tmp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/coco_tmp' +seq2seq_logs_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/coco_logs' + seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=None, app_feats='fmod', checkpoint_after_iter=1, temp_path=seq2seq_tmp_path, epochs=8) seq2SeqNMSLearner.fit(dataset='COCO', use_ssd=False, datasets_folder=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/datasets', - logging_path='./logs_coco_own3', silent=False, verbose=True, nms_gt_iou=0.50, + logging_path=seq2seq_logs_path, silent=False, verbose=True, nms_gt_iou=0.50, max_dt_boxes=450) From 61139b737a36c279d99ed04074a53078fa26f79a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 16:52:04 +0200 Subject: [PATCH 191/374] Rename training_demo.py to train_demo.py --- .../nms/seq2seq-nms/{training_demo.py => train_demo.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename projects/perception/object_detection_2d/nms/seq2seq-nms/{training_demo.py => train_demo.py} (100%) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py similarity index 100% rename from projects/perception/object_detection_2d/nms/seq2seq-nms/training_demo.py rename to projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py From 87148e5b53651567cf5a2154bcb02870a6530c61 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 17:00:05 +0200 Subject: [PATCH 192/374] Create eval_demo.py --- .../nms/seq2seq-nms/eval_demo.py | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py new file mode 100644 index 0000000000..ca87cc4d25 --- /dev/null +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py @@ -0,0 +1,25 @@ +# Copyright 2020-2022 OpenDR European Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner +import os +OPENDR_HOME = os.environ['OPENDR_HOME'] +temp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/pets_tmp' +dataset_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/pets_dataset' +seq2SeqNMSLearner = Seq2SeqNMSLearner(iou_filtering=0.8, app_feats='fmod', temp_path=temp_path, + device='cuda') +seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd', path=temp_path) +seq2SeqNMSLearner.load(os.path.join(temp_path, 'seq2seq_pets_jpd'), verbose=True) +seq2SeqNMSLearner.eval(dataset='PETS', split='test', max_dt_boxes=600, + datasets_folder=dataset_path, use_ssd=False) From 1ad6e98c02393f804f9cc1433706d7ca968e8d6c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 17 Mar 2022 17:11:43 +0200 Subject: [PATCH 193/374] Update train_demo.py --- .../nms/seq2seq-nms/train_demo.py | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py index 36f2401c8e..bef6c9b6dd 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py @@ -17,12 +17,26 @@ import os OPENDR_HOME = os.environ['OPENDR_HOME'] + parser = argparse.ArgumentParser() + parser.add_argument("--dataset", help="Dataset to train on", type=str, default="voc", choices=["PETS", "COCO", + "TEST_MODULE"]) + parser.add_argument("--data_root", help="Dataset root folder", type=str) + parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cuda", choices=["cuda", "cpu"]) + parser.add_argument("--max_dt_boxes", help="Maximum number of input RoIs to Seq2Seq-NMS", type=int, default=450) + parser.add_argument("--nms_gt_iou", help="Learning rate to use for training", type=float, default=5e-4) + parser.add_argument("--val-after", help="Epochs in-between evaluations", type=int, default=5) + parser.add_argument("--checkpoint-freq", help="Frequency in-between checkpoint saving", type=int, default=5) + parser.add_argument("--n-epochs", help="Number of total epochs", type=int, default=25) + parser.add_argument("--resume-from", help="Epoch to load checkpoint file and resume training from", type=int, default=0) + + args = parser.parse_args() + seq2seq_tmp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/coco_tmp' seq2seq_logs_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/coco_logs' seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=None, app_feats='fmod', checkpoint_after_iter=1, temp_path=seq2seq_tmp_path, epochs=8) -seq2SeqNMSLearner.fit(dataset='COCO', use_ssd=False, - datasets_folder=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/datasets', +seq2SeqNMSLearner.fit(dataset=args.dataset, use_ssd=False, + datasets_folder= args.data_root, logging_path=seq2seq_logs_path, silent=False, verbose=True, nms_gt_iou=0.50, - max_dt_boxes=450) + max_dt_boxes=args.max_dt_boxes) From ae9284109263237eb6907173edbf7d36038b72ea Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 10:58:42 +0200 Subject: [PATCH 194/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index cd58800d23..667c2937ef 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -27,7 +27,8 @@ Constructor parameters: - **temp_path**: *str, default='./temp'*\ Specifies a path to be used for storage of checkpoints during training. - **checkpoint_after_iter**: *int, default=0*\ - Specifies the epoch interval between checkpoints during training. If set to 0 no checkpoint will be saved. + Specifies the epoch interval between checkpoints during training. + If set to 0 no checkpoint will be saved. - **checkpoint_load_iter**: *int, default=0*\ Specifies the epoch to load a saved checkpoint from. If set to 0 no checkpoint will be loaded. - **log_after**: *int, default=500*\ From 9ee3537ad5db2903a21d5907009e68636a2f89f5 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 10:59:06 +0200 Subject: [PATCH 195/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 667c2937ef..3f26c3073a 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -30,7 +30,8 @@ Constructor parameters: Specifies the epoch interval between checkpoints during training. If set to 0 no checkpoint will be saved. - **checkpoint_load_iter**: *int, default=0*\ - Specifies the epoch to load a saved checkpoint from. If set to 0 no checkpoint will be loaded. + Specifies the epoch to load a saved checkpoint from. + If set to 0 no checkpoint will be loaded. - **log_after**: *int, default=500*\ Specifies interval (in iterations/batches) between information logging on *stdout*. - **variant**: *{'light', 'medium', 'full'}, default='medium'*\ From 22875bc2b8d6f49f13f0eae2a19979c5554de8f2 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 10:59:15 +0200 Subject: [PATCH 196/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 3f26c3073a..ea513d2d63 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -37,7 +37,8 @@ Constructor parameters: - **variant**: *{'light', 'medium', 'full'}, default='medium'*\ Specifies the variant of seq2seq-nms model. - **iou_filtering**: *float, default=0.8*\ - Specifies the IoU threshold used for filtering RoIs before provided by the seq2seq-nms model.If set to values <0 or >1, no filtering is applied. + Specifies the IoU threshold used for filtering RoIs before provided by the seq2seq-nms model. + If set to values <0 or >1, no filtering is applied. - **dropout**: *float, default=0.025*\ Specifies the dropout rate. - **app_feats**: *{'fmod', 'zeros', 'custom'}, default='fmod'*\ From d701063a721ecd476da11a22cccfcb579549a257 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 10:59:22 +0200 Subject: [PATCH 197/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index ea513d2d63..cdd555488e 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -48,7 +48,8 @@ Constructor parameters: - **fmod_map_bin**: *bool, default=True*\ Specifies whether FMoD maps are binary or not, in the case where *app_feats*='fmod'. - **app_input_dim**: *int, default=None*\ - Specifies the dimension of appearance-based RoI features. In the case where *app_feats*='fmod', the corresponding dimension is automatically computed. + Specifies the dimension of appearance-based RoI features. + In the case where *app_feats*='fmod', the corresponding dimension is automatically computed. #### `Seq2SeqNMSLearner.fit` From 570f794017324a71adbabb7958c8e3028212e19d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 10:59:32 +0200 Subject: [PATCH 198/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index cdd555488e..ffc44b7438 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -64,7 +64,8 @@ Parameters: - **dataset**: *{'PETS', 'COCO'}*\ Specifies the name of the dataset among those available from training. - **logging_path**: *str, default=None*\ - Path to save log files. If set to None, only the console will be used for logging. + Path to save log files. + If set to None, only the console will be used for logging. - **logging_flush_secs**: *int, default=30*\ How often, in seconds, to flush the TensorBoard data to disk. - **silent**: *bool, default=False*\ From 96b55cbec262b5818bb95dd9edb3a0217946853d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 10:59:44 +0200 Subject: [PATCH 199/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index ffc44b7438..135ece4478 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -57,7 +57,8 @@ Constructor parameters: Seq2SeqNMSLearner.fit(self, dataset, logging_path, logging_flush_secs, silent, verbose, nms_gt_iou, max_dt_boxes, datasets_folder, use_ssd) ``` -This method is used to train the algorithm on a `Dataset_NMS` dataset. Returns a dictionary containing stats regarding the training process. +This method is used to train the algorithm on a `Dataset_NMS` dataset. +Returns a dictionary containing stats regarding the training process. Parameters: From d4fb6f7d107a40a67b297f2cc033c889c2db50e2 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 10:59:53 +0200 Subject: [PATCH 200/374] Update src/opendr/perception/object_detection_2d/datasets/transforms.py Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- src/opendr/perception/object_detection_2d/datasets/transforms.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/datasets/transforms.py b/src/opendr/perception/object_detection_2d/datasets/transforms.py index c308e32a12..06d03fadaf 100644 --- a/src/opendr/perception/object_detection_2d/datasets/transforms.py +++ b/src/opendr/perception/object_detection_2d/datasets/transforms.py @@ -159,5 +159,4 @@ def pad_test(img, min_size=512): img_padded = mx.nd.pad(img, mode="constant", constant_value=0, pad_width=(0, 0, 0, 0, 0, 0, h_pad_size, h_pad_size)) - # img_mx = np.pad(img_mx, ((0, 0), (h_pad_size, h_pad_size), (0, 0))) return img_padded From c9e107af8a5d8dc8c396b34d6914c02633d96822 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:09:00 +0200 Subject: [PATCH 201/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index bcd45fe378..903731f074 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -3,6 +3,11 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). +TABLE-1: Average Precision (AP) of pretrained models +| Model name | Dataset | Validation Set | Test set | +| | | | | | | + + [1] Neural Attention-driven Non-Maximum Suppression for Person Detection, [ArXiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). From 246b962d32b246a368da6a18b780227e1e54b164 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:09:44 +0200 Subject: [PATCH 202/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 903731f074..0c92f2b684 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -6,6 +6,7 @@ This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) of pretrained models | Model name | Dataset | Validation Set | Test set | | | | | | | | +|------------|---------|-------|--------|-----|----| From 11a2c4549dbb61e6f8b105e02e016893c16a8d8c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:13:45 +0200 Subject: [PATCH 203/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 0c92f2b684..e2c03dbb75 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -5,7 +5,7 @@ This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) of pretrained models | Model name | Dataset | Validation Set | Test set | -| | | | | | | +| | | AP | AP | AP | AP | |------------|---------|-------|--------|-----|----| From b1bd1c7fbc011469815cad38e271b27cba8bb19b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:15:12 +0200 Subject: [PATCH 204/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index e2c03dbb75..014bcfa57a 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -5,6 +5,7 @@ This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) of pretrained models | Model name | Dataset | Validation Set | Test set | +|------------|---------|-------|--------|-----|----| | | | AP | AP | AP | AP | |------------|---------|-------|--------|-----|----| From 003d20271bbe7f7550b6d3ae0a7ae0206b01fa4f Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:15:33 +0200 Subject: [PATCH 205/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 014bcfa57a..eb02785a2d 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -7,7 +7,7 @@ TABLE-1: Average Precision (AP) of pretrained models | Model name | Dataset | Validation Set | Test set | |------------|---------|-------|--------|-----|----| | | | AP | AP | AP | AP | -|------------|---------|-------|--------|-----|----| + From c6b3c360eadb6cb6396c6f60a36f6b5855ff0d76 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:16:31 +0200 Subject: [PATCH 206/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index eb02785a2d..c8bbb7e6a6 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -5,7 +5,7 @@ This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) of pretrained models | Model name | Dataset | Validation Set | Test set | -|------------|---------|-------|--------|-----|----| +|------------|---------|----------------|----------| | | | AP | AP | AP | AP | From 0b2f4de64d14bf8f69822d65d3b455210de0f3c5 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:16:54 +0200 Subject: [PATCH 207/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index c8bbb7e6a6..e5a31228f2 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -7,6 +7,7 @@ TABLE-1: Average Precision (AP) of pretrained models | Model name | Dataset | Validation Set | Test set | |------------|---------|----------------|----------| | | | AP | AP | AP | AP | +|------------|---------|-------|--------|-----|----| From cbc57c9b3d809586b6ca7dffa16bae4341f32d2a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:19:40 +0200 Subject: [PATCH 208/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index e5a31228f2..e2e9f5bbbd 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -4,7 +4,7 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) of pretrained models -| Model name | Dataset | Validation Set | Test set | +| Model name | Dataset | Validation Set Test set | |------------|---------|----------------|----------| | | | AP | AP | AP | AP | |------------|---------|-------|--------|-----|----| From b5b3fc738cd9ffc848cec30cc06e6f64f3c7ef0f Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:20:03 +0200 Subject: [PATCH 209/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index e2e9f5bbbd..b41e899ca0 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -5,9 +5,8 @@ This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) of pretrained models | Model name | Dataset | Validation Set Test set | -|------------|---------|----------------|----------| -| | | AP | AP | AP | AP | |------------|---------|-------|--------|-----|----| +| | | AP | AP | AP | AP | From 2b2656140a4b767cf88c94b91446a8592804ae22 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:21:13 +0200 Subject: [PATCH 210/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index b41e899ca0..1ab3834163 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -5,8 +5,8 @@ This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) of pretrained models | Model name | Dataset | Validation Set Test set | -|------------|---------|-------|--------|-----|----| -| | | AP | AP | AP | AP | +|------------|---------|-------|-----------------------|---------|-------------| +| | | AP | AP | AP | AP | From 0ad5a85e58f26dccd2d79a23aae6614d4ef2b4ae Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:22:53 +0200 Subject: [PATCH 211/374] Update README.md --- .../object_detection_2d/nms/seq2seq_nms/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 1ab3834163..3e3a67b43b 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -4,9 +4,9 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) of pretrained models -| Model name | Dataset | Validation Set Test set | -|------------|---------|-------|-----------------------|---------|-------------| -| | | AP | AP | AP | AP | +| Model name | Dataset | Validation Set Test set | +|------------|---------|-------|-------------------------|-----------------|---------------| +| | | AP | AP | AP | AP | From aff72d9ad59bbae2c0e19e518dbf5ca19bd9ffcc Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:23:17 +0200 Subject: [PATCH 212/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 3e3a67b43b..0f26bed9f4 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -5,8 +5,7 @@ This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) of pretrained models | Model name | Dataset | Validation Set Test set | -|------------|---------|-------|-------------------------|-----------------|---------------| -| | | AP | AP | AP | AP | + From 6dd39a910dfaaa9e95423c3f8a35d4decfc6a930 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:26:39 +0200 Subject: [PATCH 213/374] Update README.md --- .../object_detection_2d/nms/seq2seq_nms/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 0f26bed9f4..e36d970bef 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -4,7 +4,13 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) of pretrained models +| One | Two | Three | Four | Five | Six | +| ---------|-------|----------|----------|--------|------| +| Span triple double + | Model name | Dataset | Validation Set Test set | +|------------|---------|-------|-------------------------|-----------------|---------------| +| | | AP | AP | AP | AP | From 06bb790f30a44c1b7e71b4cef8af6d3d6cd9bef4 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 11:33:42 +0200 Subject: [PATCH 214/374] Update README.md --- .../object_detection_2d/nms/seq2seq_nms/README.md | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index e36d970bef..9046cfc3d4 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -4,13 +4,8 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) of pretrained models -| One | Two | Three | Four | Five | Six | -| ---------|-------|----------|----------|--------|------| -| Span triple double - -| Model name | Dataset | Validation Set Test set | -|------------|---------|-------|-------------------------|-----------------|---------------| -| | | AP | AP | AP | AP | +| Model name | Dataset | AP0.5 on validation set | AP0.50.95 on validation set | AP0.5 on test set | AP0.50.95 on test set | +|------------|---------|------------------------------------|---------------------------------------------------|------------------------------|-------------------------------------------------------| From 16ab0c5e68eaf26f1e90dcd75cddcdd474dd3630 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:43:13 +0200 Subject: [PATCH 215/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 135ece4478..945cac7a03 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -80,7 +80,8 @@ Parameters: - **datasets_folder**: *str, default='./datasets'*\ Specifies the path to the folder where the datasets are stored. - **use_ssd**: *bool, default=False*\ - If set to True, RoIs from SSD are fed to the seq2Seq-nms model. Otherwise, RoIs from the default detector of the specified dataset are used as input. + If set to True, RoIs from SSD are fed to the seq2Seq-nms model. + Otherwise, RoIs from the default detector of the specified dataset are used as input. #### `Seq2SeqNMSLearner.eval` ```python From 881b9bc64994550b0df38a104d423c59c34eb352 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:43:28 +0200 Subject: [PATCH 216/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 945cac7a03..c05f573d6e 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -103,7 +103,8 @@ Parameters: - **datasets_folder**: *str, default='./datasets'*\ Specifies the path to the folder where the datasets are stored. - **use_ssd**: *bool, default=False*\ - If set to True, RoIs from SSD are fed to the seq2Seq-nms model. Otherwise, RoIs from the default detector of the specified dataset are used as input. + If set to True, RoIs from SSD are fed to the seq2Seq-nms model. + Otherwise, RoIs from the default detector of the specified dataset are used as input. #### `Seq2SeqNMSLearner.infer` ```python From 0702e2eebb7c58f6a89b0989627239aeda59f771 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:43:44 +0200 Subject: [PATCH 217/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index c05f573d6e..b2370ecff7 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -116,7 +116,8 @@ Performs non-maximum suppression, using seq2seq-nms. In the case where FMoD is s Parameters: - **boxes**: *torch.tensor, default=None*\ - Image coordinates of candidate detection RoIs, expressed as the coordinates of their upper-left and top-down corners (x_min, y_min, x_max, y_max). For N candidate detection RoIs, the size of the *torch.tensor* is Nx4. + Image coordinates of candidate detection RoIs, expressed as the coordinates of their upper-left and top-down corners (x_min, y_min, x_max, y_max). + For N candidate detection RoIs, the size of the *torch.tensor* is Nx4. - **scores**: *torch.tensor, default=None*\ Specifies the scores of the candidate detection RoIs, assigned previously by a detector. For N candidate detection RoIs, the size of the *torch.tensor* is Nx1. - **boxes_sorted**: *bool, default=False*\ From 87d4e372ae0a434f92024ee064de8c003ea655c7 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:43:55 +0200 Subject: [PATCH 218/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index b2370ecff7..f01ff3ee41 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -111,7 +111,8 @@ Parameters: Seq2SeqNMSLearner.infer(self, boxes, scores, boxes_sorted, max_dt_boxes, img_res, threshold) ``` -Performs non-maximum suppression, using seq2seq-nms. In the case where FMoD is selected for appearance-based RoI feature computation, FMoD maps are not computed. +Performs non-maximum suppression, using seq2seq-nms. +In the case where FMoD is selected for appearance-based RoI feature computation, FMoD maps are not computed. Parameters: From fca9a6c2fa18255f2cf195cc6a3591793cea1373 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:44:06 +0200 Subject: [PATCH 219/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index f01ff3ee41..203813efdc 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -120,7 +120,8 @@ Parameters: Image coordinates of candidate detection RoIs, expressed as the coordinates of their upper-left and top-down corners (x_min, y_min, x_max, y_max). For N candidate detection RoIs, the size of the *torch.tensor* is Nx4. - **scores**: *torch.tensor, default=None*\ - Specifies the scores of the candidate detection RoIs, assigned previously by a detector. For N candidate detection RoIs, the size of the *torch.tensor* is Nx1. + Specifies the scores of the candidate detection RoIs, assigned previously by a detector. + For N candidate detection RoIs, the size of the *torch.tensor* is Nx1. - **boxes_sorted**: *bool, default=False*\ Specifies whether *boxes* and *scores* are sorted based on *scores* in descending order. - **max_dt_boxes**: *int, default=400*\ From 19052962ed3804dba6d7fe30d016af4fdc261b2e Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:44:25 +0200 Subject: [PATCH 220/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 203813efdc..e843ff22bb 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -136,7 +136,8 @@ Parameters: Seq2SeqNMSLearner.run_nms(self, boxes, scores, img, threshold, boxes_sorted, top_k) ``` -Performs non-maximum suppression, using seq2seq-nms. It incorporates the full pipeline needed for inference. +Performs non-maximum suppression, using seq2seq-nms. +It incorporates the full pipeline needed for inference. Parameters: From 4e5da0a962a3d0198ddfbabe02bc0c7892d042cd Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:44:37 +0200 Subject: [PATCH 221/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index e843ff22bb..c2d38029b8 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -142,7 +142,8 @@ It incorporates the full pipeline needed for inference. Parameters: - **boxes**: *numpy.ndarray, default=None*\ - Image coordinates of candidate detection RoIs, expressed as the coordinates of their upper-left and top-down corners (x_min, y_min, x_max, y_max). For N candidate detection RoIs, the size of the array is Nx4. + Image coordinates of candidate detection RoIs, expressed as the coordinates of their upper-left and top-down corners (x_min, y_min, x_max, y_max). + For N candidate detection RoIs, the size of the array is Nx4. - **scores**: *numpy.ndarray, default=None*\ Specifies the scores of the candidate detection RoIs, assigned previously by a detector. For N candidate detection RoIs, the size of the array is Nx1. - **boxes_sorted**: *bool, default=False*\ From 43d0814be287e0023e13d38acfb6644c27002dbb Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:44:48 +0200 Subject: [PATCH 222/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index c2d38029b8..a0726578b9 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -145,7 +145,8 @@ Parameters: Image coordinates of candidate detection RoIs, expressed as the coordinates of their upper-left and top-down corners (x_min, y_min, x_max, y_max). For N candidate detection RoIs, the size of the array is Nx4. - **scores**: *numpy.ndarray, default=None*\ - Specifies the scores of the candidate detection RoIs, assigned previously by a detector. For N candidate detection RoIs, the size of the array is Nx1. + Specifies the scores of the candidate detection RoIs, assigned previously by a detector. + For N candidate detection RoIs, the size of the array is Nx1. - **boxes_sorted**: *bool, default=False*\ Specifies whether *boxes* and *scores* are sorted based on *scores* in descending order. - **top_k**: *int, default=400*\ From b78cda8c8f87a236e700fa4e10968c98d9e7ae77 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:45:00 +0200 Subject: [PATCH 223/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index a0726578b9..1beb35e863 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -167,7 +167,7 @@ Parameters: - **path**: *str*\ Specifies the folder where the model will be saved. -- **verbose**: *bool default=True*\ +- **verbose**: *bool default=False*\ If True, enables maximum verbosity. - **optimizer**: *torch.optim.Optimizer default=None*\ Specifies the optimizer used for training. From 0dff7c4c18cc64da80decc9f7a96cd9908e10f5c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:45:42 +0200 Subject: [PATCH 224/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 1beb35e863..4b5934f782 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -191,7 +191,7 @@ Parameters: - **path**: *str*\ Specifies the folder where the model will be loaded from. -- **verbose**: *bool default=True*\ +- **verbose**: *bool default=False*\ If True, enables maximum verbosity. From 5cbee3604ccf019dff7489c5bd0802bacd161af1 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:46:22 +0200 Subject: [PATCH 225/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 4b5934f782..953289a0e5 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -211,7 +211,8 @@ Parameters: - **path**: *str, default=None*\ Specifies the folder where data will be downloaded. If *None*, the *self.temp_path* directory is used instead. - **model_name**: *{'seq2seq_medium_pets_jpd_fmod_3', 'seq2seq_medium_pets_ssd_fmod_3', 'seq2seq_medium_coco_frcn_fmod_3', 'seq2seq_medium_pets_ssd_fmod_3'}, default=''seq2seq_medium_pets_jpd_fmod_3'*\ - If *'pretrained'*, downloads a pretrained detector model. If *'images'*, downloads an image to perform inference on. If + If *'pretrained'*, downloads a pretrained detector model. + If *'images'*, downloads an image to perform inference on. If *'test_data'* downloads a dummy dataset for testing purposes. - **verbose**: *bool default=True*\ If True, enables maximum verbosity. From c46c6173c0c7275d39d2f868b2b80a40314c9b02 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:46:45 +0200 Subject: [PATCH 226/374] Update docs/reference/object-detection-2d-nms-seq2seq_nms.md Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 953289a0e5..f4c860bab4 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -209,7 +209,8 @@ Downloads data needed for the various functions of the learner, e.g., pretrained Parameters: - **path**: *str, default=None*\ - Specifies the folder where data will be downloaded. If *None*, the *self.temp_path* directory is used instead. + Specifies the folder where data will be downloaded. + If *None*, the *self.temp_path* directory is used instead. - **model_name**: *{'seq2seq_medium_pets_jpd_fmod_3', 'seq2seq_medium_pets_ssd_fmod_3', 'seq2seq_medium_coco_frcn_fmod_3', 'seq2seq_medium_pets_ssd_fmod_3'}, default=''seq2seq_medium_pets_jpd_fmod_3'*\ If *'pretrained'*, downloads a pretrained detector model. If *'images'*, downloads an image to perform inference on. If From 46ea127c23084b760b0116ca21d5ef5b4d92e2a7 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:49:38 +0200 Subject: [PATCH 227/374] Create init --- .../perception/object_detection_2d/nms/init | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 src/opendr/perception/object_detection_2d/nms/init diff --git a/src/opendr/perception/object_detection_2d/nms/init b/src/opendr/perception/object_detection_2d/nms/init new file mode 100644 index 0000000000..61428cb1bd --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/init @@ -0,0 +1,16 @@ +from opendr.perception.object_detection_2d.centernet.centernet_learner import CenterNetDetectorLearner +from opendr.perception.object_detection_2d.detr.detr_learner import DetrLearner +from opendr.perception.object_detection_2d.gem.gem_learner import GemLearner +from opendr.perception.object_detection_2d.retinaface.retinaface_learner import RetinaFaceLearner +from opendr.perception.object_detection_2d.ssd.ssd_learner import SingleShotDetectorLearner +from opendr.perception.object_detection_2d.yolov3.yolov3_learner import YOLOv3DetectorLearner + +from opendr.perception.object_detection_2d.datasets.wider_person import WiderPersonDataset +from opendr.perception.object_detection_2d.datasets.wider_face import WiderFaceDataset +from opendr.perception.object_detection_2d.datasets import transforms + +from opendr.perception.object_detection_2d.utils.vis_utils import draw_bounding_boxes + +__all__ = ['CenterNetDetectorLearner', 'DetrLearner', 'GemLearner', 'RetinaFaceLearner', + 'SingleShotDetectorLearner', 'YOLOv3DetectorLearner', 'WiderPersonDataset', 'WiderFaceDataset', + 'transforms', 'draw_bounding_boxes'] From 55c807d1a460415ceb380e82ca326069139fdabe Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:55:09 +0200 Subject: [PATCH 228/374] Update and rename init to __init__.py --- .../object_detection_2d/nms/__init__.py | 11 +++++++++++ .../perception/object_detection_2d/nms/init | 16 ---------------- 2 files changed, 11 insertions(+), 16 deletions(-) create mode 100644 src/opendr/perception/object_detection_2d/nms/__init__.py delete mode 100644 src/opendr/perception/object_detection_2d/nms/init diff --git a/src/opendr/perception/object_detection_2d/nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/__init__.py new file mode 100644 index 0000000000..47b561dcdd --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/__init__.py @@ -0,0 +1,11 @@ +from opendr.perception.object_detection_2d.nms.cluster_nms import ClusterNMS +from opendr.perception.object_detection_2d.nms.fast_nms import FastNMS +from opendr.perception.object_detection_2d.nms.soft_nms import SoftNMS +from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner + +from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner.algorithm.fmod import FMoD +from opendr.perception.object_detection_2d.nms.seq2seq_nms.utils.dataset import Dataset_NMS + + +__all__ = ['ClusterNMS', 'FastNMS', 'SoftNMS', 'Seq2SeqNMSLearner', + 'FMoD', 'Dataset_NMS'] diff --git a/src/opendr/perception/object_detection_2d/nms/init b/src/opendr/perception/object_detection_2d/nms/init deleted file mode 100644 index 61428cb1bd..0000000000 --- a/src/opendr/perception/object_detection_2d/nms/init +++ /dev/null @@ -1,16 +0,0 @@ -from opendr.perception.object_detection_2d.centernet.centernet_learner import CenterNetDetectorLearner -from opendr.perception.object_detection_2d.detr.detr_learner import DetrLearner -from opendr.perception.object_detection_2d.gem.gem_learner import GemLearner -from opendr.perception.object_detection_2d.retinaface.retinaface_learner import RetinaFaceLearner -from opendr.perception.object_detection_2d.ssd.ssd_learner import SingleShotDetectorLearner -from opendr.perception.object_detection_2d.yolov3.yolov3_learner import YOLOv3DetectorLearner - -from opendr.perception.object_detection_2d.datasets.wider_person import WiderPersonDataset -from opendr.perception.object_detection_2d.datasets.wider_face import WiderFaceDataset -from opendr.perception.object_detection_2d.datasets import transforms - -from opendr.perception.object_detection_2d.utils.vis_utils import draw_bounding_boxes - -__all__ = ['CenterNetDetectorLearner', 'DetrLearner', 'GemLearner', 'RetinaFaceLearner', - 'SingleShotDetectorLearner', 'YOLOv3DetectorLearner', 'WiderPersonDataset', 'WiderFaceDataset', - 'transforms', 'draw_bounding_boxes'] From 2b7ef6eba98be771382e3462aa5e099d775a8eba Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:57:29 +0200 Subject: [PATCH 229/374] Delete dataset.py --- .../nms/seq2seq_nms/algorithm/dataset.py | 309 ------------------ 1 file changed, 309 deletions(-) delete mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py deleted file mode 100644 index 9103b0b46f..0000000000 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/dataset.py +++ /dev/null @@ -1,309 +0,0 @@ -# Copyright 2020-2022 OpenDR European Project -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -from opendr.engine.datasets import Dataset -import os -from urllib.request import urlretrieve -import time -from zipfile import ZipFile -import tarfile -import gdown -import shutil -import json -import cv2 -import pickle -import numpy as np -import math -from tqdm import tqdm - - -class Dataset_NMS(Dataset): - def __init__(self, path, dataset_name, split): - super().__init__() - - available_dataset = ['COCO', 'PETS', 'CrowdHuman'] - if dataset_name not in available_dataset: - except_str = 'Unsupported dataset: ' + dataset_name + '. Currently available are:' - for j in range(len(available_dataset)): - except_str = except_str + ' \'' + available_dataset[j] + '\'' - if j < len(available_dataset) - 1: - except_str = except_str + ',' - except_str = except_str + '.' - raise ValueError(except_str) - - self.dataset_name = dataset_name - self.split = split - # self.__prepare_dataset() - self.path = os.path.join(path, dataset_name) - self.src_data = [] - if self.dataset_name == "PETS": - if not os.path.exists(os.path.join(self.path, 'images/S1/L1')): - self.download( - 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S1_L1.tar.bz2', - download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) - if not os.path.exists(os.path.join(self.path, 'images/S1/L2')): - self.download( - 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S1_L2.tar.bz2', - download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) - if not os.path.exists(os.path.join(self.path, 'images/S2/L1')): - self.download( - 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L1.tar.bz2', - download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) - if not os.path.exists(os.path.join(self.path, 'images/S2/L2')): - self.download( - 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L2.tar.bz2', - download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) - if not os.path.exists(os.path.join(self.path, 'images/S2/L3')): - self.download( - 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S2_L3.tar.bz2', - download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) - if not os.path.exists(os.path.join(self.path, 'images/S3/Multiple_Flow')): - self.download( - 'http://ftp.cs.rdg.ac.uk/pub/PETS2009/Crowd_PETS09_dataset/a_data/Crowd_PETS09/S3_MF.tar.bz2', - download_path=os.path.join(self.path, 'images'), file_format="tar.bz2", create_dir=True) - splits = ['train', 'val', 'test'] - if self.split not in splits: - raise ValueError(self.split + ' is not available...') - if not os.path.exists(os.path.join(self.path, 'annotations', 'pets_' + self.split + '.json')): - self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_annotations_json.zip', - download_path=os.path.join(self.path, 'annotations'), file_format="zip", - create_dir=True) - if not os.path.exists(os.path.join(self.path, 'data_' + self.split + '_pets.pkl')): - if not os.path.exists( - os.path.join(self.path, 'detections', 'PETS-' + self.split + '_siyudpm_dets.idl')): - self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_detections.zip', - download_path=os.path.join(self.path, 'detections'), file_format="zip", - create_dir=True) - if not os.path.exists(os.path.join(self.path, 'annotations', 'PETS-' + self.split + '.idl')): - self.download('http://datasets.d2.mpi-inf.mpg.de/hosang17cvpr/PETS_annotations.zip', - download_path=os.path.join(self.path, 'annotations'), file_format="zip", - create_dir=True) - with open(os.path.join(self.path, 'detections', 'PETS-' + self.split + '_siyudpm_dets.idl')) as fp_dt, \ - open(os.path.join(self.path, 'annotations', 'PETS-' + self.split + '.idl')) as fp_gt: - print('Preparing PETS ' + self.split + ' set...') - current_id = 0 - number_samples = 1696 - if self.split == 'val': - current_id = 1696 - number_samples = 240 - elif self.split == 'test': - current_id = 1936 - number_samples = 436 - pbarDesc = "Overall progress" - pbar = tqdm(desc=pbarDesc, total=number_samples) - line_dt = fp_dt.readline() - line_gt = fp_gt.readline() - while line_dt and line_gt: - data_dt = line_dt.replace(':', ' ') - data_gt = line_gt.replace(':', ' ') - remove_strings = ['PETS09-', '\"', ':', '(', ')', ',', '', ';'] - for j in range(len(remove_strings)): - data_dt = data_dt.replace(remove_strings[j], '') - for j in range(len(remove_strings)): - data_gt = data_gt.replace(remove_strings[j], '') - data_dt = data_dt.split() - data_gt = data_gt.split() - filename_dt = data_dt[0][0:2] + '/' + data_dt[0][2:] - if filename_dt[0:6] == 'S2/L1/': - filename_dt = filename_dt.replace('img/00', 'Time_12-34/View_001/frame_') - num = int(filename_dt[-8:-4]) - 1 - filename_dt = filename_dt[:-8] + str(num).zfill(4) + '.jpg' - if filename_dt[0:6] == 'S2/L2/': - filename_dt = filename_dt.replace('img/00', 'Time_14-55/View_001/frame_') - num = int(filename_dt[-8:-4]) - 1 - filename_dt = filename_dt[:-8] + str(num).zfill(4) + '.jpg' - if filename_dt[0:2] == 'S3': - filename_dt = filename_dt.replace('_MF', 'Multiple_Flow') - - filename_gt = data_gt[0][0:2] + '/' + data_gt[0][2:] - if filename_gt[0:6] == 'S2/L1/': - filename_gt = filename_gt.replace('img/00', 'Time_12-34/View_001/frame_') - num = int(filename_gt[-8:-4]) - 1 - filename_gt = filename_gt[:-8] + str(num).zfill(4) + '.jpg' - if filename_gt[0:6] == 'S2/L2/': - filename_gt = filename_gt.replace('img/00', 'Time_14-55/View_001/frame_') - num = int(filename_gt[-8:-4]) - 1 - filename_gt = filename_gt[:-8] + str(num).zfill(4) + '.jpg' - if filename_gt[0:2] == 'S3': - filename_gt = filename_gt.replace('_MF', 'Multiple_Flow') - if filename_gt != filename_dt: - raise ValueError('Errors in files...') - img = cv2.imread(os.path.join(self.path, 'images/', filename_dt)) - dt_boxes = [] - for i in range(1, (len(data_dt)), 5): - dt_box = np.array((float(data_dt[i]), float(data_dt[i + 1]), float(data_dt[i + 2]), - float(data_dt[i + 3]), 1 / (1 + math.exp(- float(data_dt[i + 4]))))) - dt_boxes.append(dt_box) - gt_boxes = [] - for i in range(1, (len(data_gt)), 5): - gt_box = np.array((float(data_gt[i]), float(data_gt[i + 1]), float(data_gt[i + 2]), - float(data_gt[i + 3]))) - gt_boxes.append(gt_box) - self.src_data.append({ - 'id': current_id, - 'filename': filename_dt, - 'resolution': img.shape[0:2][::-1], - 'gt_boxes': [np.asarray([]), np.asarray(gt_boxes)], - 'dt_boxes': [np.asarray([]), np.asarray(dt_boxes)] - }) - current_id = current_id + 1 - pbar.update(1) - line_dt = fp_dt.readline() - line_gt = fp_gt.readline() - pbar.close() - with open(os.path.join(self.path, 'data_' + self.split + '_pets.pkl'), 'wb') as handle: - pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) - else: - with open(os.path.join(self.path, 'data_' + self.split + '_pets.pkl'), 'rb') as fp_dt: - self.src_data = pickle.load(fp_dt) - - self.classes = ['background', 'human'] - self.class_ids = {'background': 0, 'human': 1} - - elif self.dataset_name == "CrowdHuman": - if not os.path.exists(os.path.join(self.path, 'images/train')): - os.makedirs(os.path.join(self.path, 'images/train'), exist_ok=True) - urls = ['https://drive.google.com/uc?export=download&confirm=YZB1&id=134QOvaatwKdy0iIeNqA_p-xkAhkV4F8Y', - 'https://drive.google.com/u/0/uc?id=17evzPh7gc1JBNvnW1ENXLy5Kr4Q_Nnla', - 'https://drive.google.com/u/0/uc?id=1tdp0UCgxrqy1B6p8LkR-Iy0aIJ8l4fJW'] - outputs = ['CrowdHuman_train01.zip', 'CrowdHuman_train02.zip', 'CrowdHuman_train03.zip'] - for i in range(0, len(urls)): - gdown.download(urls[i], outputs[i], quiet=False) - zip_path = os.path.join('.', outputs[i]) - with ZipFile(zip_path, 'r') as zip_ref: - download_path = os.path.join(self.path, 'images', 'train') - zip_ref.extractall(download_path) - os.remove(zip_path) - - if not os.path.exists(os.path.join(self.path, 'images/val')): - os.makedirs(os.path.join(self.path, 'images/val'), exist_ok=True) - url = 'https://drive.google.com/u/0/uc?id=18jFI789CoHTppQ7vmRSFEdnGaSQZ4YzO' - output = 'CrowdHuman_val.zip' - gdown.download(url, output, quiet=False) - zip_path = os.path.join('.', output) - with ZipFile(zip_path, 'r') as zip_ref: - download_path = os.path.join(self.path, 'images', 'val') - zip_ref.extractall(download_path) - os.remove(zip_path) - - if not os.path.exists(os.path.join(self.path, 'data_train_crowdhuman.pkl')): - # Download detections from FTP server - - # Download annotations from official CrowdHuman GoogleDrive repo - if not os.path.exists(os.path.join(self.path, 'annotations', 'annotation_train.odgt')): - os.makedirs(os.path.join(self.path, 'annotations'), exist_ok=True) - urls = ['https://drive.google.com/u/0/uc?id=1UUTea5mYqvlUObsC1Z8CFldHJAtLtMX3&export=download', - 'https://drive.google.com/u/0/uc?id=10WIRwu8ju8GRLuCkZ_vT6hnNxs5ptwoL&export=download'] - outputs = ['annotation_train.odgt', 'annotation_val.odgt'] - gdown.download(urls[0], outputs[0], quiet=False) - shutil.move(os.path.join('.', outputs[0]), - os.path.join('.', 'datasets', 'CrowdHuman', 'annotations', 'train')) - gdown.download(urls[1], outputs[1], quiet=False) - shutil.move(os.path.join('.', outputs[1]), - os.path.join('.', 'datasets', 'CrowdHuman', 'annotations', 'val')) - - with open(os.path.join(self.path, 'annotations', 'annotation_train.odgt')) as fp_gt, open( - os.path.join(self.path, 'detections', 'det_data_train_crowdhuman.pkl'), 'rb') as fp_dt: - line = fp_gt.readline() - data_dt = pickle.load(fp_dt) - i = 0 - while line: - annotations = json.loads(line) - if data_dt[i]['id'] != annotations['ID']: - continue - img = cv2.imread(os.path.join(self.path, 'images/train', annotations['ID'] + '.jpg')) - gt_boxes = [] - for j in range(len(annotations['gtboxes'])): - if annotations['gtboxes'][j]['tag'] == 'person': - gt_box = annotations['gtboxes'][j]['fbox'] - gt_box[2] = gt_box[2] + gt_box[0] - gt_box[3] = gt_box[3] + gt_box[1] - gt_boxes.append(gt_box) - self.src_data.append({ - 'id': annotations['ID'], - 'filename': annotations['ID'] + '.jpg', - 'resolution': img.shape[0:2][::-1], - 'gt_boxes': np.asarray(gt_boxes), - 'dt_boxes': data_dt[i]['dt_boxes'], - }) - line = fp_gt.readline() - i = i + 1 - with open(os.path.join(self.path, 'data_train_crowdhuman.pkl'), 'wb') as handle: - pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) - else: - with open(os.path.join(self.path, 'data_train_crowdhuman.pkl'), 'rb') as fp_dt: - self.src_data = pickle.load(fp_dt) - - @staticmethod - def download( - url, download_path, dataset_sub_path=".", file_format="zip", create_dir=False): - - if create_dir: - os.makedirs(download_path, exist_ok=True) - - print("Downloading dataset from", url, "to", download_path) - - start_time = 0 - last_print = 0 - - def reporthook(count, block_size, total_size): - nonlocal start_time - nonlocal last_print - if count == 0: - start_time = time.time() - last_print = start_time - return - - duration = time.time() - start_time - progress_size = int(count * block_size) - speed = int(progress_size / (1024 * duration)) - if time.time() - last_print >= 1: - last_print = time.time() - print( - "\r%d MB, %d KB/s, %d seconds passed" % - (progress_size / (1024 * 1024), speed, duration), - end='' - ) - - if file_format == "zip": - zip_path = os.path.join(download_path, "dataset.zip") - urlretrieve(url, zip_path, reporthook=reporthook) - print() - print("Extracting data from zip file") - with ZipFile(zip_path, 'r') as zip_ref: - zip_ref.extractall(download_path) - os.remove(zip_path) - elif file_format == "tar.bz2": - tar_path = os.path.join(download_path, "dataset.tar.bz2") - urlretrieve(url, tar_path, reporthook=reporthook) - print() - - def members(tf): - l = len("Crowd_PETS09/") - for member in tf.getmembers(): - if member.path.startswith("Crowd_PETS09/"): - member.path = member.path[l:] - yield member - - with tarfile.open(tar_path, "r:bz2") as tar: - tar.extractall(path=download_path, members=members(tar)) - tar.close() - os.remove(tar_path) - else: - raise ValueError("Unsupported file_format: " + file_format) - - # def __prepare_dataset(self): - # seq_root = os.path.join(self.path, "images/train") - # label_root = os.path.join(self.path, "labels/test") From e0d7a2aec7b8ecf7e2d23b35dcd19c00c4608c08 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 13:59:04 +0200 Subject: [PATCH 230/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 653f4d00f9..844acee629 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -17,8 +17,8 @@ from opendr.engine.target import BoundingBox, BoundingBoxList from opendr.engine.data import Image from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet -from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.fmod import FMoD -from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS +from opendr.perception.object_detection_2d.nms import FMoD +from opendr.perception.object_detection_2d.nms import Dataset_NMS from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS From b741bb2baf51ac180d378796f05b408ef8c5dc70 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:03:08 +0200 Subject: [PATCH 231/374] Update train_demo.py --- .../nms/seq2seq-nms/train_demo.py | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py index bef6c9b6dd..d4b959fb4d 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py @@ -13,23 +13,23 @@ # limitations under the License. -from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner +from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner import os OPENDR_HOME = os.environ['OPENDR_HOME'] - parser = argparse.ArgumentParser() - parser.add_argument("--dataset", help="Dataset to train on", type=str, default="voc", choices=["PETS", "COCO", - "TEST_MODULE"]) - parser.add_argument("--data_root", help="Dataset root folder", type=str) - parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cuda", choices=["cuda", "cpu"]) - parser.add_argument("--max_dt_boxes", help="Maximum number of input RoIs to Seq2Seq-NMS", type=int, default=450) - parser.add_argument("--nms_gt_iou", help="Learning rate to use for training", type=float, default=5e-4) - parser.add_argument("--val-after", help="Epochs in-between evaluations", type=int, default=5) - parser.add_argument("--checkpoint-freq", help="Frequency in-between checkpoint saving", type=int, default=5) - parser.add_argument("--n-epochs", help="Number of total epochs", type=int, default=25) - parser.add_argument("--resume-from", help="Epoch to load checkpoint file and resume training from", type=int, default=0) +parser = argparse.ArgumentParser() +parser.add_argument("--dataset", help="Dataset to train on", type=str, default="voc", choices=["PETS", "COCO", + "TEST_MODULE"]) +parser.add_argument("--data_root", help="Dataset root folder", type=str) +parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cuda", choices=["cuda", "cpu"]) +parser.add_argument("--max_dt_boxes", help="Maximum number of input RoIs to Seq2Seq-NMS", type=int, default=450) +parser.add_argument("--nms_gt_iou", help="Learning rate to use for training", type=float, default=5e-4) +parser.add_argument("--val-after", help="Epochs in-between evaluations", type=int, default=5) +parser.add_argument("--checkpoint-freq", help="Frequency in-between checkpoint saving", type=int, default=5) +parser.add_argument("--n-epochs", help="Number of total epochs", type=int, default=25) +parser.add_argument("--resume-from", help="Epoch to load checkpoint file and resume training from", type=int, default=0) - args = parser.parse_args() +args = parser.parse_args() seq2seq_tmp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/coco_tmp' seq2seq_logs_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/coco_logs' From e3778ee10c3dcfa3935244326db34a316b847d63 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:03:23 +0200 Subject: [PATCH 232/374] Update train_demo.py --- .../object_detection_2d/nms/seq2seq-nms/train_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py index d4b959fb4d..55edce4c33 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py @@ -37,6 +37,6 @@ seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=None, app_feats='fmod', checkpoint_after_iter=1, temp_path=seq2seq_tmp_path, epochs=8) seq2SeqNMSLearner.fit(dataset=args.dataset, use_ssd=False, - datasets_folder= args.data_root, + datasets_folder=args.data_root, logging_path=seq2seq_logs_path, silent=False, verbose=True, nms_gt_iou=0.50, max_dt_boxes=args.max_dt_boxes) From b5cac43c7e41c676f99740c8c9198644da21ba93 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:20:18 +0200 Subject: [PATCH 233/374] Update object_detection_2d_ssd.py --- .../src/perception/scripts/object_detection_2d_ssd.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py index 6cd9e05026..5cf533aa62 100755 --- a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py +++ b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py @@ -22,10 +22,8 @@ from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes -from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner -from opendr.perception.object_detection_2d.nms.soft_nms.soft_nms import SoftNMS -from opendr.perception.object_detection_2d.nms.fast_nms.fast_nms import FastNMS -from opendr.perception.object_detection_2d.nms.cluster_nms.cluster_nms import ClusterNMS +from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner, SoftNMS, FastNMS, ClusterNMS + class ObjectDetectionSSDNode: From 2eb2640377b021f54ffdcf81eb2dbc491df72fdc Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:22:33 +0200 Subject: [PATCH 234/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index f4c860bab4..4da3c14378 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -226,7 +226,7 @@ Parameters: To train seq2seq-nms properly, the PETS and COCO datasets are supported as Dataset_NMS types. ```python - from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner + from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner import os OPENDR_HOME = os.environ['OPENDR_HOME'] @@ -244,7 +244,7 @@ Parameters: * **Inference and result drawing example on a test .jpg image using OpenCV.** ```python - from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner + from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes From 9928147baf82db727b3f77248ef46d530df89549 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:24:47 +0200 Subject: [PATCH 235/374] Update inference_demo.py --- .../object_detection_2d/nms/cluster_nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py index f8273b0582..25cefa627c 100644 --- a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py @@ -13,7 +13,7 @@ # limitations under the License. -from opendr.perception.object_detection_2d.nms.cluster_nms.cluster_nms import ClusterNMS +from opendr.perception.object_detection_2d.nms import ClusterNMS from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes From 215a905694c35d38808daea83cbef3a0628db49b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:25:28 +0200 Subject: [PATCH 236/374] Update inference_demo.py --- .../object_detection_2d/nms/fast_nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py index 0c0648a921..d277520567 100644 --- a/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py @@ -13,7 +13,7 @@ # limitations under the License. -from opendr.perception.object_detection_2d.nms.fast_nms.fast_nms import FastNMS +from opendr.perception.object_detection_2d.nms import FastNMS from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes From d6a263bb98bd296d01a011ad57fb6dd17e796837 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:25:46 +0200 Subject: [PATCH 237/374] Update inference_demo.py --- .../object_detection_2d/nms/seq2seq-nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index 9f03339366..a511b2d298 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -13,7 +13,7 @@ # limitations under the License. -from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner +from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes From ec2b4946c18ad2233ebcfb003e7f9bc8d9b5bbfb Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:28:19 +0200 Subject: [PATCH 238/374] Update eval_demo.py --- .../perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py index ca87cc4d25..4460f5d122 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner +from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner import os OPENDR_HOME = os.environ['OPENDR_HOME'] temp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/pets_tmp' From f6fac961256e2c8d67ca596d5273b024b06bb996 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:28:35 +0200 Subject: [PATCH 239/374] Update inference_demo.py --- .../object_detection_2d/nms/soft_nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py index 004fa5f41e..c79e885b2c 100644 --- a/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py @@ -13,7 +13,7 @@ # limitations under the License. -from opendr.perception.object_detection_2d.nms.soft_nms.soft_nms import SoftNMS +from opendr.perception.object_detection_2d.nms import SoftNMS from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes From caf4f36fa7f2d6bad17a21ee123d9f92369d75b5 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:29:17 +0200 Subject: [PATCH 240/374] Update src/opendr/perception/object_detection_2d/datasets/transforms.py Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- src/opendr/perception/object_detection_2d/datasets/transforms.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/datasets/transforms.py b/src/opendr/perception/object_detection_2d/datasets/transforms.py index 06d03fadaf..08c0f34ecf 100644 --- a/src/opendr/perception/object_detection_2d/datasets/transforms.py +++ b/src/opendr/perception/object_detection_2d/datasets/transforms.py @@ -154,7 +154,6 @@ def pad_test(img, min_size=512): img_padded = mx.nd.pad(img, mode="constant", constant_value=0, pad_width=(0, 0, 0, 0, h_pad_size, h_pad_size, 0, 0)) - # img_mx = np.pad(img_mx, ((h_pad_size, h_pad_size), (0, 0), (0, 0))) else: img_padded = mx.nd.pad(img, mode="constant", constant_value=0, pad_width=(0, 0, 0, 0, 0, 0, From 8f3a6f48c4e632f46ee67f8ad4ee74809d7fd18f Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:32:16 +0200 Subject: [PATCH 241/374] Update fast_nms.py --- .../perception/object_detection_2d/nms/fast_nms/fast_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py index 31de9383c2..543e27e8d4 100644 --- a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard from opendr.engine.target import BoundingBox, BoundingBoxList import torch From 1c165e7d99225fa50d42471eab58328346c4f4f7 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:33:48 +0200 Subject: [PATCH 242/374] Update __init__.py --- src/opendr/perception/object_detection_2d/nms/__init__.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/__init__.py index 47b561dcdd..e0e28c42d6 100644 --- a/src/opendr/perception/object_detection_2d/nms/__init__.py +++ b/src/opendr/perception/object_detection_2d/nms/__init__.py @@ -5,7 +5,8 @@ from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner.algorithm.fmod import FMoD from opendr.perception.object_detection_2d.nms.seq2seq_nms.utils.dataset import Dataset_NMS +from opendr.perception.object_detection_2d.nms.seq2seq_nms.utils.nms_custom import NMSCustom __all__ = ['ClusterNMS', 'FastNMS', 'SoftNMS', 'Seq2SeqNMSLearner', - 'FMoD', 'Dataset_NMS'] + 'FMoD', 'Dataset_NMS', 'NMSCustom'] From 460eebdee15d6c9b3abdca7fab76b898819729a9 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:34:07 +0200 Subject: [PATCH 243/374] Update cluster_nms.py --- .../object_detection_2d/nms/cluster_nms/cluster_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index cfbea222d5..bbca8790ee 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard, diou, distance from opendr.engine.target import BoundingBox, BoundingBoxList import numpy as np From 85de18527e7c829b4c3f910cba2a335cab8fdd49 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:34:32 +0200 Subject: [PATCH 244/374] Update soft_nms.py --- .../perception/object_detection_2d/nms/soft_nms/soft_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py index 539de5388f..ce1a6578ba 100644 --- a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard from opendr.engine.target import BoundingBox, BoundingBoxList import torch From 46e24f62c9ee99a8cfff0ce552892ed18ab677b7 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:34:54 +0200 Subject: [PATCH 245/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 844acee629..3dd94d7211 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -19,7 +19,7 @@ from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet from opendr.perception.object_detection_2d.nms import FMoD from opendr.perception.object_detection_2d.nms import Dataset_NMS -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS import torch From 7ad68bd6a3c5535b60d15ce576962e2f84d18cee Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:37:12 +0200 Subject: [PATCH 246/374] Update ssd_learner.py --- src/opendr/perception/object_detection_2d/ssd/ssd_learner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py index c7e64fab9c..1b4b8416d0 100644 --- a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py +++ b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py @@ -46,7 +46,7 @@ from opendr.perception.object_detection_2d.datasets.transforms import ImageToNDArrayTransform, \ BoundingBoxListToNumpyArray, \ transform_test, pad_test -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms import NMSCustom gutils.random.seed(0) From 0ae128d5a5d975b1d99f543a390fc334a04efac3 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:37:40 +0200 Subject: [PATCH 247/374] Update test_seq2seq_nms.py --- .../object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index 2c20980d0c..46a9a5465f 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -17,8 +17,8 @@ import shutil import os import numpy as np -from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner -from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS +from opendr.perception.object_detection_2d.nmsr import Seq2SeqNMSLearner +from opendr.perception.object_detection_2d.nms import Dataset_NMS from opendr.engine.data import Image From 72465c1585da9e0e304d90702b55a7766af1bffe Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:43:32 +0200 Subject: [PATCH 248/374] Update object_detection_2d_ssd.py --- .../opendr_ws/src/perception/scripts/object_detection_2d_ssd.py | 1 - 1 file changed, 1 deletion(-) diff --git a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py index 5cf533aa62..26c039c21a 100755 --- a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py +++ b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py @@ -25,7 +25,6 @@ from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner, SoftNMS, FastNMS, ClusterNMS - class ObjectDetectionSSDNode: def __init__(self, input_image_topic="/usb_cam/image_raw", output_image_topic="/opendr/image_boxes_annotated", detections_topic="/opendr/objects", device="cuda", backbone="vgg16_atrous", nms_type='default'): From 91786db0a66cd888b7fe954a0cc2b5cbd4b571a0 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 14:47:19 +0200 Subject: [PATCH 249/374] Update train_demo.py --- .../perception/object_detection_2d/nms/seq2seq-nms/train_demo.py | 1 + 1 file changed, 1 insertion(+) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py index 55edce4c33..834ce39325 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py @@ -15,6 +15,7 @@ from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner import os +import argparse OPENDR_HOME = os.environ['OPENDR_HOME'] parser = argparse.ArgumentParser() From 229b2b0c9a05cac0f5b048e63285f9c5e6f6c857 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 15:11:11 +0200 Subject: [PATCH 250/374] Update __init__.py --- src/opendr/perception/object_detection_2d/nms/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/__init__.py index e0e28c42d6..f6109b4ceb 100644 --- a/src/opendr/perception/object_detection_2d/nms/__init__.py +++ b/src/opendr/perception/object_detection_2d/nms/__init__.py @@ -1,6 +1,6 @@ -from opendr.perception.object_detection_2d.nms.cluster_nms import ClusterNMS -from opendr.perception.object_detection_2d.nms.fast_nms import FastNMS -from opendr.perception.object_detection_2d.nms.soft_nms import SoftNMS +from opendr.perception.object_detection_2d.nms.cluster_nms.cluster_nms import ClusterNMS +from opendr.perception.object_detection_2d.nms.fast_nms.fast_nms import FastNMS +from opendr.perception.object_detection_2d.nms.soft_nms.soft_nms import SoftNMS from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner.algorithm.fmod import FMoD From 46b150a7c808cb04e73dd3143fbc5e972d8a0416 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 15:31:16 +0200 Subject: [PATCH 251/374] Update __init__.py --- src/opendr/perception/object_detection_2d/nms/__init__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/__init__.py index f6109b4ceb..e2c68806d8 100644 --- a/src/opendr/perception/object_detection_2d/nms/__init__.py +++ b/src/opendr/perception/object_detection_2d/nms/__init__.py @@ -4,8 +4,8 @@ from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner.algorithm.fmod import FMoD -from opendr.perception.object_detection_2d.nms.seq2seq_nms.utils.dataset import Dataset_NMS -from opendr.perception.object_detection_2d.nms.seq2seq_nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom __all__ = ['ClusterNMS', 'FastNMS', 'SoftNMS', 'Seq2SeqNMSLearner', From 0788c8f11021090e5253cc033ee2d467f586c325 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 15:57:52 +0200 Subject: [PATCH 252/374] Update cluster_nms.py --- .../object_detection_2d/nms/cluster_nms/cluster_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index bbca8790ee..cfbea222d5 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms import NMSCustom +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard, diou, distance from opendr.engine.target import BoundingBox, BoundingBoxList import numpy as np From dd361157f44dae9027131170b3b2b34e9cd24b07 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 17:27:44 +0200 Subject: [PATCH 253/374] Update fast_nms.py --- .../perception/object_detection_2d/nms/fast_nms/fast_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py index 543e27e8d4..31de9383c2 100644 --- a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms import NMSCustom +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard from opendr.engine.target import BoundingBox, BoundingBoxList import torch From 34538eb2b0f3f22dfc6330ee18669fbf71ed5847 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 17:28:07 +0200 Subject: [PATCH 254/374] Update soft_nms.py --- .../perception/object_detection_2d/nms/soft_nms/soft_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py index ce1a6578ba..539de5388f 100644 --- a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms import NMSCustom +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard from opendr.engine.target import BoundingBox, BoundingBoxList import torch From 654438388d316ecbb5974840eb31d726a8e91743 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 17:29:03 +0200 Subject: [PATCH 255/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 3dd94d7211..593aa8810a 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -17,9 +17,7 @@ from opendr.engine.target import BoundingBox, BoundingBoxList from opendr.engine.data import Image from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet -from opendr.perception.object_detection_2d.nms import FMoD -from opendr.perception.object_detection_2d.nms import Dataset_NMS -from opendr.perception.object_detection_2d.nms import NMSCustom +from opendr.perception.object_detection_2d.nms import FMoD, Dataset_NMS, NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS import torch From 6422e6111965e939720e7878a98a48ee0097b01d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 17:38:07 +0200 Subject: [PATCH 256/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 593aa8810a..a2362cf048 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -17,7 +17,8 @@ from opendr.engine.target import BoundingBox, BoundingBoxList from opendr.engine.data import Image from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet -from opendr.perception.object_detection_2d.nms import FMoD, Dataset_NMS, NMSCustom +from opendr.perception.object_detection_2d.nms import FMoD, Dataset_NMS +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS import torch From 8a6388e3f2ca01ae82e78b32077270aeee748b76 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 18:28:17 +0200 Subject: [PATCH 257/374] Update __init__.py --- src/opendr/perception/object_detection_2d/nms/__init__.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/__init__.py index e2c68806d8..4ecbe91ef2 100644 --- a/src/opendr/perception/object_detection_2d/nms/__init__.py +++ b/src/opendr/perception/object_detection_2d/nms/__init__.py @@ -3,10 +3,8 @@ from opendr.perception.object_detection_2d.nms.soft_nms.soft_nms import SoftNMS from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner -from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner.algorithm.fmod import FMoD from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom -__all__ = ['ClusterNMS', 'FastNMS', 'SoftNMS', 'Seq2SeqNMSLearner', - 'FMoD', 'Dataset_NMS', 'NMSCustom'] +__all__ = ['ClusterNMS', 'FastNMS', 'SoftNMS', 'Seq2SeqNMSLearner', 'Dataset_NMS', 'NMSCustom'] From 2246b456c9d342183a8895051d5ccbc34b69c9ac Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 18:29:40 +0200 Subject: [PATCH 258/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index a2362cf048..8fd25ae69f 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -17,8 +17,9 @@ from opendr.engine.target import BoundingBox, BoundingBoxList from opendr.engine.data import Image from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet -from opendr.perception.object_detection_2d.nms import FMoD, Dataset_NMS +from opendr.perception.object_detection_2d.nms import Dataset_NMS from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner.algorithm.fmod import FMoD from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS import torch From d1129f1d3517abbef755dc83a07ffad04121e825 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 19:22:12 +0200 Subject: [PATCH 259/374] Update __init__.py --- src/opendr/perception/object_detection_2d/nms/__init__.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/__init__.py index 4ecbe91ef2..60903cd475 100644 --- a/src/opendr/perception/object_detection_2d/nms/__init__.py +++ b/src/opendr/perception/object_detection_2d/nms/__init__.py @@ -3,8 +3,4 @@ from opendr.perception.object_detection_2d.nms.soft_nms.soft_nms import SoftNMS from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner -from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom - - -__all__ = ['ClusterNMS', 'FastNMS', 'SoftNMS', 'Seq2SeqNMSLearner', 'Dataset_NMS', 'NMSCustom'] +__all__ = ['ClusterNMS', 'FastNMS', 'SoftNMS', 'Seq2SeqNMSLearner'] From 775e1c22c6da140b0237702bcb29923778677542 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 19:22:47 +0200 Subject: [PATCH 260/374] Create __init__.py --- .../perception/object_detection_2d/nms/utils/__init__.py | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 src/opendr/perception/object_detection_2d/nms/utils/__init__.py diff --git a/src/opendr/perception/object_detection_2d/nms/utils/__init__.py b/src/opendr/perception/object_detection_2d/nms/utils/__init__.py new file mode 100644 index 0000000000..ee87091f8b --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/utils/__init__.py @@ -0,0 +1,5 @@ +from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom + + +__all__ = ['Dataset_NMS', 'NMSCustom'] From 56c0413c37cbf8de74760592fd7154355a827623 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 19:23:39 +0200 Subject: [PATCH 261/374] Update cluster_nms.py --- .../object_detection_2d/nms/cluster_nms/cluster_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index cfbea222d5..8c5185a191 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.utils import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard, diou, distance from opendr.engine.target import BoundingBox, BoundingBoxList import numpy as np From 89a0fe8dca726f5c842f0e10e6ae1b8416b5b29a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 19:23:51 +0200 Subject: [PATCH 262/374] Update fast_nms.py --- .../perception/object_detection_2d/nms/fast_nms/fast_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py index 31de9383c2..7777a0f422 100644 --- a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.utils import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard from opendr.engine.target import BoundingBox, BoundingBoxList import torch From 87d5b1d84779cb3d89bae7112dab48f1e72d0db1 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 19:24:08 +0200 Subject: [PATCH 263/374] Update soft_nms.py --- .../perception/object_detection_2d/nms/soft_nms/soft_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py index 539de5388f..737960b7d1 100644 --- a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.utils import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard from opendr.engine.target import BoundingBox, BoundingBoxList import torch From 4ecf38224ad86c169291f8a1e1bb6fb38713901c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 19:24:52 +0200 Subject: [PATCH 264/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 8fd25ae69f..29000319c9 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -17,8 +17,7 @@ from opendr.engine.target import BoundingBox, BoundingBoxList from opendr.engine.data import Image from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet -from opendr.perception.object_detection_2d.nms import Dataset_NMS -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.utils import NMSCustom, Dataset_NMS from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner.algorithm.fmod import FMoD from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS From 02a2cf4982c03d9e27329c09f027b2f029c50a23 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 19:26:50 +0200 Subject: [PATCH 265/374] Update test_seq2seq_nms.py --- .../object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index 46a9a5465f..91ab90b511 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -17,8 +17,8 @@ import shutil import os import numpy as np -from opendr.perception.object_detection_2d.nmsr import Seq2SeqNMSLearner -from opendr.perception.object_detection_2d.nms import Dataset_NMS +from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner +from opendr.perception.object_detection_2d.nms.utils import Dataset_NMS from opendr.engine.data import Image From 45ea106bffc945fa84128b5735132833ba54dd4f Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 19:28:08 +0200 Subject: [PATCH 266/374] Update ssd_learner.py --- src/opendr/perception/object_detection_2d/ssd/ssd_learner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py index 1b4b8416d0..41c79eee94 100644 --- a/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py +++ b/src/opendr/perception/object_detection_2d/ssd/ssd_learner.py @@ -46,7 +46,7 @@ from opendr.perception.object_detection_2d.datasets.transforms import ImageToNDArrayTransform, \ BoundingBoxListToNumpyArray, \ transform_test, pad_test -from opendr.perception.object_detection_2d.nms import NMSCustom +from opendr.perception.object_detection_2d.nms.utils import NMSCustom gutils.random.seed(0) From 2c658336f99224cc971cd1f2150bcff55bfb3358 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 19:54:48 +0200 Subject: [PATCH 267/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index a4ea722319..f71548ebff 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -13,7 +13,7 @@ # limitations under the License. from opendr.engine.datasets import Dataset -from opendr.perception.object_detection_2d import SingleShotDetectorLearner +from opendr.perception.object_detection_2d.ssd.ssd_learner import SingleShotDetectorLearner from opendr.engine.data import Image from opendr.perception.object_detection_2d.datasets.transforms import BoundingBoxListToNumpyArray from opendr.engine.constants import OPENDR_SERVER_URL From 69c382ca002ae02f471dce417a84b2d297bafd82 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 20:50:09 +0200 Subject: [PATCH 268/374] Delete __init__.py --- .../perception/object_detection_2d/nms/utils/__init__.py | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 src/opendr/perception/object_detection_2d/nms/utils/__init__.py diff --git a/src/opendr/perception/object_detection_2d/nms/utils/__init__.py b/src/opendr/perception/object_detection_2d/nms/utils/__init__.py deleted file mode 100644 index ee87091f8b..0000000000 --- a/src/opendr/perception/object_detection_2d/nms/utils/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom - - -__all__ = ['Dataset_NMS', 'NMSCustom'] From f5737d657e91ffa2403b95456a06221e2dab041b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 20:50:37 +0200 Subject: [PATCH 269/374] Update cluster_nms.py --- .../object_detection_2d/nms/cluster_nms/cluster_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index 8c5185a191..cfbea222d5 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms.utils import NMSCustom +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard, diou, distance from opendr.engine.target import BoundingBox, BoundingBoxList import numpy as np From 2ce5f4ac20f8a5137af7166989e3f4de8a9d63ed Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 20:51:19 +0200 Subject: [PATCH 270/374] Update cluster_nms.py --- .../object_detection_2d/nms/cluster_nms/cluster_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index cfbea222d5..8c5185a191 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.utils import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard, diou, distance from opendr.engine.target import BoundingBox, BoundingBoxList import numpy as np From 0bbbf0b4919692777fe8af50f62e57bbe2f71707 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 20:52:29 +0200 Subject: [PATCH 271/374] Create __init__.py --- .../perception/object_detection_2d/nms/utils/__init__.py | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/opendr/perception/object_detection_2d/nms/utils/__init__.py diff --git a/src/opendr/perception/object_detection_2d/nms/utils/__init__.py b/src/opendr/perception/object_detection_2d/nms/utils/__init__.py new file mode 100644 index 0000000000..e610cee0fd --- /dev/null +++ b/src/opendr/perception/object_detection_2d/nms/utils/__init__.py @@ -0,0 +1,6 @@ +from opendr.perception.object_detection_2d.nms.cluster_nms.utis.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.fast_nms.fast_nms import FastNMS +from opendr.perception.object_detection_2d.nms.soft_nms.soft_nms import SoftNMS +from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner + +__all__ = ['NMSCustom'] From 1fb206ac1b4c955b830a64d91440bd11c33c8248 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 20:53:48 +0200 Subject: [PATCH 272/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 29000319c9..75bd730f06 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -17,7 +17,8 @@ from opendr.engine.target import BoundingBox, BoundingBoxList from opendr.engine.data import Image from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet -from opendr.perception.object_detection_2d.nms.utils import NMSCustom, Dataset_NMS +from opendr.perception.object_detection_2d.nms.utils import NMSCustom +from opendr.perception.object_detection_2d.nms.utils.dataset import NMS_Dataset from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner.algorithm.fmod import FMoD from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS From 6b685428abf70868cbfa9dc4290af5ff9a9444e3 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 20:55:00 +0200 Subject: [PATCH 273/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 75bd730f06..59553afe5b 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -18,7 +18,7 @@ from opendr.engine.data import Image from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet from opendr.perception.object_detection_2d.nms.utils import NMSCustom -from opendr.perception.object_detection_2d.nms.utils.dataset import NMS_Dataset +from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner.algorithm.fmod import FMoD from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS From 6b80546b05cea34c4db1b957f266be190911bcbb Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 20:57:53 +0200 Subject: [PATCH 274/374] Update __init__.py --- .../perception/object_detection_2d/nms/utils/__init__.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/__init__.py b/src/opendr/perception/object_detection_2d/nms/utils/__init__.py index e610cee0fd..ad87346ce3 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/__init__.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/__init__.py @@ -1,6 +1,3 @@ from opendr.perception.object_detection_2d.nms.cluster_nms.utis.nms_custom import NMSCustom -from opendr.perception.object_detection_2d.nms.fast_nms.fast_nms import FastNMS -from opendr.perception.object_detection_2d.nms.soft_nms.soft_nms import SoftNMS -from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner __all__ = ['NMSCustom'] From b5878fb82758b03aa7f2801f71bb1be6b306f41d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 21:28:01 +0200 Subject: [PATCH 275/374] Update __init__.py --- src/opendr/perception/object_detection_2d/nms/utils/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/__init__.py b/src/opendr/perception/object_detection_2d/nms/utils/__init__.py index ad87346ce3..83d7848fb8 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/__init__.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/__init__.py @@ -1,3 +1,3 @@ -from opendr.perception.object_detection_2d.nms.cluster_nms.utis.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.cluster_nms.utils.nms_custom import NMSCustom __all__ = ['NMSCustom'] From 189b51efe035d3e06d0e009609ab45723ca25ce9 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 21:49:45 +0200 Subject: [PATCH 276/374] Update __init__.py --- src/opendr/perception/object_detection_2d/nms/utils/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/__init__.py b/src/opendr/perception/object_detection_2d/nms/utils/__init__.py index 83d7848fb8..2d130e14b8 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/__init__.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/__init__.py @@ -1,3 +1,3 @@ -from opendr.perception.object_detection_2d.nms.cluster_nms.utils.nms_custom import NMSCustom +from opendr.perception.object_detection_2d.nms.utils.nms_custom import NMSCustom __all__ = ['NMSCustom'] From 826a67910b0d25ff35c786d34b18536f22269fd8 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 21 Mar 2022 22:38:29 +0200 Subject: [PATCH 277/374] Update seq2seq_nms_learner.py --- .../object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 59553afe5b..00ae01a4c1 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -19,7 +19,7 @@ from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.seq2seq_model import Seq2SeqNet from opendr.perception.object_detection_2d.nms.utils import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS -from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner.algorithm.fmod import FMoD +from opendr.perception.object_detection_2d.nms.seq2seq_nms.algorithm.fmod import FMoD from opendr.perception.object_detection_2d.nms.utils.nms_utils import drop_dets, det_matching, \ run_coco_eval, filter_iou_boxes, bb_intersection_over_union, compute_class_weights, apply_torchNMS import torch From 10baef03fbbb02b898ee1e7c756d64f5aae1b6d6 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 00:00:59 +0200 Subject: [PATCH 278/374] Update test_seq2seq_nms.py --- .../object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index 91ab90b511..f032cc5210 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -18,7 +18,7 @@ import os import numpy as np from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner -from opendr.perception.object_detection_2d.nms.utils import Dataset_NMS +from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS from opendr.engine.data import Image From e698640d8f8ed1554820db9bcea922c0e0618328 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 11:01:27 +0200 Subject: [PATCH 279/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index f71548ebff..6bfad909a9 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -13,7 +13,6 @@ # limitations under the License. from opendr.engine.datasets import Dataset -from opendr.perception.object_detection_2d.ssd.ssd_learner import SingleShotDetectorLearner from opendr.engine.data import Image from opendr.perception.object_detection_2d.datasets.transforms import BoundingBoxListToNumpyArray from opendr.engine.constants import OPENDR_SERVER_URL @@ -99,6 +98,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic if not os.path.exists(pkl_filename): ssd = None if use_ssd: + from opendr.perception.object_detection_2d.ssd.ssd_learner import SingleShotDetectorLearner ssd = SingleShotDetectorLearner(device=device) ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) @@ -233,6 +233,7 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic if use_ssd: self.detector = 'SSD' self.detector_type = 'custom' + from opendr.perception.object_detection_2d.ssd.ssd_learner import SingleShotDetectorLearner ssd = SingleShotDetectorLearner(device=device) ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) From 0f2fa213fd3578fabeed9974be3ae98ce80d5d4f Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 15:01:38 +0200 Subject: [PATCH 280/374] Update cluster_nms.py --- .../nms/cluster_nms/cluster_nms.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index 8c5185a191..9efcb1a8be 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -12,6 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +# This file contains code frin the CIoU distribution (https://github.com/Zzh-tju/CIoU). +# Copyright (c) 2020 Zheng, Zhaohui. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from opendr.perception.object_detection_2d.nms.utils import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard, diou, distance from opendr.engine.target import BoundingBox, BoundingBoxList From 70ac29ab6e01519dbefed1d640c903e068c387a1 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 15:02:11 +0200 Subject: [PATCH 281/374] Update fast_nms.py --- .../object_detection_2d/nms/fast_nms/fast_nms.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py index 7777a0f422..f2276bc968 100644 --- a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py @@ -12,6 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +# This file contains code frin the CIoU distribution (https://github.com/Zzh-tju/CIoU). +# Copyright (c) 2020 Zheng, Zhaohui. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + from opendr.perception.object_detection_2d.nms.utils import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard from opendr.engine.target import BoundingBox, BoundingBoxList From 28c372f3ddd7c0678a1adf167f6fe8047ff52163 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 15:02:22 +0200 Subject: [PATCH 282/374] Update fast_nms.py --- .../perception/object_detection_2d/nms/fast_nms/fast_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py index f2276bc968..5594e65938 100644 --- a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This file contains code frin the CIoU distribution (https://github.com/Zzh-tju/CIoU). +# This file contains code from the CIoU distribution (https://github.com/Zzh-tju/CIoU). # Copyright (c) 2020 Zheng, Zhaohui. # # This program is free software: you can redistribute it and/or modify From 0e1a3926c4232f4b68942b5239f625b1df77e981 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 15:02:44 +0200 Subject: [PATCH 283/374] Update cluster_nms.py --- .../object_detection_2d/nms/cluster_nms/cluster_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index 9efcb1a8be..939fdb29ee 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This file contains code frin the CIoU distribution (https://github.com/Zzh-tju/CIoU). +# This file contains code from the CIoU distribution (https://github.com/Zzh-tju/CIoU). # Copyright (c) 2020 Zheng, Zhaohui. # # This program is free software: you can redistribute it and/or modify From 2a281ba9c3b95f3fbca825311d532be17d22da08 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 15:04:19 +0200 Subject: [PATCH 284/374] Update nms_utils.py --- .../object_detection_2d/nms/utils/nms_utils.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py index 7e69b49927..69b32a5d73 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py @@ -12,6 +12,21 @@ # See the License for the specific language governing permissions and # limitations under the License. +# This file contains code from the CIoU distribution (https://github.com/Zzh-tju/CIoU). +# Copyright (c) 2020 Zheng, Zhaohui. +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, version 3. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + import torch import torchvision import numpy as np From 7912e090c87d067e8df298bed5d1527225f16875 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 15:06:07 +0200 Subject: [PATCH 285/374] Update soft_nms.py --- .../nms/soft_nms/soft_nms.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py index 737960b7d1..a0c668c850 100644 --- a/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/soft_nms/soft_nms.py @@ -12,6 +12,28 @@ # See the License for the specific language governing permissions and # limitations under the License. +# MIT License +# +# Copyright (c) 2020 DocF +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + from opendr.perception.object_detection_2d.nms.utils import NMSCustom from opendr.perception.object_detection_2d.nms.utils.nms_utils import jaccard from opendr.engine.target import BoundingBox, BoundingBoxList From 705dc4ed9615e7374361ecccdf2efc0d6e8500a5 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 15:31:41 +0200 Subject: [PATCH 286/374] Update README.md --- .../nms/soft_nms/README.md | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/soft_nms/README.md b/src/opendr/perception/object_detection_2d/nms/soft_nms/README.md index 3dfc265ff2..6b8c2513d0 100644 --- a/src/opendr/perception/object_detection_2d/nms/soft_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/soft_nms/README.md @@ -5,7 +5,31 @@ This folder contains an implementation of Soft-NMS [[1]](#soft_nms-1). Sources ------ -Large parts of code are taken from [here](https://github.com/DocF/Soft-NMS) with modifications to make it compatible with OpenDR specifications. +Large parts of code are taken from [here](https://github.com/DocF/Soft-NMS) with modifications to make it compatible with OpenDR specifications. The original code is licensed under the MIT license: + +``` +MIT License + +Copyright (c) 2020 DocF + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +``` [1] Soft-NMS -- Improving Object Detection With One Line of Code, [ArXiv](https://arxiv.org/abs/1704.04503). From 6f4d8575c41475debe20fc631b31ada13d8ac21c Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 15:37:08 +0200 Subject: [PATCH 287/374] Update README.md --- .../nms/cluster_nms/README.md | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md index fbe82b2928..410c887028 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/README.md @@ -1,11 +1,28 @@ Cluster-NMS ====== -This folder contains an implementation of Cluster-NMS [[1]](#cluster_nms-1). +This folder contains an implementation of Cluster-NMS [[1]](#cluster_nms-1). Sources ------ -Large parts of code are taken from [here](https://github.com/Zzh-tju/CIoU) with modifications to make it compatible with OpenDR specifications. +Large parts of code are taken from [here](https://github.com/Zzh-tju/CIoU) with modifications to make it compatible with OpenDR specifications. The original code is licensed under the GNU General Public License v3.0: + +``` +This folder contains code from the CIoU distribution (https://github.com/Zzh-tju/CIoU). +Copyright (c) 2020 Zheng, Zhaohui. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 3. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +``` [1] Enhancing Geometric Factors in Model Learning and Inference for Object Detection and Instance Segmentation, [ArXiv](https://arxiv.org/abs/2005.03572). From 8742c69a84fbd11829fbe81e32e7e92d3d1dd29f Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 15:37:33 +0200 Subject: [PATCH 288/374] Update README.md --- .../nms/fast_nms/README.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/fast_nms/README.md b/src/opendr/perception/object_detection_2d/nms/fast_nms/README.md index 8060c78898..1b6165122d 100644 --- a/src/opendr/perception/object_detection_2d/nms/fast_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/fast_nms/README.md @@ -5,7 +5,24 @@ This folder contains an implementation of Fast-NMS [[1]](#fast_nms-1). Sources ------ -Large parts of code are taken from [here](https://github.com/Zzh-tju/CIoU) with modifications to make it compatible with OpenDR specifications. +Large parts of code are taken from [here](https://github.com/Zzh-tju/CIoU) with modifications to make it compatible with OpenDR specifications. The original code is licensed under the GNU General Public License v3.0: + +``` +This folder contains code from the CIoU distribution (https://github.com/Zzh-tju/CIoU). +Copyright (c) 2020 Zheng, Zhaohui. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 3. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +``` [1] YOLACT: Real-time Instance Segmentation, [ArXiv](https://arxiv.org/abs/1904.02689). From 00594d5781c7b54eb03a6acc91d2b806954b5d67 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 17:31:34 +0200 Subject: [PATCH 289/374] Update cluster_nms.py --- .../nms/cluster_nms/cluster_nms.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py index 939fdb29ee..ee34323346 100644 --- a/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/cluster_nms/cluster_nms.py @@ -14,17 +14,17 @@ # This file contains code from the CIoU distribution (https://github.com/Zzh-tju/CIoU). # Copyright (c) 2020 Zheng, Zhaohui. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 3. # -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU General Public License # along with this program. If not, see . from opendr.perception.object_detection_2d.nms.utils import NMSCustom From 295e1724223e72d1db9d8976dcc3a5758cc443a3 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 17:32:01 +0200 Subject: [PATCH 290/374] Update fast_nms.py --- .../object_detection_2d/nms/fast_nms/fast_nms.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py index 5594e65938..ace8b37089 100644 --- a/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py +++ b/src/opendr/perception/object_detection_2d/nms/fast_nms/fast_nms.py @@ -14,17 +14,17 @@ # This file contains code from the CIoU distribution (https://github.com/Zzh-tju/CIoU). # Copyright (c) 2020 Zheng, Zhaohui. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 3. # -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU General Public License # along with this program. If not, see . from opendr.perception.object_detection_2d.nms.utils import NMSCustom From 00885f16a7d63b54fdd91b108933d9823fe69861 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 22 Mar 2022 17:32:32 +0200 Subject: [PATCH 291/374] Update nms_utils.py --- .../object_detection_2d/nms/utils/nms_utils.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py index 69b32a5d73..93286bbc7a 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_utils.py @@ -14,17 +14,17 @@ # This file contains code from the CIoU distribution (https://github.com/Zzh-tju/CIoU). # Copyright (c) 2020 Zheng, Zhaohui. -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by # the Free Software Foundation, version 3. # -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # -# You should have received a copy of the GNU General Public License +# You should have received a copy of the GNU General Public License # along with this program. If not, see . import torch From f3cef0ab185f5b07fa3c9e79083ddce8746acfd0 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 14:07:02 +0200 Subject: [PATCH 292/374] Update train_demo.py --- .../object_detection_2d/ssd/train_demo.py | 71 +++++++++---------- 1 file changed, 34 insertions(+), 37 deletions(-) diff --git a/projects/perception/object_detection_2d/ssd/train_demo.py b/projects/perception/object_detection_2d/ssd/train_demo.py index b0d875269e..3747471523 100644 --- a/projects/perception/object_detection_2d/ssd/train_demo.py +++ b/projects/perception/object_detection_2d/ssd/train_demo.py @@ -12,41 +12,38 @@ # See the License for the specific language governing permissions and # limitations under the License. -import argparse - -from opendr.engine.datasets import ExternalDataset -from opendr.perception.object_detection_2d import SingleShotDetectorLearner - - -if __name__ == '__main__': - parser = argparse.ArgumentParser() - parser.add_argument("--dataset", help="Dataset to train on", type=str, default="voc", choices=["voc", "coco", - "widerperson"]) - parser.add_argument("--data-root", help="Dataset root folder", type=str) - parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cuda", choices=["cuda", "cpu"]) - parser.add_argument("--batch-size", help="Batch size to use for training", type=int, default=6) - parser.add_argument("--lr", help="Learning rate to use for training", type=float, default=5e-4) - parser.add_argument("--val-after", help="Epochs in-between evaluations", type=int, default=5) - parser.add_argument("--checkpoint-freq", help="Frequency in-between checkpoint saving", type=int, default=5) - parser.add_argument("--n-epochs", help="Number of total epochs", type=int, default=25) - parser.add_argument("--resume-from", help="Epoch to load checkpoint file and resume training from", type=int, default=0) - args = parser.parse_args() - - if args.dataset == 'voc': - dataset = ExternalDataset(args.data_root, 'voc') - val_dataset = ExternalDataset(args.data_root, 'voc') - elif args.dataset == 'coco': - dataset = ExternalDataset(args.data_root, 'coco') - val_dataset = ExternalDataset(args.data_root, 'coco') - elif args.dataset == 'widerperson': - from opendr.perception.object_detection_2d.datasets import WiderPersonDataset - dataset = WiderPersonDataset(root=args.data_root, splits=['train']) - val_dataset = WiderPersonDataset(root=args.data_root, splits=['val']) - - ssd = SingleShotDetectorLearner(device=args.device, batch_size=args.batch_size, lr=args.lr, val_after=args.val_after, - checkpoint_load_iter=args.resume_from, epochs=args.n_epochs, - checkpoint_after_iter=args.checkpoint_freq) - - ssd.fit(dataset, val_dataset) - ssd.save("./ssd_saved_model") +from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner +import os +import argparse +OPENDR_HOME = os.environ['OPENDR_HOME'] + +parser = argparse.ArgumentParser() +parser.add_argument("--app_feats", help="Type of appearance-based features", type=str, default="fmod", + choices=["fmod", "zeros"]) +parser.add_argument("--fmod_type", help="Type of fmod maps", type=str, default="EDGEMAP", + choices=["EDGEMAP", "FAST", "AKAZE", "BRISK", "ORB"]) +parser.add_argument("--iou_filtering", help="Pre-processing IoU threshold", type=float, default=1.0) +parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cuda", choices=["cuda", "cpu"]) +parser.add_argument("--lr", help="Learning rate to use for training", type=float, default=1e-4) +parser.add_argument("--n_epochs", help="Number of total epochs", type=int, default=1) +parser.add_argument("--tmp_path", help="Temporary path where weights will be saved", type=str, + default=os.path.join(OPENDR_HOME, 'projects/perception/object_detection_2d/nms/seq2seq-nms/tmp')) +parser.add_argument("--checkpoint_freq", help="Frequency in-between checkpoint saving", type=int, default=1) +parser.add_argument("--resume-from", help="Epoch to load checkpoint file and resume training from", type=int, default=0) +parser.add_argument("--dataset", help="Dataset to train on", type=str, default="PETS", choices=["PETS", "COCO", + "TEST_MODULE"]) +parser.add_argument("--use_ssd", help="Train using SSD or the dataset's default detector", type=bool, default=False) +parser.add_argument("--max_dt_boxes", help="Maximum number of input RoIs fed to Seq2Seq-NMS", type=int, default=500) +parser.add_argument("--data-root", help="Dataset root folder", type=str, + default=os.path.join(OPENDR_HOME, + 'projects/perception/object_detection_2d/nms/seq2seq-nms/datasets')) +args = parser.parse_args() +seq2SeqNMSLearner = Seq2SeqNMSLearner(epochs=args.n_epochs, lr=args.lr, device=args.device, + fmod_map_type=args.fmod_type, iou_filtering=args.iou_filtering, + temp_path=args.tmp_path, checkpoint_after_iter=args.checkpoint_freq, + checkpoint_load_iter=args.resume_from) +seq2SeqNMSLearner.fit(dataset=args.dataset, use_ssd=args.use_ssd, + datasets_folder=args.data_root, silent=False, verbose=True, + max_dt_boxes=args.max_dt_boxes) +seq2SeqNMSLearner.save(path=os.path.join(args.tmp_path, 'saved_model'), current_epoch=args.n_epochs-1, max_dt_boxes=args.max_dt_boxes) From 3b7bfc4f78109de5d25e2670dca396c4b1763dea Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 14:07:29 +0200 Subject: [PATCH 293/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 00ae01a4c1..7a6fcb8b1f 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -103,7 +103,7 @@ def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', check def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, verbose=True, nms_gt_iou=0.5, max_dt_boxes=400, datasets_folder='./datasets', - use_ssd=False): + use_ssd=False, lr_step=True): dataset_nms = Dataset_NMS(path=datasets_folder, dataset_name=dataset, split='train', use_ssd=use_ssd) if self.classes is None: @@ -142,13 +142,19 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, self.fMoD.set_mean_std(mean_values=self.fmod_mean_std['mean'], std_values=self.fmod_mean_std['std']) start_epoch = 0 - drop_after_epoch = [4, 6] + drop_after_epoch = [] + if lr_step and self.epochs>1: + drop_after_epoch = [int(self.epochs * 0.5)] + if self.epochs>3: + drop_after_epoch.append(int(self.epochs * 0.7)) train_ids = np.arange(len(dataset_nms.src_data)) total_loss_iter = 0 total_loss_epoch = 0 optimizer = optim.Adam(self.model.parameters(), lr=self.lr, betas=(0.9, 0.99), eps=1e-9) # HERE - scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=drop_after_epoch, gamma=0.1) + scheduler = None + if len(drop_after_epoch)>0: + scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=drop_after_epoch, gamma=0.1) num_iter = 0 training_weights = compute_class_weights(pos_weights=[0.9, 0.1], max_dets=max_dt_boxes, dataset_nms=dataset_nms) @@ -274,7 +280,8 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, self.save(path=snapshot_name_lw, optimizer=optimizer, scheduler=scheduler, current_epoch=epoch, max_dt_boxes=max_dt_boxes) total_loss_epoch = 0 - scheduler.step() + if scheduler is not None: + scheduler.step() if logging: file_writer.close() return training_dict From cc02461d1674167766b846610fd16d1b522d3399 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 14:12:41 +0200 Subject: [PATCH 294/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 7a6fcb8b1f..7438114365 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -98,8 +98,8 @@ def __init__(self, lr=0.0001, epochs=8, device='cuda', temp_path='./temp', check resize_dim=self.fmod_map_res_dim, map_type=self.fmod_map_type, map_bin=self.fmod_map_bin, device=self.device) self.init_model() - if self.device == 'cuda': - self.model = self.model.cuda() + if "cuda" in self.device: + self.model = self.model.to(self.device) def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, verbose=True, nms_gt_iou=0.5, max_dt_boxes=400, datasets_folder='./datasets', @@ -125,8 +125,8 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, print("Model trainable parameters:", self.count_parameters()) self.model.train() - if self.device == 'cuda': - self.model = self.model.cuda() + if "cuda" in self.device: + self.model = self.model.to(self.device) if self.epochs is None: raise ValueError("Training epochs not specified") @@ -198,10 +198,10 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, image_path = os.path.join(datasets_folder, dataset, image_fln) img_res = dataset_nms.src_data[sample_id]['resolution'][::-1] - if self.device == "cuda": - dt_boxes = dt_boxes.cuda() - dt_scores = dt_scores.cuda() - gt_boxes = gt_boxes.cuda() + if "cuda" in self.device: + dt_boxes = dt_boxes.to(self.device) + dt_scores = dt_scores.to(self.device) + gt_boxes = gt_boxes.to(self.device) val_ids = torch.logical_and((dt_boxes[:, 2] - dt_boxes[:, 0]) > 4, (dt_boxes[:, 3] - dt_boxes[:, 1]) > 4) @@ -229,8 +229,8 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, app_feats = torch.unsqueeze(app_feats, dim=1) elif self.app_feats == 'zeros': app_feats = torch.zeros([dt_boxes.shape[0], 1, self.app_input_dim]) - if self.device == 'cuda': - app_feats = app_feats.cuda() + if "cuda" in self.device: + app_feats = app_feats.to(self.device) elif self.app_feats == 'custom': raise AttributeError("Custom appearance-based features are not yet supported.") @@ -247,9 +247,9 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, 1 - labels)) e = torch.distributions.uniform.Uniform(0.05, 0.055).sample([labels.shape[0], 1]) - if self.device == 'cuda': - weights = weights.cuda() - e = e.cuda() + if "cuda" in self.device: + weights = weights.to(self.device) + e = e.to(self.device) labels = labels * (1 - e) + (1 - labels) * e ce_loss = F.binary_cross_entropy(preds, labels, reduction="none") loss = (ce_loss * weights).sum() @@ -313,12 +313,12 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, self.fMoD.set_mean_std(mean_values=self.fmod_mean_std['mean'], std_values=self.fmod_mean_std['std']) self.model = self.model.eval() - if self.device == "cuda": - self.model = self.model.cuda() + if "cuda" in self.device: + self.model = self.model.to(self.device) self.model = self.model.eval() - if self.device == "cuda": - self.model = self.model.cuda() + if "cuda" in self.device: + self.model = self.model.to(self.device) train_ids = np.arange(len(dataset_nms.src_data)) nms_results = [] @@ -342,9 +342,9 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, pbar_eval.update(1) continue - if self.device == "cuda": - dt_boxes = dt_boxes.cuda() - dt_scores = dt_scores.cuda() + if "cuda" in self.device: + dt_boxes = dt_boxes.to(self.device) + dt_scores = dt_scores.to(self.device) val_ids = torch.logical_and((dt_boxes[:, 2] - dt_boxes[:, 0]) > 4, (dt_boxes[:, 3] - dt_boxes[:, 1]) > 4) @@ -365,8 +365,8 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, app_feats = torch.unsqueeze(app_feats, dim=1) elif self.app_feats == 'zeros': app_feats = torch.zeros([dt_boxes.shape[0], 1, self.app_input_dim]) - if self.device == 'cuda': - app_feats = app_feats.cuda() + if "cuda" in self.device: + app_feats = app_feats.to(self.device) elif self.app_feats == 'custom': raise AttributeError("Custom appearance-based features are not yet supported.") msk = self.compute_mask(dt_boxes, iou_thres=0.2, extra=0.1) @@ -601,9 +601,9 @@ def infer(self, boxes=None, scores=None, boxes_sorted=False, max_dt_boxes=400, i raise ValueError('Multi-class NMS is not supported in Seq2Seq-NMS yet.') if boxes.shape[0] != scores.shape[0]: raise ValueError('Scores and boxes must have the same size in dim 0.') - if self.device == "cuda": - boxes = boxes.cuda() - scores = scores.cuda() + if "cuda" in self.device: + boxes = boxes.to(self.device) + scores = scores.to(self.device) scores = scores.squeeze(-1) keep_ids = torch.where(scores > 0.05)[0] @@ -630,8 +630,8 @@ def infer(self, boxes=None, scores=None, boxes_sorted=False, max_dt_boxes=400, i app_feats = torch.unsqueeze(app_feats, dim=1) elif self.app_feats == 'zeros': app_feats = torch.zeros([boxes.shape[0], 1, self.app_input_dim]) - if self.device == 'cuda': - app_feats = app_feats.cuda() + if "cuda" in self.device: + app_feats = app_feats.to(self.device) elif self.app_feats == 'custom': raise AttributeError("Custom appearance-based features are not yet supported.") @@ -679,16 +679,16 @@ def run_nms(self, boxes=None, scores=None, boxes_sorted=False, top_k=400, img=No elif torch.is_tensor(boxes): if self.device == 'cpu': boxes = boxes.cpu() - elif self.device == 'cuda': - boxes = boxes.cuda() + if "cuda" in self.device: + boxes = boxes.to(self.device) if isinstance(scores, np.ndarray): scores = torch.tensor(scores, device=self.device) elif torch.is_tensor(scores): if self.device == 'cpu': scores = scores.cpu() - elif self.device == 'cuda': - scores = scores.cuda() + if "cuda" in self.device: + scores = scores.to(self.device) boxes = self.infer(boxes=boxes, scores=scores, boxes_sorted=boxes_sorted, max_dt_boxes=top_k, img_res=img.opencv().shape[::-1][1:]) return boxes From 8578215608a79f52cfce3fbec1016fabb17f2b24 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 14:16:44 +0200 Subject: [PATCH 295/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 7438114365..315aebe219 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -677,18 +677,14 @@ def run_nms(self, boxes=None, scores=None, boxes_sorted=False, top_k=400, img=No if isinstance(boxes, np.ndarray): boxes = torch.tensor(boxes, device=self.device) elif torch.is_tensor(boxes): - if self.device == 'cpu': - boxes = boxes.cpu() - if "cuda" in self.device: - boxes = boxes.to(self.device) + if "cuda" in self.device: + boxes = boxes.to(self.device) if isinstance(scores, np.ndarray): scores = torch.tensor(scores, device=self.device) elif torch.is_tensor(scores): - if self.device == 'cpu': - scores = scores.cpu() - if "cuda" in self.device: - scores = scores.to(self.device) + if "cuda" in self.device: + scores = scores.to(self.device) boxes = self.infer(boxes=boxes, scores=scores, boxes_sorted=boxes_sorted, max_dt_boxes=top_k, img_res=img.opencv().shape[::-1][1:]) return boxes From bed2c9f6d5e90b74e8e0ce796fda22cf05b2482e Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 14:26:28 +0200 Subject: [PATCH 296/374] Update seq2seq_model.py --- .../nms/seq2seq_nms/algorithm/seq2seq_model.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py index 9322937ced..953892d04e 100755 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/seq2seq_model.py @@ -26,10 +26,11 @@ def __init__(self, dropout=0.01, use_app_feats=True, app_input_dim=315, geom_inp self.dropout_q = nn.Dropout(dropout * 0.25) self.num_JPUs = num_JPUs self.joint_processing_units = [] + self.device = device for i in range(self.num_JPUs): self.joint_processing_units.append(Joint_processing_unit(lq_dim=lq_dim, sq_dim=sq_dim, dropout=dropout)) - if device == 'cuda': - self.joint_processing_units[i] = self.joint_processing_units[i].cuda() + if "cuda" in self.device: + self.joint_processing_units[i] = self.joint_processing_units[i].to(self.device) self.joint_processing_units = nn.ModuleList(self.joint_processing_units) if self.use_app_feats: q_app_dims = [180, 180] From d98e01275618c44e7b12b4fdade85ed56f091626 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 14:26:39 +0200 Subject: [PATCH 297/374] Update fmod.py --- .../nms/seq2seq_nms/algorithm/fmod.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py index 1c1cef8365..4b5d5ec2f5 100755 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/algorithm/fmod.py @@ -39,8 +39,8 @@ def __init__(self, roi_pooling_dim=None, pyramid_depth=3, map_type="SIFT", map_b self.rp_size.append([int(self.roi_pooling_dim[0] * s), int(self.roi_pooling_dim[1] * s)]) self.device = device self.boxes_p = torch.tensor(self.boxes_p).float() - if self.device == 'cuda': - self.boxes_p = self.boxes_p.cuda() + if "cuda" in self.device: + self.boxes_p = self.boxes_p.to(self.device) self.resc = 1.0 self.map = None self.resize_dim = resize_dim @@ -52,9 +52,9 @@ def __init__(self, roi_pooling_dim=None, pyramid_depth=3, map_type="SIFT", map_b def set_mean_std(self, mean_values=None, std_values=None): self.mean = torch.tensor(mean_values).float() self.std = torch.tensor(std_values).float() - if self.device == 'cuda': - self.mean = self.mean .cuda() - self.std = self.std.cuda() + if "cuda" in self.device: + self.mean = self.mean.to(self.device) + self.std = self.std.to(self.device) def extract_maps(self, img=None, augm=False): if img is None: @@ -116,8 +116,8 @@ def extract_maps(self, img=None, augm=False): else: self.map[coords_y, coords_x] = 255 self.map = torch.from_numpy(self.map).float() - if self.device == 'cuda': - self.map = self.map.cuda() + if "cuda" in self.device: + self.map = self.map.to(self.device) def extract_FMoD_feats(self, boxes): num_rois = boxes.shape[0] From 0fc6495716673159c75a7ffc590fae6b89573ecd Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 16:36:40 +0200 Subject: [PATCH 298/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 315aebe219..c4b7de4b67 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -143,9 +143,9 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, start_epoch = 0 drop_after_epoch = [] - if lr_step and self.epochs>1: + if lr_step and self.epochs > 1: drop_after_epoch = [int(self.epochs * 0.5)] - if self.epochs>3: + if self.epochs > 3: drop_after_epoch.append(int(self.epochs * 0.7)) train_ids = np.arange(len(dataset_nms.src_data)) @@ -153,7 +153,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, total_loss_epoch = 0 optimizer = optim.Adam(self.model.parameters(), lr=self.lr, betas=(0.9, 0.99), eps=1e-9) # HERE scheduler = None - if len(drop_after_epoch)>0: + if len(drop_after_epoch) > 0: scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=drop_after_epoch, gamma=0.1) num_iter = 0 @@ -246,7 +246,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, weights = (training_weights[class_index][1] * labels + training_weights[class_index][0] * ( 1 - labels)) - e = torch.distributions.uniform.Uniform(0.05, 0.055).sample([labels.shape[0], 1]) + e = torch.distributions.uniform.Uniform(0.001, 0.005).sample([labels.shape[0], 1]) if "cuda" in self.device: weights = weights.to(self.device) e = e.to(self.device) From c50a8b169ec43285eaa55a1295db412f5126571e Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 16:38:15 +0200 Subject: [PATCH 299/374] Update train_demo.py --- .../object_detection_2d/ssd/train_demo.py | 71 ++++++++++--------- 1 file changed, 37 insertions(+), 34 deletions(-) diff --git a/projects/perception/object_detection_2d/ssd/train_demo.py b/projects/perception/object_detection_2d/ssd/train_demo.py index 3747471523..b0d875269e 100644 --- a/projects/perception/object_detection_2d/ssd/train_demo.py +++ b/projects/perception/object_detection_2d/ssd/train_demo.py @@ -12,38 +12,41 @@ # See the License for the specific language governing permissions and # limitations under the License. - -from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner -import os import argparse -OPENDR_HOME = os.environ['OPENDR_HOME'] - -parser = argparse.ArgumentParser() -parser.add_argument("--app_feats", help="Type of appearance-based features", type=str, default="fmod", - choices=["fmod", "zeros"]) -parser.add_argument("--fmod_type", help="Type of fmod maps", type=str, default="EDGEMAP", - choices=["EDGEMAP", "FAST", "AKAZE", "BRISK", "ORB"]) -parser.add_argument("--iou_filtering", help="Pre-processing IoU threshold", type=float, default=1.0) -parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cuda", choices=["cuda", "cpu"]) -parser.add_argument("--lr", help="Learning rate to use for training", type=float, default=1e-4) -parser.add_argument("--n_epochs", help="Number of total epochs", type=int, default=1) -parser.add_argument("--tmp_path", help="Temporary path where weights will be saved", type=str, - default=os.path.join(OPENDR_HOME, 'projects/perception/object_detection_2d/nms/seq2seq-nms/tmp')) -parser.add_argument("--checkpoint_freq", help="Frequency in-between checkpoint saving", type=int, default=1) -parser.add_argument("--resume-from", help="Epoch to load checkpoint file and resume training from", type=int, default=0) -parser.add_argument("--dataset", help="Dataset to train on", type=str, default="PETS", choices=["PETS", "COCO", - "TEST_MODULE"]) -parser.add_argument("--use_ssd", help="Train using SSD or the dataset's default detector", type=bool, default=False) -parser.add_argument("--max_dt_boxes", help="Maximum number of input RoIs fed to Seq2Seq-NMS", type=int, default=500) -parser.add_argument("--data-root", help="Dataset root folder", type=str, - default=os.path.join(OPENDR_HOME, - 'projects/perception/object_detection_2d/nms/seq2seq-nms/datasets')) -args = parser.parse_args() -seq2SeqNMSLearner = Seq2SeqNMSLearner(epochs=args.n_epochs, lr=args.lr, device=args.device, - fmod_map_type=args.fmod_type, iou_filtering=args.iou_filtering, - temp_path=args.tmp_path, checkpoint_after_iter=args.checkpoint_freq, - checkpoint_load_iter=args.resume_from) -seq2SeqNMSLearner.fit(dataset=args.dataset, use_ssd=args.use_ssd, - datasets_folder=args.data_root, silent=False, verbose=True, - max_dt_boxes=args.max_dt_boxes) -seq2SeqNMSLearner.save(path=os.path.join(args.tmp_path, 'saved_model'), current_epoch=args.n_epochs-1, max_dt_boxes=args.max_dt_boxes) + +from opendr.engine.datasets import ExternalDataset +from opendr.perception.object_detection_2d import SingleShotDetectorLearner + + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument("--dataset", help="Dataset to train on", type=str, default="voc", choices=["voc", "coco", + "widerperson"]) + parser.add_argument("--data-root", help="Dataset root folder", type=str) + parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cuda", choices=["cuda", "cpu"]) + parser.add_argument("--batch-size", help="Batch size to use for training", type=int, default=6) + parser.add_argument("--lr", help="Learning rate to use for training", type=float, default=5e-4) + parser.add_argument("--val-after", help="Epochs in-between evaluations", type=int, default=5) + parser.add_argument("--checkpoint-freq", help="Frequency in-between checkpoint saving", type=int, default=5) + parser.add_argument("--n-epochs", help="Number of total epochs", type=int, default=25) + parser.add_argument("--resume-from", help="Epoch to load checkpoint file and resume training from", type=int, default=0) + + args = parser.parse_args() + + if args.dataset == 'voc': + dataset = ExternalDataset(args.data_root, 'voc') + val_dataset = ExternalDataset(args.data_root, 'voc') + elif args.dataset == 'coco': + dataset = ExternalDataset(args.data_root, 'coco') + val_dataset = ExternalDataset(args.data_root, 'coco') + elif args.dataset == 'widerperson': + from opendr.perception.object_detection_2d.datasets import WiderPersonDataset + dataset = WiderPersonDataset(root=args.data_root, splits=['train']) + val_dataset = WiderPersonDataset(root=args.data_root, splits=['val']) + + ssd = SingleShotDetectorLearner(device=args.device, batch_size=args.batch_size, lr=args.lr, val_after=args.val_after, + checkpoint_load_iter=args.resume_from, epochs=args.n_epochs, + checkpoint_after_iter=args.checkpoint_freq) + + ssd.fit(dataset, val_dataset) + ssd.save("./ssd_saved_model") From aa6ef6c52d63c8f9357b5e6a6fa100d137b7d616 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 18:35:53 +0200 Subject: [PATCH 300/374] Update train_demo.py --- .../nms/seq2seq-nms/train_demo.py | 43 +++++++++++-------- 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py index 834ce39325..6523ee8c4d 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py @@ -19,25 +19,32 @@ OPENDR_HOME = os.environ['OPENDR_HOME'] parser = argparse.ArgumentParser() -parser.add_argument("--dataset", help="Dataset to train on", type=str, default="voc", choices=["PETS", "COCO", - "TEST_MODULE"]) -parser.add_argument("--data_root", help="Dataset root folder", type=str) +parser.add_argument("--app_feats", help="Type of appearance-based features", type=str, default="fmod", + choices=["fmod", "zeros"]) +parser.add_argument("--fmod_type", help="Type of fmod maps", type=str, default="EDGEMAP", + choices=["EDGEMAP", "FAST", "AKAZE", "BRISK", "ORB"]) +parser.add_argument("--iou_filtering", help="Pre-processing IoU threshold", type=float, default=1.0) parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cuda", choices=["cuda", "cpu"]) -parser.add_argument("--max_dt_boxes", help="Maximum number of input RoIs to Seq2Seq-NMS", type=int, default=450) -parser.add_argument("--nms_gt_iou", help="Learning rate to use for training", type=float, default=5e-4) -parser.add_argument("--val-after", help="Epochs in-between evaluations", type=int, default=5) -parser.add_argument("--checkpoint-freq", help="Frequency in-between checkpoint saving", type=int, default=5) -parser.add_argument("--n-epochs", help="Number of total epochs", type=int, default=25) +parser.add_argument("--lr", help="Learning rate to use for training", type=float, default=1e-4) +parser.add_argument("--n_epochs", help="Number of total epochs", type=int, default=10) +parser.add_argument("--tmp_path", help="Temporary path where weights will be saved", type=str, + default=os.path.join(OPENDR_HOME, 'projects/perception/object_detection_2d/nms/seq2seq-nms/tmp')) +parser.add_argument("--checkpoint_freq", help="Frequency in-between checkpoint saving", type=int, default=1) parser.add_argument("--resume-from", help="Epoch to load checkpoint file and resume training from", type=int, default=0) - +parser.add_argument("--dataset", help="Dataset to train on", type=str, default="PETS", choices=["PETS", "COCO", + "TEST_MODULE"]) +parser.add_argument("--use_ssd", help="Train using SSD as default detector", type=bool, default=False) +parser.add_argument("--max_dt_boxes", help="Maximum number of input RoIs fed to Seq2Seq-NMS", type=int, default=500) +parser.add_argument("--data-root", help="Dataset root folder", type=str, + default=os.path.join(OPENDR_HOME, + 'projects/perception/object_detection_2d/nms/seq2seq-nms/datasets')) args = parser.parse_args() - -seq2seq_tmp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/coco_tmp' -seq2seq_logs_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/coco_logs' - -seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=None, app_feats='fmod', - checkpoint_after_iter=1, temp_path=seq2seq_tmp_path, epochs=8) -seq2SeqNMSLearner.fit(dataset=args.dataset, use_ssd=False, - datasets_folder=args.data_root, - logging_path=seq2seq_logs_path, silent=False, verbose=True, nms_gt_iou=0.50, +seq2SeqNMSLearner = Seq2SeqNMSLearner(epochs=args.n_epochs, lr=args.lr, device=args.device, app_feats=args.app_feats, + fmod_map_type=args.fmod_type, iou_filtering=args.iou_filtering, + temp_path=args.tmp_path, checkpoint_after_iter=args.checkpoint_freq, + checkpoint_load_iter=args.resume_from) +seq2SeqNMSLearner.fit(dataset=args.dataset, use_ssd=args.use_ssd, + datasets_folder=args.data_root, silent=False, verbose=True, max_dt_boxes=args.max_dt_boxes) +seq2SeqNMSLearner.save(path=os.path.join(args.tmp_path, 'saved_model'), current_epoch=args.n_epochs-1, + max_dt_boxes=args.max_dt_boxes) From 7e8cad026edf9a5ab2eeb14f73422de510ae475d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 18:36:12 +0200 Subject: [PATCH 301/374] Update eval_demo.py --- .../nms/seq2seq-nms/eval_demo.py | 38 +++++++++++++++---- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py index 4460f5d122..db7c6f90e8 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py @@ -14,12 +14,34 @@ from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner import os +import argparse OPENDR_HOME = os.environ['OPENDR_HOME'] -temp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/pets_tmp' -dataset_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/pets_dataset' -seq2SeqNMSLearner = Seq2SeqNMSLearner(iou_filtering=0.8, app_feats='fmod', temp_path=temp_path, - device='cuda') -seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd', path=temp_path) -seq2SeqNMSLearner.load(os.path.join(temp_path, 'seq2seq_pets_jpd'), verbose=True) -seq2SeqNMSLearner.eval(dataset='PETS', split='test', max_dt_boxes=600, - datasets_folder=dataset_path, use_ssd=False) + +parser = argparse.ArgumentParser() +parser.add_argument("--app_feats", help="Type of appearance-based features", type=str, default="fmod", + choices=["fmod", "zeros"]) +parser.add_argument("--fmod_type", help="Type of fmod maps", type=str, default="EDGEMAP", + choices=["EDGEMAP", "FAST", "AKAZE", "BRISK", "ORB"]) +parser.add_argument("--iou_filtering", help="Pre-processing IoU threshold", type=float, default=1.0) +parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cuda", choices=["cuda", "cpu"]) +parser.add_argument("--pretrained_model", help="Name of pretrained model", type=str, default='seq2seq_pets_jpd', + choices=['seq2seq_pets_jpd']) +parser.add_argument("--split", help="The split of the corresponding dataset", type=str, default='test', + choices=["test", "val", "train"]) +parser.add_argument("--max_dt_boxes", help="Maximum number of input RoIs fed to Seq2Seq-NMS", type=int, default=600) +parser.add_argument("--dataset", help="Dataset to train on", type=str, default="PETS", choices=["PETS", "COCO", + "TEST_MODULE"]) +parser.add_argument("--data_root", help="Dataset root folder", type=str, + default=os.path.join(OPENDR_HOME, + 'projects/perception/object_detection_2d/nms/seq2seq-nms/datasets')) +parser.add_argument("--use_ssd", help="Train using SSD as detector", type=bool, default=False) + +args = parser.parse_args() +tmp_path = os.path.join(OPENDR_HOME, 'projects/perception/object_detection_2d/nms/seq2seq-nms/tmp') +seq2SeqNMSLearner = Seq2SeqNMSLearner(device=args.device, app_feats=args.app_feats, fmod_map_type=args.fmod_type, + iou_filtering=args.iou_filtering, + temp_path=tmp_path) +seq2SeqNMSLearner.download(model_name=args.pretrained_model, path=tmp_path) +seq2SeqNMSLearner.load(os.path.join(tmp_path, args.pretrained_model), verbose=True) +seq2SeqNMSLearner.eval(dataset=args.dataset, use_ssd=args.use_ssd, split=args.split, max_dt_boxes=args.max_dt_boxes, + datasets_folder=args.data_root) From d1f0255a4ccfe7d34d79946467e35f8e6533accd Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 18:43:29 +0200 Subject: [PATCH 302/374] Update inference_demo.py --- .../nms/seq2seq-nms/inference_demo.py | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index a511b2d298..3fe6b568a5 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -12,20 +12,33 @@ # See the License for the specific language governing permissions and # limitations under the License. - from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner -from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes +from opendr.engine.data import Image import os +import argparse OPENDR_HOME = os.environ['OPENDR_HOME'] -seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=0.8, - app_feats='fmod', device='cpu') -seq2_seq_tmp_dir = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/temp' -seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd', path=seq2_seq_tmp_dir) -seq2SeqNMSLearner.load(os.path.join(seq2_seq_tmp_dir, 'seq2seq_pets_jpd'), verbose=True) -ssd = SingleShotDetectorLearner(device='cuda') +parser = argparse.ArgumentParser() +parser.add_argument("--app_feats", help="Type of appearance-based features", type=str, default="fmod", + choices=["fmod", "zeros"]) +parser.add_argument("--fmod_type", help="Type of fmod maps", type=str, default="EDGEMAP", + choices=["EDGEMAP", "FAST", "AKAZE", "BRISK", "ORB"]) +parser.add_argument("--iou_filtering", help="Pre-processing IoU threshold", type=float, default=1.0) +parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cuda", choices=["cuda", "cpu"]) +parser.add_argument("--pretrained_model", help="Name of pretrained model", type=str, default='seq2seq_pets_jpd', + choices=['seq2seq_pets_jpd']) + +args = parser.parse_args() +tmp_path = os.path.join(OPENDR_HOME, 'projects/perception/object_detection_2d/nms/seq2seq-nms/tmp') +seq2SeqNMSLearner = Seq2SeqNMSLearner(device=args.device, app_feats=args.app_feats, fmod_map_type=args.fmod_type, + iou_filtering=args.iou_filtering, + temp_path=tmp_path) +seq2SeqNMSLearner.download(model_name=args.pretrained_model, path=tmp_path) +seq2SeqNMSLearner.load(os.path.join(tmp_path, args.pretrained_model), verbose=True) + +ssd = SingleShotDetectorLearner(device=args.device) ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) img = Image.open(OPENDR_HOME + '/projects/perception/object_detection_2d/nms/img_temp/frame_0000.jpg') From 53728f21f7f4ee4226a5fc5281c68ae202e0381e Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 18:51:57 +0200 Subject: [PATCH 303/374] Add files via upload --- .../nms/seq2seq_nms/stats_pretrained.png | Bin 0 -> 107092 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png new file mode 100644 index 0000000000000000000000000000000000000000..0cf4e76401daecded231a879d65de350a29cd007 GIT binary patch literal 107092 zcmcG#byOQ|*Z&*bU5f-O?i48Q?pBIRaVT0O5Zv9J;!ayA?%txs9f}o~KyZhX-uL_b z-t(OQ&RXZNvY449bID}SHG6;eXGdwM$z!3Dp#uN_EJXzwEdT%+2mruYpd!QG=~Hu6 zf^85#Nh#`}!v1_wEhAyauiRzz+_jyp-M!4+tN=Dn&W={>pDf(0teigCI=i1Dbc+E1 z)Br^pNgdGV<5lrkTAOTf=;`zJyE!DW@47-Gcsr3~V6WccUIj+Y_?{r7_#Qj~fgn!1 zV=OZHU0Rpf+vEWQNUwqk9|2!InhIjEXjXQ6N_H2boKV!EazzrG<|h&jO405>_-JIG zdmPc#Hy6IIEpK$@3{M}U96PamG6BT-|y2S_dc_n#s3#Yq_9e~JvT#rglw8tSNzlL3nPMk@N@9FEPDlf!(m3Zphc~!n^A) zPwRzD=+D>AFV{`=eQSW1GpZN3{E0zG6t|~Uy49xm%Z2zE&I=T$IhSZ)&F4`xskVLV z@A+rr!lx4HJ1gVp7S4@(6Z!q8H*`5;CW3L_5P|+rN2dK;n2)<}yIcS5Sv_A&Rw!4l zd;Q;T`*Fl&8VzK*NIPJoc-!L~@L>3OmJsmc>EXs%m^HR`VfN*5;$`Ee`$be`2KF7U z>-mTM;sj{9_!C;8#y)JMi-xB-0k;TiemBO1=wbhkLj2`!0(1+dc|OnRHWI`#+4}$O zC%hPUvu~ zU}4&cr$I0AGRUh3e3)s7~gV2!A@P;S-`J6@)gio`MCb(o4ELky|o# zAmPTu>}1uCJ0Ek-^0yk^=Y7vxgo9~hK6gB~O)g@iyk?oiGMb3gQiO0l!B*_gN9mR= z3$iY32yJkYw8vZJ4~E3l!|%ymKO7?Lm!XZ;nPm~HC}=Fi*}p-t^+3i&(5%Qn*D&Dn z@bkf*3AWS!F7rzBUF$0KT-sC|6YrkK(ro$FH&F1YiBvl3@QW>aO$Ehd0J;R zKVY#$Ms)RASY%_jBYp|f+953mgxUg^0#PNTB=7=Lv?UVpHu4UH72PMw)Z93|jFx9u z#%l1I$&! z)Xirc#=YZBsUo`~pz-R5+2q@eFN|NvLs7AR5hrJK*<#J6+(75F2gSX4Y{`i#l-uX< zaD0R0C*V*`EDc0;W@FS^-bygvb9V*o-ZBQ@J()aT%Z(X-5sB@T61mUlGzYob{j+d+ zGG>NHk)YC=iV?WCP-_kseZE0R_dXLmT}myqFcTkQ8?IZ`XQx@6oO0x!niC!xY0eOB zGX6jvUlMS=z?_$cVe8Tm-x*6P+xqUO8g00qHPttRY~e-@YMn!K5uk;Lh(zDk;zqPt zw|F1uYjG39J^-NA7Buxe;lv*khzdQWC|WtSs93=3)+*7EYU7saHkQ#??8sQEDzrk$ zbnyxHk!}AW2+!mmE?{rH(XK?y*>6un5?%CLIH36`ZI8V?tswk-|F@^u8gczpHzOk# zHBG@l(k~(nrZkO_FSzPuD{5+LF0@rc8A?n<=R@?x8VLAiD$SxtS7yJZu2Iqiq?QI8 z9srX^c`xme@*-S+uSudG};|HY#|N`+!0^>t5v6V4)0vf*4AG2@>8C5=E5%2^@ex}{HjZ;Qy2 zkHf|GH(ME_44C65`63vik}+k`CGmpF%a3kcS0MUymdC`)>JPeqpFNAY zX8R1(tP3$DL+F;7T(=}Ve`m#zI7%l%W#02l?=$^O4E&0_8=3^1NiSI&rjyra<57w4xcuGl4%- zOhpG|?f@UrxQZ%TLUif^ro zG$+kaLoHm5Vud}2$tGO3T4b!$de@3*%wcvZ!qvoWK+%DSeRfdVdVw6J{=2a3uV!2? zEg5D^n5T%OQHkWq|tsRIq!d2Kx5m_MR!y5@P|Y@p}9%O^1PQ+4)8vW zFPuxS_R}QXOed;1qp&CEcphEYxqMEIk0?;Ux6}`38%3>9w4Bjo3i_R;b~1XrE=~W+ z*q+3#sZr;Bhyj@^y%n?2BS1z~Kp4JD) z3{-l3sm>`0cB;-|ZF?*YR`D(~#?2#*JYj{J!dcMS`P1UOiu_BJA?cF?Y}+MeT^xJw zJ-YPU^{-j5{I6NW?!g7UdAI4iENh$98Kz}ld zo_y7tt)>i^oEk!=UVnjKf2&eaitH1P^l4H`5WS)61^*_Ei6x{F#WXNV%_PkC^po!@ z7aq&(=ZSZk!>Ma$u#4_^dMR5Ga}@WTw0CW?f@p8$)j zf@3 zI6!wxBStPm`!p%ZP7-MHfS&J9O=mDa@8xfZFq?wD{b2g%p$(hh$DeBe0)NjQ$q>~<$ZDJC1oEDRySev#_hjF7Pr{RXl8v|dB zKlcb+2z=X5r&gqm?d8rB74D64>f;d_s$@YA!G(=LD3`2gfAcJ)=FE;dIy#=HOgETi zy?<|gzHn4Om7J_W4oTlTaJkuZV+%|}_?3d}imjuZ6WXBVeOD1AEG@&E;rZ1M3LiJk zyV#i*?smZZ`%Gl|x8aFdL0Vj~%j3D|5>Xb}`LIYHbZfn4_DJY{flMdym)MVsj8h-R z&Xc?D8C#4s?>)-y<`wjTJMxDio(7 zMsGKdGRe%(A*?i|q!75Z8X2mbMSA+hJG}0Ye>%$?s9&g1mxnM=9$PUT*WTcX5Ux4a zG@;NIonU)I8Xh;f?!4M~X^PCJ#Kj|6r#_#GIhE}`fFXXl0}*KF0L1s1*AeeoH(i`v zoo;z%O@?nHu|L!w8B@QUOeu*G+ubrzT(2x_Wme&t`x|YWc_Lv}lGV;!ytdt$rY~}x z;UF<0)MsAI%x131t&aJCQe5hYa`7qH_h%Q~80+kgOMWoCLL_DNu{gU|;)c@XBW3&X z^BegX&)VljJV=BMgjFF)!DS~;U>V1$i&4ETHEUJfuifS(BA)+brSQa3VeAh!5zf8C zsLLxV|63Z5_Em>6H%+>#aFSEejnZ7Kav&AM5E9k5r~M*s%6DE&c-JWlTeOn6Lpx{5 z6I5jiRSFUEd#l4MscuVqHnZ6Qox4x;{sXWnQaVt{`;T}1r)Cwq7l6P+*D0C4}knGO)731_K zxVG7^P@c<0lnoX;_vzfmkz>*nDS7rFKdMlD5Jp3P=-fU74If=4FOZbzu}DW1Bz&0j zup-xf`L2+qm*@*5X|=whP@Ek1&ygD!iObee2_1gxKz02zN`lFGD4=Ql#L*zT?t6jd zceCpC78Ks@0MaY@v+43QfDu4)GGp$VkX>)dAZ>qQ#YB9$1X-3fF-@ec#f0!hIGpBh z6|+DXXt!^ChPE14vc#n-RigX4xW>fl23AFt!u+=JDem07nMq9=G8Wg~buF22P$_e0 zuH}rs9G#Ts`xi}!Jsca@{f$nqsGxS5NQ9 z-9XGUVi#{x5O8XK$DsiEJB)zs2p?|(+j8#LBGZL3X+rG+nocWJf9fR$Ct*_l0#AP4 zTbooAveO=^Umo^<)!!)_(a2a|SU&IFiSb1e+lCAZ8Lydh^~%@Uqz==5aJM9JSnG90 z(VxF2QOl0O{#}1VVq-Gyd4fN+&m}8Hq5ze#J>Adt5X2yCeM}V;C^}R6v6C46vtQO` z)9S`lyX-0`g8N;6{B={=8bd_w-IE)A+=+KkT-26WQ{|gydlScvAlqq`u@z!~+fVF; z-(C?7RD=qsr!{EUY8AO><3}ILMa$6eR0sU*Ph^i9kj|~<5woNAfA{oPDE`z5?u#FP zf<9+cP(ZZ%-mVT3tQFcnM1~i0$K5+tSqE>swG!vY9KqxC`=PIRyU1QcsQW|Zg%Gmy3TRurI@NP{G4%Bg+r*?)&Yb0hpTeiB~(sG*4A^O-!ED{p%dLoJ+^75zV4Q_PP}Dij^)uc5qLMjjN!p|qu`Xg0D^y{lJSlI zGDZSW!PNB3uijFsof$m5BVo_7l?-?s)`XYk`=7EXbiT^!X6zpB_c!z6^a6q z(>iU>1}c+BJ#;69{K#eIiJ}?)Ig^vgt)6~XudN`IQ|xc#k8Wq%6hRSK>Z~=ZBzRTT zjuP>VoBi*|W-`N{#ID|Uh8Ob{6A>>Yd(F`OnJxR(A+4o%VAi1l4UUXta3=*X*)kXH z_>eGperI}|iqA0dpU7s*xKQ#?l-UZA1>jSo0?)%NQkR#C?JsPvo;{bI_U_tMHY5v% zdb8#BF-1Oiu6M9OaSahQyi8!D8o6RYJop%J*1%!pAUBMMcU8G>NZU(t{MO?p(fY&L(#|j&${1z7;ukv8$jI;p zlFw=D(t9Q&B+LmG+eNsQ)mWGAUcMJMRiLJx_z9O=Izlvtba`X8Mq`}PapV_Hm_@6E zI635>=OIgGAmI2dV=V6x(KZN?7OBg=xVOLkv}&lL*5I!avTrFx4%5v zra#KPL&uomZ*7@ayeY%F2|KWv&DJy+o7I9s?$_yR5))X{ZpzMItQX}rf)@Tq9CH>x z8n*i zAkBmdR#5w&0#6)$!qE4Pnd^B{y{*-`_YZPzbjDfd0Lx~z6;&7a`V1dxhrPuxLVAmI z5vMvgA$ncbH98r94YeXI|clc_Mv(UAByTe@y-OqFLA9h8*oLX_1Ni^DD?f z0!1dm$|1d3jX22rSjX+TZ=*}x#*SC30B(0&)^iCnLjxTCk!F6of9UX2MXo4oPB#UHM9r4MFOB|e9}kMy(TIQmD&ra z4xd(dFb>?1L$#sU9IuWwZ`cam`Cp>s3Z z8{Sx9K5)4Wk7{0Chh2hD}ZZ*=T zB~J(zMss>Q@8MTnPMtSq4xvvQMF7YM0+!gEnY|p?a>1XJ*C|vofj0W%-5l1gq6Xhx zR^RD!>SbJu4-X3=7qYR0;oDPU4Kl{`3?B?z_>w0`&GK%ieu2CwMY1S0VhZKMV)6+k zg*_r2Hx|qN{nYvj5rhr&56vc0wuV8ChP3n-3cL9mL7mwLir+%z3b~EU6< ztz`Bd!iRtiItiEXuM+Ss@EezkSnPB$$ICbufTF`z8WO$vcVa=Ss7xjsXJ~3bzc_WE zA6CXff(BD)U==M{ob*^a1>~np`F!tVZt_l}ql6Ybbb~psd%utm@TZW~GHz8=7v*Z; zW2GfrT}QQQ8=i*c#?+h7_LR1|#IBl>Ow=2jGbEt%r}CDYPC$YxI=+$`(y3wjpv*CCGUcLZ^A zz_V;PgXfH*hdU3(8JW_LeT1@2jdFk?$ggw<>=#StlgVxaU4-^rKcl36E zwt0y!GeKonT%`M4Y!VH>93ndTr@^GZ2)v}*tOs*#uO_R!CZ~8Wkr6Q632@<*yRF4I zM@Y@Mj%q?%ye)rBNA|%rz|Ero5#N@O-v?r)9x~Z$`aZbdXTAK{CQVR}KfB#bxCL_D zY7@<}Dl*Xm_V*8Bbj_O36&Mzb1gs~zaLBp5fAr_{llE}i;utVTSvq>Wb>QbYo&D^e z9>r7F$YXH$9`r~7P&<3PMFRrGd;6)n2NwjXK9mX_F7;doXE_-2P`&3kjUx^YLcsYa zM{&$fBX==$N42qH0hq8?7+js)VQXld(fjzl@N{ZcD02dFGmiEE^g$zvar5OGMCLQe zcgZHP29=g~PMgA?8LA?g(5424-8|UL#4Gs;sm63`0XNSxKyK)Oa*zRs zv~m^Gg4%}aLhaqwaPS%nbq@R1*)TJrGwFdZ_D*ti;vZxK#mIcIj;xLTCb?f(qB?GN z+f)==NJdb`^P!!K$SOF6KY-Gn&V#)x)pjj!HofL4Mb7ZV1$UVvB*GDP+fEyhSU`&D z#%(W2WM7;Kdz;%>o3!0_-TAWRCnP`-c?N~cun9RW{4j-^!}>bKIY6da1ZO{5iJ0A3 zw%ACbwYt#DmxoF)gk%D`|ApyKQMj%_*OHN`AXNq{XS;sKK))jw)_$9RZ$?l|e4fo4 zV)t)haz`FH?Teve`-SCp`|d)vjbyf0w@C;v!Sf@S(DH)21pwfL9xn!FuZzU}tkT{O z@gPve(O_*p#s-qmhQX)bqouKpyaG?3lVGJD-QRCtp-&I@?d<7c?`TG=Du?Z{&o=Ox z0^^VmuP--)Ib)^|WhP>crBTDQFoA#`G_sw6`y@YA)SYug>Ia>)lF_kP)7=6H6}yY|`l18;)VWZusgZ-ml;Hd97q`vZaVi-$g< zqiJ{-pID{JM$Z8KEH#3ycd2#}+g3LLR&1H`%y|oLL%If&KBAXC2$;wS`>-SosNbJT zS#dih@8>!r-*z$*?^o*c*0E1(q;b5n>fQOsl#lKEmqHbmTQddys`cd**>%;|{(7RR zMKr!w8>E~YlE(!RCZY-Mye<$t!cHapgAsb&$fVZ_7eD#a%k>P$>)%MwNT=6i_Bwoz zg>#>YlcrGUE)1bT)`gK|z|mv;z|9>rou1-xs39Ho5c%NGM`o4&X-E9;2-XH8`JoNp5iQt`@n3%j+%a43| zClqf`;vLBvdVd1nx-ecStWZWl%aXb+Q66WU-~C`+rsdSdNdpnym6rpIP>BsI$|uSW z!VT;Sv!PNjU(T{vVS)FTjZ-b=<)L>)Aw?_*D{VBk2LMn|m^WYwHwLIdEqJ1$n<{XW zooT2hHqQ>+@um&F9A}cRhF056`o!Fe@|ELA*=BcnlTmouWQHtxOop8J_Oq?}Q*rwH zEi$Xsbmnb&MQ}^V&lFtoH={A@%R6ww;{@*E%tTrr>4`{NNG{k9Rk0`y73yl$h_?40 zY_ZL{kJWCJpnW5he~dV2;L95lGawq&?%r(>^NA;788exv&c`Zslh?F^(Cs2Y|IpM8 zCtFCq$B-+JwY;avs}ZIGNJv&sNeplTKtY2COm$alMc8A&!zCuSPNtEa+sDPD*`48# z*F|^4>GQdKe5n{7pIc~|J|Fz*x_z$qESy;RS?NcW*C?!a#B4DcRJJ5Z>)>O0 zDsTw)>^>NCj>Mm>pb`)r2&obK`II0&Fi53NLh-T@f&+biINj>(#@p1@DH+XOIF_vU zkdgUhce@+V-7~{Dh`Z(eG0#d-z7sl`7e5+iS^1rZa$#;Bw}o0!_P6*$e_)p@S>4!I zH8gtglm+4iQw{U+I|LP<@}L2$;GCl97NMhp0663I$trjG?=xR$pGV|TNGs?OU~*)< z7!97*Kic(|1*w6ztIh_9Z;OT}ec?V8H*@H=i!kknVmwALUQ>5mp)C1t!>u0H-ATWC3NIG;(uOA6GI5 zifOLeRfWD1GjEz6@1dP)fqhrPsAi$k!Sh1E&;3a7rS zLsqHL>TiT*x*#f@p1i7bvYLN|LhLrLQ=nb8=gN|qb7X?peWd^M-QLRhK#pUB`sSV2 z>mWo)YDt%*Q9eJk`hXk=!SC{^uoUbRKu|EreKJ>BNTgXn4K7pDdP!$$z6g->&ey~Z zjXGmczIPG(T|4J!Z|MElzj{pBL8}o5K6T^e z=n$jwMoio|Pv-nwuo^;VaMwDklH{PPJ}v|k0V%$obQ>`VEvjlv9%X0P`CzpVk^goP zD<4kG1~W(Bc5Y{xKER`Ka3X1gXV)~CGpa_N!aF#qetO2FqJf9$QMb?ThxR;@HqH~p zo1{_3$$PAB@+qnvNdjZ=J&X5GKxi%v{db+O1)fyrIgb5hR*0%jcj zy=mW(<-NZlx!jDP(rR8=l~Q`oU1YE4k~*p^yl1@w(^KpHj8pCNSH)`AF~Io>9;y!? zwMU%ZLoIFT(P+saoYl?HXE!>^w*;_(#*Fdh8xtI!Mhx?fhSVtd?ahZ|Ze4(#uS6-{ zF|&PsPc=SaO;Va&PZ4V??pr2mTp*Hi!f|(efwp;={g7I(W=vR_x7z>AhJ-2=iaqa} z+59H&?vC^N$)Xgofy&cJopnGbPGv%TVr@Ip^T|^b&7b9Zfl{7VNF`Aob>>;CEuKFZ zmGT$a)OO;BU>nu;l|1LJyYQ}ullC0p-XnXX(#Q*7%k{D+>4`Sz8tC(8*7$+`lL{m@ z196>0wTA4$q#Ij7<~m!+C_A7i+vF9WkrgXHmgVe^(kcw`29I@^yI}}rA-zcEP?AwxUy9I6oMd>2~)ee-#sO|mOy!zzZ9)wb)_=fLvh-BX5NB-10#(2OR^j>3msJ)8(1NV8vn^fq8KY_e$ zvyTGg`LdJps(se+RMT=^axZ$yzgc;;D|g6JL4K8k(%SdpXsr8_!m88y)UaTolPj?v zRO?Scx9!^$yvCR$Z||}_)R_~>lx08RFxM2Vi)Sp(pH(qijQtD{#HZ8|nd3{O^YZKc zf~C^JtxsTIT*F5vHHyi|GC0KUBNdc~un}oq5rw5*6cQw_&q4Qi9ybKrxsEFkj=BB@ zv6y%X#YE2)<3r%m!gP!Js#C_bMT|eX>26}%YH{g#$7f0qKmkf``!eJW4GoWYb&dgl z=h-&80NqdIsow~BD+hKQl*Zl?qa?Q2CK4eu^e%9hg8ZUg#9up|31ygF$4D7%t}oQ~ z5*C1Ry(#)T?WHfR%948?M88YRK7j-HEcu;IwI&-uk*!On4LN7u6(7*3T8+$?b8b#n zD4zk|wBT8j`(&Y_Yo|mbsK$pK-AGPXzu z9LHa|xSCE18$_Y`WXQvoOx0o$ghET^VaG{OtoI?JO1@?j0t-17{+bsW3UHC%bz}32 zOH8O>RV6%nJP9%7AcWv3FZ_4nNH{FGT)5ap0X8{n!y;?ud!0*DXcSa2!_#-g0i&4` zl$mb)Jz&rD`0ep`{Sui;;U@@F%h1t9(!y4$OPSIW+Ej~iN#?pk!g!Wg>Ozw|qJVta zFZt(Ra&nF3l8Ha}slk`2xP^yVU*p;yQloB%_gs@kfoS_@_e`Ic%RN8YoFSgEDI~jG zf?^XYvZE5$v1!qORCm6>^Lq=Oj|q_senJXiu#=XG=@8L5MU%zLitWSu*7R)(C4xuQ zD?{ECqi|~G4S!bzS90B17b8J5<#5Z219j#3$Jd(YlEms6s|M$W8vG~ns5q324~2hb zR+$HhY+@355p3V6$g9Gh9Oo^^NpaxStKt!u>VIm(^ylXDE4%|*Q-S){b<64UkX%$) z!_|mEMqP-IngB#U2LY(r%KZMiW=54T_xVH(5qLIlqtwhkzfIZsg@)dU_jcD5Q4=YsBk51pCFdd8U5n1YD~Tfv-jbDZ_q;D1y}zmn z!0P9M=Bz*NwkdXc2-&?A^ERuIV|eXiJBPRa{j`9vr_(uMFW|v5fs3j0JPOH?SV$i! z{}BWqP@7=#O!lRz*6JJY?|iWy3_zX=xtwe#grZY7Ps}gcT`11KJ77iM-0N2am4Bpt zW3(9;2zKZkxc+?Ie7i;U68Ug*y6&mFD2K3}2EKiM1)vE=C=M$jpJZi$M?!0qq$Dv^ z>Xi{?*^C)12Oz%ACO(|X850Bx!>F-G9RHVx^?qLOKN~UAqcpzIEB6E2Q#BGF?~6a} z#~!>A%q}?Vz%BT0ZqEACQNPP6`P-TN=TMD(;+0e@GqcD7*^ya-F95N zVoAoe5xz~lcQ=hifGgV~i&wNC-a_*!-L8j=J<`d}^^sn$46YxaMsbDpg-soI)ll`u zfDI#^Y1zBhY&qteY1JAVLAZHeFlzJb%?}Yvd%=izZC?URd#IkFC>^ke0TUtmTmS0j zG1=utD}CHOk}pX8TxR-#hRK}sCdd59ie2*`&KAZ|szH>_%rDNt|BboDc{OEHT@z0o z*_8x{v_d}q!?ie4OJySw|DK_mmt%|onaFo|_7;R#^);wu&R1^bV`i42PWj0T(U5{! z^|(|C$}I2U9iF`0vn@|zp+St7i?n>36HNy9BV zV;f4a$;H>eQ_Yy%{|4sy6|5UA?J+M+jWgD&Toc=J_)8u2 zZtYU9^PL=jHEqFAVj5r;L`*a$a3jjyAas7f1Yd{P%+$xuj9Q^ta=~Z2C)#0sJ;}6} zq$*d4Y&qlxD73|I%|?Fu{e}k?lOKPuv}6TGf)HDN3n|f{DftB28cVZxO~*Cr*5LMm zPyGUG@_s$<5GHhis7^b}i$q##W8Vyn+gs6e--wAl`*Ytv+=Zy0J%dka^!M=SobkOX zLe*-bIvZk5PQ=!{Mo~j`WVRH4z~&A2>g48>u3S-p7-wo`M58qz5{59gr+|L+AN3s; z%p1gVxrAXb$xzlhHNz`T7doh)9TNgDNx!irdlM|V!F{;?^mx1fs%sLn1;s-K!f9h& z6Ki?tAmWb=vH(}iO`|f?{xU%bb0;$mFp#F73Dk{JD_$wWx zjvG8ub>5m`Pgd?EKHnSqJ{JH?%i`7OPe4^tp-hU2GL+x8EII&ygjR}4T>7Cpa=9b4 z_GaHw$An=<|hZK#Y#asH)$FmGNux? zJ`e+@#yZEH$uy&A-@{&TY}ygk4 z%GTL2U(vH>4)zyWr8}DkwCy;^)O}+B%nx0(^X@0SmahuE>xXvVLv;GiK+R%fS&mz6lsq$LL)KyHWZz2)<6$q6TMgeAp?}oN&pKSf8a|T9! zWol6@RRA^w$##Us^WFEYtkp|I`U&WwrG8`e#DNN9bp#?^s$!>ob%KIH{O~mZ)HTGq zs*5D4w?$`x#v^|-GkUoqhqUV5zplOG8AEWD?t0EOlRHQi3vbfP#iv<^-sNo)0z@<| z-^)oyqL!vW;RHlEil=K|mJSON!Di~3JMtVg)me0!;Z-9fL*oCYLH>osS5-ykrgQ(u z*RD(ZvpQIyp~^~o+O(n48%wf67C(AuIE&<;vW_0@Vz|&14D}S-2+Rpher5Y(NIG?> zxphGuA)G4vEyZ|A{%_WSUBXDTkcp%1NPX-;M`>X=T{(`*Q6Z=HSc{S&Ej~ z6RoZiYBWGZ*biHk98d+X{H2gPhkcZ&Wx3D%-x2)}+dK&K)#B(S)5j0u-y)L=5aUlO zDZY02(yosH{@h=QcF`vK$gkhJQ8GkZ;DFU2L}_b)6B2~o4=*$N<6tzQi|dAdFKiAR zKld7z$WwGwZ6w`a%HoYX2=*E<3)HVbadI8A{V%8<{PefOopATfJV(4BOYGL3Hb=p2 zxJaj0Bk4XPKQlNGttFj_635cdZnp`8-^RL&MYt)-D!3wid;LS5%8C8NQ|SEWjBPlPfgX1voH;sKEafZzapVO|l5zZs4CZd}wb4jo;^WSR{S8JFN2 zKZ5^in)z?j_|gh;#xNQkDUgKp5?R8%{|~-3PU8rm(AUia?(hv;XP6vgs7UhrUzzbf zn}wZ#dW>N$bNYQV{pJ;`njb090I&#_=suYbF|{)(Ut#lzZIqqmySFlY*zZ80FrUX{ ze^NDY&+x;)Q>tCL3V68*XbE_EhG9_LyHJ=LG|`-k1S9r0U2Y8qKW%J&+mY+gk!raj z%Ig5cvs&4vXUfsJH`l3y-OZpt}emHKlA)6di=EGD-29u9&{R`rfpP#g!7Og;N z8{+H$i{EZD0`5pCC@BjKzOBLBK)$C954dN1TnKnt zaI^_Cp2>fCv=Q;Wg&NpBcC+t<83$Wo7TA&TehbN~Z9wu-uWvr!;!Lx~$)1;<`0O#9 zL%L{(#ebDIqR&g#j@kzJ{1^%1O_(=x)zx+`Ova=!$t|+j8 z=Q3oP!>U-irG=Uu?%R?1jJtz7?OvfADUnJDk%wXcpzv3|z+7+2to?V%L)S$Lw~&Ct zIn64*$ycP`0i+062IUcVH0eP>WrgL27mv0!7scuqZ=M(*ME9|Xubf|zy7SuBhc#{f zx2D=4%h+gD@P0xXYsc(|L&XmpNiw`bErhvDlpYL`@lwqL!NZEbTAF z^Fk|Xi(_vz)dK=?#9D5To^GCzyYW{wW?#FdVY}xkAH|g{6lK_xP<6ZjpLgHWmPil| z`(lxqj{cwf157?i+;K53d^yV5{gJM+xzA-n9e^4v5lo%9;g&SIL!0q*<8By>&6%`2 zRh@vSlHk>9wCy%FjnCBbR^(;l-*5zMv*($l43LCsaW$&1p56BkKtz=gMPCCDQD371 z(NB5pwtrV<(UN@EQIo_~0Kk-|$?y`pMK&$kefo@Cs+tLTlZ1@EES4)qnJv#Gm`cW* z59m!P;*YZxXIu2v7t8P}ci3a(7QGP>kMW77REexm7G7Hde`4tF6*Z_HM!U)Zr=mX` z`>Gt71WIt2#(LsJ@amg>a@Scc)SHwCW=L?aWEIwX|{b7nb^%dOlx`sSvVQx{oO zXB0G39m?Ol`l~$7fM&~L7tZ_Wm@F>$QY^>P>?N3>vw2HtnPdw!FvM&E68= zELc!?!_upq)Oiw@>b%Qv1YKS$;D7iZeDM)|oVU=wUTJQ(Y=UsWX(UwciB3r9P^)>h z%=#h`yWM%~CW#yCLEe29qP0>Tu{-5?@|}^95r!BwB@+uzWXko^U`5c8#mVuy`I@M| z0H<68N;YjVyq2Q;ID}V|F2KFEGR0Gg;r%pm@74HRDVlHN1;i;Qy#tu!HuZ?&qtT%l7rBlcxIKrj7qa%b+^S%@X5R60MN3 zS4>!DY1N?bgi>w4CE76mMoSGGyrPkYV};c_fYCs6KoQ$F4t?Bjy(P<~^{?eGD&#K$ zt@^lB_0nM^{ZK--d~t@Upc+JP#x9OOYTjJ)=`*Di(^2Som>aWH)UHO%E|+X-uW-#?6mM zPKv=_5eo+DnJz~Zfyg!xLX+Z`I$ghfKTwC>AJjxaHwvAsf9tC>WL?1m$&0J5ov1D zYhh7)YZWfnh$v0gC|I~Uok`i4tx&7d9 z(2%@bYo57U8m~>eUS*|re?b9vwyBB?HDIyv(R>N|dX5DAmaEPm*;yF=*|+oSKhL;M zdyzSOL)tc&D~x%^^C>w7zr;f_0%D1p{8~Ew^q%5?_IEO-zQ6vY`B;(-0?{>?TG6Rx zmBJmg+JYd+YtRmbtz{Gm^{(4OZ@EvCVKo7(Cq9gZ3)0Hqv+%TGhDxSJvLR4;K%R&S zt;ykPPt=JUWmlBrb(#KtDyyf>5;uz#mPiaa*y@MCVTf287!Qp8t2yMNCe%rJ!kjw6-z4*@`_lL ziFD=Jhn31TmU>OOr$>22Q)eflFsUCWEkZwMq=1d=HFqxMM^LPf^>4>N7XATAs~=i5 z2%Ptryux$RmsEJ?w7Z$S5RR&-TTnGZ8Gst@$j}Gz?1y+tyTy#27Vn2!I)8HB!Sc+* zQ0`@!Vjr7m^kKm}SyC9*0N~5O=zPKl^Vd$`zpE;k()DjaVbge=tyb>Kq6o}0{Jr$y zye!<8CxOvFfVIi9^j*jyle(2NG6t;!fEWwT(d|hW=gkkX4(7%@5jQmBrij+My znT7C9tSi9&MlP=@5vNk)-9y?}NmId;C=>RG60%ISVg|KxWNmnsB3K1P=h&N*oK6^s z{WqFbOfT22MJiITnb9C3D)o5UO^??Vi~%XsPV9w$4aJSK(R4ac-r;HFnXZCoh7tiM ze13tEWaebE{_NyrChw;!pc78~nXt*7&%VK^`HIb69HPX5#z(E55AX4RDlR_he&9l} zW!sr>>Mn!@P{fz|$Th#M;d%mfN9iaO8=0WXcJo|X?$SA_%kXTU$pJ4 zf8}}B<}I<%5PG~d{9=AGJ47k(ODXRL zWMoX^i0Y&Lxq942p*)cp^Unu8d|)e?9USPvf_M?5mFCet7dwK1D2jf~=8-xPVjcV7 zpFSt1Dc(BQmk&bl&A}S(nhfu}QyA_NsfFLCo_I_O6PWw(dDxn3C`%=Y_r4c*543#s zEeLItv>*wm_oHvj1OnXaqkAQ^UuwWAU!44aCpup4Xf5M@i3RR`!U9a-R&R5@RFv-V z_}P~R{T{N}Bpu7&FLjt>xpJjbA?DeWjY3LQQ3DJ4TX_^xUG=~1W%a{fXOmJ;Z7mI> zxzB{AC(tfwB(naXIT!>zZoQ9WaA1WzjZd*uP_*N6@+Bq+FdTsl266~v{^J;5hZnJf z_Hw=UGfe%LBf%`QtSV)_@6r|$6&`@-8bWS)W$jT*n@+wQ)-_!!daAr0 zkwpVRqJ+RpE_-#+*HmB+juCo8{5pkK)A;$tR1#6BTlyNr-9PT1YP!r{Kf(qn0=2ct zV+bXs6lyju8;ghKu$Db=E2nL(BG5d%d_4^$S%A4?eku5#lx@N0=;08bW1;iC)xr~{ zwv3DalqZbo@Mmef+05GeG_At6W*8_^xqIlh8M`SNO}oj36yksW;JbY#XWK1a_H3TS zQ_FSdXL5f3NElygTdr4nVlV4VA7@o>5wd;JGDP1pv~{J;m0Xbf#2+_L3`>p7Q7VN# zZC|x0;3B$tcWhroFekH2Z%$>Wi`i*&yFRSDpUm9|v6W5PuGN@HXkFPWZnxyAW?peV+_A}3F!F~Rm-bORN z55eZqrP1z--Mf@?u8tT{(quR}4c!FA-`C|$Y7!ndN$Gjo8`gnNA2a?#_*+}mtv|TL zdS0(Iv?`T3G7w=TPi)cDEGV1QWIS#nT4~{(-z}JqzOPO=!=pTbXffaweqUE!(|`Et zX}8}p=)(h1ez(c+f1ITDf=wV2<&8GYl!(`j;!EN+4>!zhY_e=#Rj|*fTAgaW`7_-6 z=Yawct-}dozmD0Ch-jMqwTR?*yBRSHF}YcRYghe$?H&CK-g_IvQ6_(_I%qXA-CSl+uFV18QXQxRR)+GcI-(DO%O~cc0-J zX(&%*m`G!%PBx(*qcc2r-e5-+OEJrjFKO)#woNLR1er8w8aKdM<$z9eAJrUi@ zE2grqoOj=xpx~OtY;W#7F|K_&5oA<%6STH{EDn#z82uFF3f^OVrDhPi?1)a{?48RAkpnDq+N z*h+&rrAcQkiIuIuz2IXutOrALD=#;ol6R(i+VU3V2Ov*;#06SC@43;_R*qw^B*E#wo49w0Izo*A-sg~5A##`JD}3yWGGYM++}b9$^UOAb7GD|x;T4>z|5fqH-0f&|tK_OJdgs@^iHt+neK z4j$ay-Q8V+7N+YOjBEWFXv6auBW?!FjC<%qJ#O(R`ffRIdNdHbwdIThR*C$VdDJ6m` zIzcTkA%VdhyW&x`kQtxMjWVS%O6oKd>i=Pp7fTd> za;K6{SL2`>Nq9uYpeVygrc&GyJU2Vgznh-kXT*r#ax%dXhYy|T4bDyS3nf=ybRjJO zNJ~l!EFRSB349@>2}=92O$KnY5au_AmryyP)f*2=Wog&rt`$H6&cOpS@T`B<>K65)kG#3 zCcPKMgFb*7NhjIwt|QD|kei!K>t$~U?z$X}AV`C|uC*g5yog_q-^wLUd%iBgCdd#O z--vivyqA^b+uHhGb++bRnS}2RHpRQpvRDk9xIH9(V#GqFO~``Tv&a04s0mn;B0yJ; zvoIYl{TatYXWt~O?E<&$9lmDu5blGPkWNGflFI{3vAAR23aoTEgB9ARy4dKIm#fRp z;PT{0gcR1&6gNQfpiB`@>ENj+%j~DyYh1!p#X)2&BbayNBxuXI>1Xg&(c^Z+n;V&; z^9sLY9bJr&<#l?taZxnzs0(G7a_KbT2zneM%d&L@$z70qm}FR0O^GE@)XaFTks z#JuOqO``I!pYp^#o2>4}BhV}(;W|RGOoUtESzPZN=aZ-{z!22lNas)gj`U|A4X*Qk z2YD@^M8-nA1>fxXjiMDCI1CL<8>TiZNS(#zx-yn&KDeN~IK|qQq5?ziLmLdea*wli zJ3aQd>VgMu4;Cf2h-Es(P38za4p8uYhms-gtrCotGC8|wP0tkCN1tWVa7J{!agxfh zfy~~Nw+M2fLGeNd!=5259;Si_tGR*08@T%95lVL zb(2(L2u3mN_gUf+RX8cA%83@)eGqg8L7s*=hT(+7iofK;B*+AxtDR#rQQ-97GFZkw zuOA(~oIQhAt3&|_ma&)t#`aW^Rnzqk=!>B-@R2g|ntIsvz-JGPtQLyR@*q028g7I7 z4LJzL7C3@wHyCq|h$w`w>b}Q`?doFZ4kxG~dMt!9wvxcEI;F zH06Az*Is*aY6v5O&aQ|-%#L|Wm7pBWLc9oSs>rEwfku`fI{A%O7jn|i1EOR`Ia>j% zAtq&@O*x?OhQ(RFzBHI^5|T)Rq|+B_K9}Fchwg@$Xph;cpDst__onk+(Q^oe#;4=# z|0ov-Ae=SuAUQxKP0H;oc;vU6&W zdvnx%@i+qUF9+Zf`wcDK@KGu$ zU@VdD($5Hc!Rc$Ud+8vmSQrAuUR&7FS`v(uk@s0fFfAg3!x7#>59b(?orvkZICkiy zb2&D{tA}t>Sf(1}WKWy1Us4`$?|WRF%y`ifUqEH9pD6Al^DKRuwf>pK{EuD#y3?_* zKPw96*T0P6)j5&Sw!af^nCBM(Flmn|74~U69;wQHXv3gE;Iae&%@)>f@%n{Rj+&4W z+<9({F<8urqwssHu4g^jkTjV=+9OjpBHJ~ex;62<@Wm@*>ofY6o6`Us*!M7bYSV`O z5+u3+Upmh%^`G{3%_=1l+;&mUMPBD>C zQaAV@ii-tD&p7-$;Nv|IU~}Gyl@MN8fh8nBQx=j*n;d(iuNz#<<#YFn(oNsX1zSJc zZ}z4~Pb1ID58NRoLt5;Q48ED>^5El9Gb7$8FTrm2P!UQ5k2sLr*b`-ko(jN?GlV9y za(Pf+rE7w`bBG)FR>i*$n6+efnovyQI&MxVS_|f@nCYGs>BD-A2RD*x9ry9Dl)id| zDQ{~Sl=YVC=Ck1V2uK+{qDYci#bA#J!0JcnR1{8MyLbr1DtLR|Qb>Ma(VGnA=Ej~l z9mg*YM6zupLkY5+7Xly5@QB?m=9J9NZKM$I3}BnrnwmWNV}{H48YY!C3x|d>MQxnb z*HkgmB4TQe+y0I*qQh=hq~(QtvBoCD0^mjJp*SW4-!5W=E%Ip%aTHX00UIWkvZK1 z$P4x7@&uo!6_n59)wIl13b3$!TsWV}1(3=2qrpx+UAw}JB93|zW}W9E(FjZ~A6am$ZpvYveh7gZlje!@$5JTs+ofKyDiYBF12j#+ zd#EF2$y0hFObv|*XXRMClLB#f2g~u4}fLa#qjbf4zSZW6Ivf&E@GioT&<^ZnHA443=Fn6Mfuqpi(;(NG_L8ouW%i`VZz+A8Ffs9PatP(@y!gaqT4`%7fW`6j+evBFad-@3)rnuU zYS+2d6FyfZKfo_M~YGNOX*xja}JatECb|K|9l>DW0+NMKjkqWhS%`=A7@{fYjHJQkI_Ck-kikQ zw--8W$vFw9#Q7cqeUjK3tNK;DMBSr=#+r(2(eopd zKN-(Za$R`_?9gtxXIS^s#$x36>=3!xG-s&*f$&&{jMpH~m^tUUj#%amx`hWDI`| zD8cVgu;0`G`(+LymS{qcG$SJY z6m)z{ep~IB*d+5O2cce|lQv=Ef@7(}?DXrKath7gbc0_RKi?+zXM3Hs>VhYmYUR`z zt3??|`ysrQCAs-c@|P-64%X`lS*L8CNA6R%-j(sU6D||oG)rGELub~EiLMi$fA@Gm znm3M*W1&^5)}ey2p#uW_{X3-~E>_~urZ0zA4;R99>V9LGPtQz_^$kPNwRG|<$V9bd zV5;b3o9fPdwS83cgQ04k9~Wt7>FV*uUaL$yr;R9nqW_hJ8Bce3s6uNms1pCu(lhY8 z&g{i4%`iUn!-Es@`V`irn>xaqdA}$;LITAy4XW^8u=)n8bpC@^dR6ETQ0AfH>vf6b zxDLb4#r>$stIVgX%yltOZi?Jn4*dzj;ejEMmyl!jJtfyp{u%#!#{rrp6Z-y5SbZh} z#e5B#m{EI6`#;xCXHReMuX6vW{AD7pDSIw z)ug8tFG787n`-f*1yFdEk#w{uSS!y!}Cp-G>6LTC$nZsUVzypeSN(zm(GE!YYS*TjZl$$T~soSRv1kEu!*C; zp3Q@~UNDIxqqqmP3{@OS=5f>jkXvVc@Nn|4OOd6o>B;RQBtZuwr(dGXq=IOMf6=c; z_>xj^+@>mF$klVp4U2pOVa#8aeM+6w9=ZEgoYF&u`jup5%ed1Me^(iIq(OLSKbEAw zm^o?LpOtQsE$QT~3{Y5w`J21tjcGl_uYr&!5(*662v38R^kX(ce`W*`-oU;-S@Kgg zO>>SNd9k?ur7+Xv`~?vl;Tg&l60j{q+Tvn9shZaMvXZC|VIy{1&xz z&AX=L6(g%m6q7=!cv_mAdy7G+MYvieA@Z%sxTEgWJ1rt044S}mH4srKW*&3wA-=dd ze#}=Nnw603xe(AFLw~xzdDD&h>$e^i+FP2;x1UIvF$a@LD1Niow|DvGBCdo_%#iFf@g)1;D9?eSz|n*w-p*$~D=9SFvEF-heLNyv5>qfbjM+)W z;n%@2J1$tCrd@EHu$e5zGVn{~sf2?`0T^lI_#5HpEtHw?D(3cuV)wQNKEt5+0F}XQ>`uNbQ|SH;o;4!#^qmP{u~LAQ$^ksqYhoe7D*HP-xWabOOP)S$+86 zz(F!Adt&JO*R`gSW)_>hf`F%fwY`u=b@jb2PyhuuqGZGMuy!3&UFqpNd7Znon)-5c z$3kp?mrIQ3Y!4hSVISxzy%FPfc9(hNPQw+KQAbOmpVKzZ6`R< z&%Ly4$bi70p6acJl(w>JaTG$ZrVRZ)h16COMp$}R$+|t@^OO_*sJQ#Z zPSgR~RkF>Oax3Dm7xVzpWY37#cO@J#o4y-5wLSbD6HuRVDWkVWOu`^q@?;s1FRQ!o zc$R|3T;-Iw`a&SwNd?yjT4=WooOSV^rg^XI8?u74q_lokeKRf0AR5po^C`-KvKZt0 zdrSW!AqUYQF6hrR1WI9?wK9g2P*6mz5jiwLpQ>3tn)YgM-t^TWyZHA@ft&!Ld#JFz zsMYal)@kzRPr012HxHG|lun5|J@O&2`fDr7s}&%Q--F+p+ND#Kg<*>o=Wq9|OG-8l zpa7wzbJ23HTl3{*=ZidZ5cPvh6kD}Z;>%a>z78^q$#a(lfn`S4*7x6ulWD`Drgus4 zPfk(HFa8h?hio-65h#>rN}yB>(#;5_4s_e<@3D&u(r555JH1pQr4T_9KO45qahUN5 z`X10DRt#lct@{7qs8n5t=js8C>?mQHQ#!+qw? zNkDy*0nNk5V7wS3&Jx2eMFJji#a-q?g}oFqhnmD9ElxJ_WZG6TP!Jh2M|EO$tj&6#E^i0EUw?Zcqrt)zO(FSLgnG|6K;gAx68?cvIO|{S1@3Qdn{|h^ z%A_tk1;%%Xdbd$5%{*DHJ`&p(iTZJl|AdG@2Oc#u;v0x#2r@yU&$g{tt#Rxp&MmCP z#GW)a?xEM1*qfN$M6WgCeN=TO{*H+~c|6o>fz-~^bwe7ObGkmIB+QdAZ%14DS|nGp z6SNuYgwrq+xP=XSisyRqI{Pdkjc8LshmX)H%hD>!S_h*Bo5wd#DY6@_Ri>EBWK? z92*!tvXR!C3^l9EpvfBjl%LEZFE`##RQPrn@Tl*%TLQTC{xqw{D;=4}A3IbfhD!sN z$e6260<@?*DaOyaA_SoQnf8iKOIoIBPCoe?H!3~dCy*VVBvsuM8Anc^`VWpwq}#Zv zYqqwC>qp++(tJH<7~6CS#VcVEy;{BdHJd*_fU;!QG&He`xU{%PMM|1!X=BWBD4sKN z&b0~gQ(pbGvV4nhc1ZWA^SPaJY}`4;P()$Jc+ zSX@nvpHCGEo|i!&J5b0s#TJSgSmlg~5B7y}rRJLDxt{rDkL`N!U=kBwceq*K-nJDD z&cC$OF#dkt_d{CU{R(B>dMJw!p1k*`zUfS}W_=$KE3$_EG-ffYP$IrNJjdz(6k=!? z`{g7~qpuHj^Sk?eQ~mGl7Q%^}jXXJwc;}fCX3YM##1wIY3VlAQ#r?D$sdb8g7-9&L zzlVHE0UEQ@7=iaQ{ka}EqP1~JZ?XBvGRvt%jA0P;o!rA+mff0;scli8ZVAFNXq$LL zqv&K6Sjl;P<+!78$fY-#4`{lTYGi0Y^aR)3|-f};#AXW*PGBh7}PP?g}yZkce* zf*9JrwkdIlqhUvj#76DP#(C?lwa>yDVq~RDb>WH=Thfb;mf?z`qrr#d&M!2~Y-ej^ z=8p2v-FYv}l*?XV9G-gi8gSDSb};Ft0~o!|*B#xUtaterB&7fnkZ}gtG2&sT%r#i<=C`fU8Hk`|Fy%(_XuL6@Rob70EBZP5wsKN6t^{tGJqJ8Tl-ID@iVZ1Gymg3p&@-~)+o<;if9 zMX#Ngkcmc^L|8G+%sMh5hMOPjVGBRV2ZP~)EH7VIYlK`@e&!FqA7Xee4qlwiCq+c- z3mQL|q6chHqZ}kJAsb;aMsL(e6hJx*M?-D&g+{(;u%P{b;zf&?Wj{Kr9hnz!g=@2v z@s#DzD$aqaHwo6=_PgreB?%hPv5)~?;B3@8@)#`H$X4YJXCWVsVkBsRWGpe3g}}e? z`d3*Ywz0PteEX>s9}5;`zQeyya;k_!8)xxzSm&?;=t?%(MQTIA^DjPUiPiI+%rLdQ zwh9H@HsLO`J5CDAtll%zw507>L?r{jvLT|_6hfqmWnrmlkI<9voDQ#OfW>f~RY@)ryNN8Rbk z%yDZ@VE&M7U>7Sr@nR8!hiQ4kGq2rEf%o$3`BJ@}4#Akry4 zG4BngXN`JniCqJod`cXEjyVA-Q3tP-p6Zg(nF4`YLn|VBq^kw(M(LQ}H15c1lYtCV zkMFu?U}gvtt6{}*2-@Qn97ppjtUo2e8rEJR#LeG-?<*wEAfso>GGeuQyu;pLJHKf-?Hti@=u%4CKKw=oAwi# zTvt^gOyYl+DZ_;du7WVS-&Z860tYtqzHq~UFe~wda$XlxOf5Vvrn$o@YhXXfw@m=` zM4lx=7RLVO&6|9t0xcu?O@S$uBd%ly5{_C!^3S@E1$vjPppl`}b9g7!!8>__o}BKA zxeX--wg4Z&vI3AMi^V`JFm4AH)iZr3ZSkwj;=I4Hw6dxtiy8-l;-~NpM;{sfj7*?56dzi+nAaIklBUc;B z`C)qhnx%Fj`)Mb_H+u}VMRCyu`313YtyAAOT$M`~W^J}qLFkxxQkC8NnI4?$`8i)c z)7NWy(-VDJwk5%t4AS}(TBw|-?GDlAAEH4@-Jw!sK^v3{2=1AiCjD4=_#uu|ycdyg zN3=t{7544#u%nDpCMdK9$H`Kvr|RQ*@EZodU1V0WqkjosL(h9dmtRo~wU$h_3ZtYh z7g`I7Zz%?DwIJ~EFX;WjNsbMJZ^%jkR6|MGD(sW z3N~%fV8Ksnx6BW10*4u}v;rG#j~~(TaR(3%m@5VO_GBjY;-mLm4Cebz5qL|89gU=B~M_i7CJYK(Xhd)LMx{6f z%%soeKhWgrUDI`_ku3Sw#Y8afn2h|}KY5a#S*YvSd$5vAA+y)y}r6Pxru zG}n;8{(GK5@?V~_x)IcFU4{sYiqf_ko|eT(=W76|O#)x|ZJP|@-D+Z1>3j2J<iv7M>v|4~aYzEb+Wu{>OUXK-G5-B_o~L4*4g0`3^6-JH zzxm0EEoJh|`_YW-g&LFOH$|6J^?Pg9CGRaE;9FQI4+3wvcaukdU4rU_GzB~RmfQB^ zEU^=s!*v~Ok3}3C1-dAzIk$DpFhn3dSvvoa!&ts@o|SyPh~HKZe4JU?QTs*xRN))a zOJe(3%-tXj0oFRvA$Nl566SX*l*VyiD~Dk)D3~ic(Qj)V*dio8J_Q+%`0>2Mxh?qP zVZ0A0xk`hI1|sm5XRM3q#7|P5bNzH;D*v(yHIO3FXtmV~_+0(t(jA z>G|O&uiyy#3*{~LweZ?M2&KI=P`&Z4eSJhQPwe4ajVVMCc6NG6KIKG8~W$fr5)soBY~1-H4!sX?3#jb8$kiPPB)N#?N&&GH>~2 zSFx0~3-ehuJp6B`=XqA z-Lv@Tf=m{A#$lCqQ`*Fvs*E;0H`VXxfPzL7mkD_I87!bplXH%j#bDdq!f&J&t@yIq z*ZtZ|RhV2S?es$JCd&-xq*hD@O{5%RE*f)qDWtF0E0tS5IzvC65rm{e3Yavuo#3%s zy-iF2kO3X_RS4vAE6OwDP|F4?AYM4h-O8PMwQrFC zqs4Jy5+U#ji)-tlE9fhqB^#HlfLfBz5^SAl-j{4)FY5`$yLW`oGY?BwP)L*P&n4%d z%h~=sG0>-*3KPhlWXY}9$VaG~=bS$9fP%1iC_4yO4Y@C9&~0(^mJn+4Hn7)m15oD& zS%DR78F9RA@@jfOgpK{mr?WXE)X!21HyjuCr{w|B4%&RE1xJM(p5dh#hzhv*B(NXd zQ^zCO7G;oe(x^~qT|$6O1`17X4VTXn&zpolx}j83;lQ5wU)D1>^trTuuGRm91wIc3 zems8)L&qJjfYqLl*oq|~zyV^N!@LAkGNwiqo2`oM9R&Oq@bdh?PoO)sAAYZupK7&V zfRc?lrC~E|Sho>_x`9QF1|ywhHcPf&er_6Yx+nQZ7$v-SoN+Dn8*+myth{z2AGuH= zQcsldMrE__!>@2#g{kYzN_gU_9-$4&R|w@l@~gWfZo0v32!0ChfuDAe$OZcP5% zKqpFr$*1z}C%kGyFfKzx$NO;ZR$2@I9GdR5LahoW*mHCU?yg(V-bL8a)MLL_x@w3i z&ECb1!+MxoWQP1)p+aYQ=ozol~*Ec%O7`5Yp%gdoag?rd2Y z8r`t-AyM8xXMbKX!xE6XVlYP^BUu?RYn;9%iIog-cU#psPCDp0k&hHwSzu0=E-7kz zC%l6Pbh9v31R2=p6_fBD)NC8ze!kqg8G_o2Ga*sY%=VQaT~%DN{8$7%2SyklVV&r{$Z%)jT`_;V6_95Gq}S^KyM{7xViU9ZD1q73|0rU%BK+&9 z|FtZ+jCF7`!U}cJY8td&xo^(iqu$r|i;r%QIwuBOgAZAFwY%V%<@t)wVZYqi_M9M-r!p&HM<&ukk%SzPu+<-t#uZq{ z+^NDG+Y|{@;b(rcqL|fu)l$|5`ylj0jb%sUfuPku2EE3O>Eq- z3xCh+fnKX_*d5*Bw^z;$WGFxY5yW|YFk_{6`|U1%M&q)PIjgo zbD;3xo|Ch=%(>@zNQQr8VV_aB)K9nx<`E5jCP0kbL{dBZpqp<*qY35kI~*-f9?4ql z&i(ZO&EG+S@M*KYP>#E2xm#(^iTc6Rve-3sA@yTBFxrDLHhy=a&5ps^@w4x!(aF@* zTr+%D<~y+-kW$6+S(`c(a}9|#2xw*8LW?`FRIiP~Y%mPo>1;Vj`+wZbWCkGh0jAO} z?_*!JM4f|a=}||o{}DmE)for}vyVc(+p~~bp`j|xq8TQQwa~Z*dP#>O>->Urm6HGF z%o|69_^^D1_#FQ}ZvQ4c7q*84>;t^UB3GHPC8Ce2)_x!o41+*4=XKETrYL(pRG_hu2Z#^tsFS%1D2nj`hqGhkx&8?Ll!suQb z-3d>>{Rj$-LsL7Xiw-5Ovga|Ethr@={4wG(z|;(~Hpz7(4S+)*)dC~nC^gVlLR)0d1?S5QDJHMuN_kTdh z-m38C6llg1!iT0!x@YP`WhXFw-8-f_oOsrAg`?=ka=SF=pYGW#_zrPju;+PCouu4} z#S-J=ML*#-^aQMBFX=D;_napDvwo%T7*{UNm)_9B^+fZk76TIsdUNe3ScVw ze;e|*{5o99$@Q(#SIoWXEd}M|RU}h1GzuQ!-L9zVqRH74hdQKOAX;C7p!3>a=Y%(c zy8CZow}b;RT!uRAc7%!L>BF`qW8-w;^1k{+8wlD{Blfoi{wmZ43+V{dob> zX4xLfzS3T)e)flBO}=M~o45NScLuk^D7-}uP!=q3#e)5#v{#x`H(PS&QQE8b?#N0ocGIx~Myd{5n$%DL`YSmOJ5YQU2E|fFJh{K0L*HnbcJS%F zrG-VPgM&lD_(_1id8qzD7r1{O+#I4=H`@@#vU6e!nYy<-;;8 zRqL0RwWY}xN8W=kce+=7$Iz%akQy2lJD)Nafo@a3t}V7HMJNHOBPp_g=u46x=CK0K)X*SyKQ zKyduemXmRPU^IsEv>CNDnOr1p5Hy8bad?&KsO)pQIhAw`1FoF^rUU!id01%Hv+1Rd zUdqEUe$i|mEv1zv>yJ#f^dr_oSCesi%KP6wLfN69bB*MR#b)GA5|YlU#nM68M8)9c zqKd)_(>!Z!n;cXkv4l*c1VLFV^ux7iS!k+V)Nx~xkw9rIY9*~nD*Kktk&{RWy0WI@ zej+u6U-x-)#_~5AN>{2(XHWprfa)Y7TEN-G9V$mZ7MKSFi9>Y2CyR^4FdbMnD zhBv)^V#^oL3690RamdG_scgx@;H{`t#Fgl9zigxgs#?C%B)AG&=@-0#X1(xSZ5xT~ zIkK^89KWFN__9F2re!_M78EesD27CKhZPuLv186FM$!=)W^&c!dG1HQWu8{-RXpn6Id_M%7I1BNE(bE2T%i;J?W5Xf5xJz zQXDZW@swYywIMsVMsbi+$5sc0z(;ZX+#BrZy>KBp&dahJG4`o^WYsPw2?4*kVT?zw zkz$7_ri8_k$B>f-rj%<8q)ct~VduwFLF5N`090{U15(Cc2I$_N_C3qY1sGT){=@11 z-_(y(MfCv~ZES=@V-j4TSRPuT0jSehL3Il|I~!7Y7i^iQTT`gZn`e(g2NUT(_^f>? z)Vd3~cEPL&Ke!91Vumj*Rtj z^x3C=E27|fQ{F5F*&!Mir}y`UpczSa8kRXLIwy<9*MG66s@QFdnKh=P)2?b8{|ATUiBRO-|^uAGG{%-`J(M~JBCK1e#nQH~|LV`R# zQ5M|R&0x=jkJ_{bGb-&ugctE;vorSKG*=_)ASeNk3HE%3Sb|*-BZNsh)puj{;Vm8@ zi%KSy{@f>iR5WUXDv}2;3T|y(33f-AmdNE8kWt-JIhTjR{jmZpa_CaUO;67nwCCeO zOCd_u*oM(y5KL`1MMsc$)?E)fgicue`0Msi!hIJzZm&OL@X-S@iZ0ZJ2&yR1t&oxp zlCJ{SZgw-rw~1c&MPAWjf3cjkgMq3COYIWw;e#!DuHn5Mx2d^!((;71b8QMY{@Q)ivek3+uv^gs1C-S>HZDlkomf+V;2f z^ba5m%?)i6(1faZZ~%1{8{U$i$jDf#&idHgJHs_Y=;E*tsXwlVTLgA5;RkWarUQQA zR_DMfgZgW_n;HoT-M`4RQgRmvNgL0fnmupjm(rxmM=oh`XfdTI1mjaN_lge)psJU6u?^_X0H=gTZpvT|L)^-3N zj6mpo?nTpsAo+4GIQ8xGeS z%exYd92|lqV>r$$!Cb#=JZSewB2$pXkd_K(uJC`kZ zR~*_X+#%~AFiCHVC)@J_j+=gHyX|Dkt&w^GcD}pVA=q)q6G^N}94vC11=Xqah_ zwg^PZZue^7&B79ccM6sqq{8FxBm?5tl~^jd0(g*&vAXH0PD_kcm+9+5d9pbtxxUNLHl#}c6kLl6yRWK>+ zm}Yp?XrM4@++wmGU+=Kw(##KTEK0z38c-7slMbrWOgQu4{rM?+mp^^}vE{fccZLo^ z@4NL4e@3vOeID^oXlwB5qR>0lXUG>o*@~14Bb+q+LPAgAjp#=k0hs>3o;_3G5FbX> z2s{sT#(}N}ibN+N3UnxlG{z+|MwL%Wp*)i}#QA<&DPN4)!5c29xGaG;7K0af|LvcI z=fBOLBc5**tm_#8(bGe&2g;gV)9on1qFTMMPvmZ&;*IRd0xPsYT6a@?tQxWu9eH`> zcQoWCpMq>3`eyWz@he~kSqcGw7MWQtQzi5kPjnd^Nc~;FenjY~`MZe6h-RU7Sd=4- zm2$)=8<^D4(m4p9Zo&_dzW1FxTpmBY(C6aQ5^hLFY{RPX+&ItVn!M@-8iJ@ z*(@XVz#PJSVk}@v@g{Ki96I~A|%z}^t&jG&VK+! zn;TvYmavl=d7ZD3%G-73f@Y*7mWfD%s0mFhWb4vjf3)f2{bNp2CP|=livQ9DG5_9T z)CJ{=N%#*ph~;lgmI!HG4yX8uX(od$gwI3Z_1XJsGa`AsUk1)e5l5oogZH}YSGnj5 zzDZThLhh4AKU+-7%3=2?uR{XX4>uO_SWr^d6nNjh(U5gP!;hu`rP4)0l}M%CN?#al zp|o)nOZ^bKXe6rVQ~d@hbn&#j{iy zB_eTvWE1EdszI_7)Gz#hG)P6>;P}7dAq*9{6xK`GNE)@d{M~7Ok3}Q(C?+&lgl^u7 z4?fd+#6qQWBC*jQ9XB5uWTiVUJI^$KqpPRbGl_ zsxOsY0SoH=VJ77iP*$6q(hP^z!JyPdqVnt$s%BXq>2xRkheMp#6U>^6TM+Cx1~wyd zL3g;m8RXA3T-SpjMS(=u`}ELK-8}muh?=!pSY^3}Kc&^rstg21;KmYB&os80+JpI2$m79=a#m+4#y{8qhKT$h1KhLjVE+WFTvdmSO=TRraVDg8NkKVY7|1=a&JhZ1_C z6Z|jo)C@7X0n$kcNG_h2xUc7jY4-?>GPhtM?uTR~KsR)bCxo>d^-bsAP@6O)CQ z@iNTim`4;0Cpkpnk5~dRGLd9{mWNa5{6VbQB>_+Hujd@$pW6QQzj3#Ta6Tw)k%9u+ zFY!X{KU3&_!KkSA$5Yk-tdVsag5Q|nG7e2SBDqpQBH|_U9EO0EU9h}idpEdzS>2e) zr*~Pvxmq({nl4}exMV^6eLJAS5zB>8Ye+d-H@a!3_#p`>jK^+nB*kc)46iSwKy<3b z`J97R1ex`y){xM39&$K+li(bXysw2&)Z64;}D#xq)1`>#tZB$K_V!Zh9SnM2IdN@Z$0V;$yD|b0= zS|j;yFc+l7|1X4^#3e{C*E#xEC1@ukUzI18zk#cH&>te%@c)+yTFH)LKxKjy=xHt| zyJPL)CB19+Oby5|fUFJBw}N6`fJwtxYGg3ksRPY>XTGG3G`>jI|fm;!& z!t3Es*c^Nik(m$12E5mtEH9bAoo=w^dJxB39l9N>9+wq%ynPy|!!(NxEa%E5FsLHH zFzPJ%xtC`k(K|0NpGu%HR@8@S1bObWPtma$TeicyO~nQAR19i9HfD;+Xc5vQkFWk4 zs#r<@*C}XzK>v)F(h3wQ>Wz<7;lXe1K`hL^LXelWN;R_ z#Ifb&WImMNk7!Myj7#Sr>L%pr(v{+q8?=(vvqzhos!7MtsmehHldBWyj=_;Q3=@a` zoG<{m*2=Mu-uiD7o(|YKU<|{lWrB8n|MhcjjQ@s>fBpXDF*Y7Pi+5*z_Wv|caNTZL zNXs|4VNU36PMa@F`02egEIM%3M!{@uLGKZt+M6fm@4MHqu0B~3^3~*-r!;trkpj9y z&fcN179NIcoRHWRqfScpJmleUxL(gRYxMLum-5|;?%>MES9PK7Eqe6#MiCJ|Gu&D6#uR}5l*mDjbS-XobToOSn-AC-=IbX!M$4We_Q}4 z&Eo%zU%ZA>H?#UjR87;MwywcSohQgrarxY zAyas$9w$m2%LitYieya^W$Ie2mJL%Ahv&2P$0abSt;UbQ_^W38(kz4uWAINHsgS7# zO+mCpu8r9*DH$&~XCC+>4(V2|=K(l;8vK$W`inBERtkqqDqqAg0(^{N)l#V4kY&~t z@DPZypyKQd3L)blwo8Cd3Mq$-YCk6B#CfqH*z*09|I$YClw6g=#*2<%plTmKccb#p z&NgHuPj`HzbFrFt-fRGDutndyk^6&fTDu(~ zMn3sp#o>cW{%{fVe-prohhe8LFPUw>?cEn=iJNcx)dlpg!f>;7PosK)Ar|A{e!rOp zV?#tWY>PVEiHQ?vbF(DQ|Zrv```H@BogkQxB`A7#rQx$R0 z4NDdqb~5DcVdNaSPc=81&bCf|hhKO!dGNuU^6|dU%^T@CRlq%0(>tFcecI;g#VxL%^HWhzG<~JhX%D7DN_e6?$*k&Z+Sy!Q z*W;h#PW4!xCC@)EH>B@%5;wb9IZI6h67YQn1Uj_v>xToQ;HNf))5^z zsaPA}YD_y|M(a)K6u7kL?COK{WoL&H%NUI{wp14ipYth{k#A&EOH&E8YbM&6+A<~O z1Ygb$B;6&o>~n(4->3Occ6y!(-(@9-t?+Wz;L=@tkoUbI;PwYFZ@*S6DoUwPbeoVC zX1A$)dwJYC+iG7=t<#4O?J?ydLPNar`R5J#m)QF-L)4wr$lQ;gz`RxAIn;%R*a<6I zBST-2>}Sz zR?}FadwubaaBD&s{BF90(fx#tBlgVl3r>iyW%Gc>fB`a+8yF1GbdpYdA7s&2?;x}R zA%rK3{W+kl5qCl-0b9l$Gz$Pg$#S8DVW`g73VaD(KG4F!+K<;WS9)IP@PziUVC8rdZ1138Ga8EV7AneQxyD5+f2rGStVs=x=&p`kSdlfs}7HH5#gWQ%kX)a7e{k za>_ec9P=)r2^VMsy!|?x5i->3g`xh#-|MsQ+86vu$SH8vFsY$u$$5lNL!2;!YRx&J)en&2CzL^l#8U82*$M$2d|o4j%x+GtXxF*XH4 z5LJF5ae5=F;sd|-pWVre!J}GQlgB_g?Lk<(3>d4epMl>hr77nUKO^=0ctn0>@Svcf z|Nj_!%YZn7XlrnAcXxLuxH|-Q2rj|h-C=MikRZW5xI?hu?(PguaQB@&+4t@4`?39J zre~_lx~jVCo^$R6*0Y+jpXbe0P+_6`u?mXG^}pzN%&PM3pH{`zS5C0^hZDDR6ZcK-kQUKuws=IPrY!% zcjF%3xMXn&;d^l4zzC#dJfq~0J|<#h+{t(l#g7p0Q)D-nFK^o)eBoawf|oh+9*R76 zZAgXqpfO?Qsq<2CdtM}?q$JQ^1N$pr%}{V`6~4;LfJe)Jc7_WL^E~E%oq$}>_1S9@ z%3X#0;YZBiM$8V6YN_(wal+geIyakl_yXZ6K8n?azeE%mW6aW|$w+=KtP3O!pI(U8 zdO|M(LY71DHN&iV0)pW2A`8zT4nD&PU34QGLjsO^OExD~LD%_FMPocSu0@^eI z!u{X9@;~|DKfrzx`j_B;viQ%lR^IPB|2ee&pMMQ@_9CPGf0LWApQHRwgZ|G9U7Y-* zqmHU0UcuxFVQBH53@{t&r3?#P-g>6!>kb+pKYy?B`@XS=rxw0S95_q@Z&VGrN2G|eek|tMv9VSMhk&6_u3QvxDmaQ4Z4+ukB~?-#2IAa6BZum2J;<2 zZ11~lq#cZLg4h2}9~WD?BFyT%PdU#AKsyS?&zR@Ef&co<3pgPiCy9=ciZ^ z7j#XRXovzEb`@uOK@AH!?imE#MBeR;h1~7`$LF@l^OcbhY1j3)nx1-Q|1&$|4!4MZ zw}bWHQ@NfQw70icSNX@=?DxZ_-;rlW)DY-j#gMj%wjN;v-*0k3VQ3=W|JCS=zz0G9 zQ~j+_hc$2_SP;_G%SCshF_^`JE`0^grIkkX?O25)YhwD$6Wl4_#uSph!5hDw=%`gL z{A->5<-h)V?EZN8*ahV~W+JYzt31A179=oby562VO^Wl+R=JSIS^lSK(--Ms z3xWb?r*8r5#4o>5n3w&bKXZh4H2!JmsWUZxkvQCW5Pe8@HnBC2)52*t4Z|}-r$Lx) zPjqkqC=FAP`2O|nQY1b!81}w=UBq(+T%Mwl3<2G8gsz2NU%9Wn(+r@5E`~g$Iq+4m z;O-NWwq$-j46Sb*yc7nNinxed_8Pxo; z+0|8@R$8jG?g9sF8@dTYQZZNKB0y^7nQ|A&@Bg zXE9wz*n(Z}U`&n~nJJ=|q3AD3nqbR+^{^X(&Ir(**z%+uKgb(0!gN71GXm&(pNnXS zGPPy)NKgGQbP-3}2sQh9PFt+DIRkV@$H<6$Rb=Xl``EX(Z|&bG4kg(!#fPV$oVS;o zE4QyB(G~F2st(ZCe1^&v@b`X(@H$O3i#)*mLFcLQVE*o;?BatHIX(@ftkPdS5s&%S zqRe|4DEbQcs}zAd)i?Fh+gG(Vuvl+rwKmoW;POkhS-{_8ZwCvnqQLS-i64Z{)6QsB!!ny0+HP2$-dV*zNh`m zpPt-F9JN5&NG$v~x=06;U-bB=w8Y`$B{Xu!@aNaG4O}qhN@13K@X}`Jb8Uj8GG;pmt-iyx`JH#MC^FN>ISf{{9{4 z9*;WAp+#>F-lG1wl10ammYaRge8KZT+;04eu=gAL3y;CNkA??CXnP<`J$n8IDYWkrdT~}TBVKD zYv3b{&SvMfllL{aj&WKfnU0VY7$aW^ZKjmn^RzA8A35U;hTr6prfuRdQr*~R!DAHR zGY4dd7uq#pW~fn3*ya!{r3c9ZT^00t$ax4`(9_uM%ht!cNR01KW}xQi*K!e|{Qa0H zTn*cjQ0(zWn`Ym?qrzCY8Yet2?$-%xb}Lg!XynG8w|P@Pa6_TP%Q-tFDJn7cq4G>@ zWGcTz`~grHrz zaSUisGYUqWo1n{4{d8U^<|(I8W6W)*&e(%-f9@yL1?EAgme?d3#>1Jfs9?aMC*_6p z{q;W=OOpSYI+S9$Ar!%njyDNL8;bm^46s;KWah`iqr(z+BPe`~@BDo}-X4yZz+`H3 zov@t&wVVAI+&PhNyIoM`mePg(*}GT4`pWy4zdLT6Ptxnt5JLe8oB=fi*Qf@9Kpn2! zMh3Dwj8=Aw4!ZvI0+kFf=_G0D(C@D;JCCj+BQ}~$`E+jEY1V$+a|9m@77pQtB|=BG zdPh>Rgqz%4Dhx{olE4r5^0cU~VK0!|LFdC};qh$}tx|RPIJ!@w)O$#&tQE)*C>mM9cMeap@wSy!fQ>%~uf#J3R5aL;t`hwZ534O4}{d zJxh}Tr%aVzwS2SW{j0=;X7HclV?jT(e|{pV$FBQCt@-nPc_bqal4u+F!BxpbVM@Dn z*^9-qKH}G5w$>a~ZJsaLxedo1qhYZOV3gwDg+!=ObnG(vj=j!}*ptkLU*gQA*b9&a zL?InKoL(tDCr2GcioR03Jr0QmPFwv_e%2g4D4)%p9WnbnHh`e?f-@>r$g3|pk%fII z);oK4km%Db_QOA-z0gDWK*QFmuir&{l*`KRj;~x6!63#n==}4o(ida&8p`TF(={ES)1}6ag_Tmqx(*D${=Q;H-zVx;sl~|Xj#-JQxaw75b zV2*Xa4yxf za>e3uoo?lF=lFt$6dWZ)Q$$?a3^FA|>^R;|UM{-3yN0m6P9r^4UYuo4`POUv(#neZ zqY@!x+{7UTUZH7f6^P&-i?SeV+wZ&#UFi*#w`Dh;e+-jg>bY(Wa!DDM8VkN`aEHTi zzTp*{n1aRU<0uDX3*m_37i~^@pVf*xv~S@Q+~+ktXG_%mDM_)&%9&zCq3)V)-5gcH9V!6!cw+NtHZKTT z%4REFG+&~*qehdez=u~l#5r0h=p5?G5gEd9^r|NR%-@7n zU3bU>j9h4xx{?a$?$(}*ZTeavxb=(pPJ@_2b=f#$@+9p}$Qjht=Q(sId0mZ+)CrK`NON{lxY@?2dbyz&~qlKZ@1$*Nx<4Z*7&zB>dy9OUZ-}shPfq?+tT)Oko z0DMwi*JD9bQ*vH%EzjN(GZP@Ir}D#KjwY`U`&Ag2M56bUobC}`{0s7 zO*KAxaVfeoJM6NC5&@j9T61nR>2Ij|qCJTvUl2Wh_-McdjJ z3PnL;U88A7W& z`H7&XU{V4mjUJ}ec)Mq2j{Si;WPwB&KEF4N@~Kly0ai8BC+nJS*b-f$eeRr6-D^YE zzM)UEp^M2oIFvu{Ks1&$uu9B+hfS9X)>@MIT(C>$BNNIvndG4z7Q*w&Xf+})aQ^5_ zPNyh77%4|k&M_*2h~u$r#LM>tJ$`$)*Ehiq7lDZS3x>3bzaZE%&hCEJi z*dhb7ebT|LcYW04#KW0WIoSv?w?@J}G-D96nv926UijCvxt_x&&StQ@DijL!)hLdR zG;s53__U-j*$&V|>PR$k$^o9Yg4<=>jp2;89Hi`if<)>=NSmY_#JH*-Jl*1zk&fZAHpSpaR`3PY>ubo{7y-;$cs?q_GOOLh7e+(6) zkOyOjG^f>7dIzK~nrx|~!TY``fiM)9>4oKX)HzO<;c5hm&?NI-Grs{g=$2$S{bMno z)2>pX2^=$I2>%4-!{wZ?kh*7nktZYgjdg#WXK*n`mnJUpz$Ttr8F~y^*T07qV6#!ymcLft)^$JOTh7MsBgoL0}vkTke?DB(Kh* zAc!+Ye{c$3>SNz*q~1qLD0P4&8XeLpC*vS;`w;M3qOim$KMI7QK#SoU4fRqCG8m=u zLh@OsqHH4-w#v<4Xm9uu-`k4S41T7qe+HUe8kg#^Mr!t}o63?acI0B$+v%~4>4(0(6_u_g+C(@7|i!0SKs zDT{J(bEH69)g55qgZ~r48;c$S*p9CtwLuru5y;(XD)F0_Y*pP`S=?`--~f^<;&-5N zcr53i^`BbG%1orp*!>>w6ow{<;qUuuDUs|2TVvDu))Ot~#BfSQZ|A01O2_VZeCFvg zxwZgz6(R{$8z>YRnS1E+>_Twev-X$=R-V^Yq7G&rEojPdBY3Tt#j=pl%`qt7rk^?l zhQRa*!2qD8T&Qdz5_LHtmk)l3Yb9E*oJ+v-G2%q|BWB%No6sPF@aVRLpYXE~p0|ja}OVzZoisIkLdN$#rse zNEN(Kuz~y?W$@)5RpBd~%A zyKJJLa>knZoq3TxkhSJazwbWe@W-ppN~nq+!65~`?%t17pZC5Z)P-HJ5Lgm^AX?&Wj@n4+Qt! zINQTXa7LPOcnt{N1L3Pn_pF>Y&3;*n3HYeMe8Oi#lKkWhtW?f@rg((-J(Eum?B6dj zk(-vhCo)hf`ocr02T>)Cbp6!6wy0WFA=i9MRP%&Cm6|mch9D^lgB~2jMm$6q7$Cnf zohQh*TbmeVTZ4kE7&TB3c|8%@wix%s8&6_}(dLXcsylR0qD@u?zt5xnYzgPO02He3 zY@HU$x|A4~B-<7vio3!UYhCWCR)X}0FBmdu8G*XX;w9C=*mH#&jM>TqX{{vcGYl2Ngr^}tM)qz8K}!>ysPkcPKssnLqS z>^RhKnEUEHRe?=LGir!oOVlN`@E0yuc@h2o4-0c?x;IGaFtyQUIxb@j3>NF}@#oYw z6a@Yp{Y+eXtqA^W1iW=7^DU{^UYkWyB`QpmdP+=bTfX-xz%OJF#5DKyViV=L z@fro31#S91nTd#L!`^f^`TOA~hOuE?22 z$3}@StsFr1Ds)Ze>^w><{I}LbPPk8q#(hmA#hu?Zc=y-jd-jk98NRWpH3$}@ zdVOmMD*Kd~}vXXXO~8LE1Lh+d6SbW}Rm=^+Dg zoQ8#~NfL36!E=Gxyz;NZW9u7f8t)(kaLFnWWocs@|IG!!iLZBbo$iEA!W%CqfPo;k z5NZ%1ZLQ35JxuVJU6QhpqN9^!q*>orkmT74PIur;sehn(BG)LU*Vx|d=6HD)0=mCTg`WiiT|ufN@Xyt# z0K;8M$sIEekB3_VNQ2$GO=RzTv=Cmuf6D!DYlR*7rUM4kkyW-4$k_GgjL!J5TDiOw{oy>B}d`-b*7tt3YS_6DHg}m>MAi|@AJi6;EO#o zoc9dA*eahOjH2pDH5NIJ8h({!nv2hvijnal1MdaZY1!z`k-T2?DE00caE9kL-~DDv zpv6L7_j+Q_Xx{=z6bSdRG~17c5pW=@)q38(il1r5v?EdK#nYccg{*zcA@~+bZfx0V zA=ldccF~HNjSUIiZ__}elL|SY;3$|o-v|9jk3RVqA9E3D(K&6moYrBY(9YsUym;rg z!ViFK?_X!xD{qNA`Y46Q7E$9k1D_2w&B-hmNJl6CHU^cIOLV76u)N>!odu68H@-|? zUNsm=RcNaO$_{B&v&f~FegNbWGX%m$fg2fWGv~TfMnRKm%v2M^qIT?ibiNvbVNfF^ zQPmSg9lsP?lOH>_RUplX<cpEK56Ym~zrGI`? z`+3Z(s5fv47&%a+R4nn6GnyU7UyTv@aEa;kkg6gBF>QjH{x6d1Z`TFi7hBp0@~7Qm zlKqoV;0nN{mzkvALF5i>JHP|NQ5MiBWijY%d6@>w&1|mhu;9*59UA7$@IRP&^W_H? zOFh}g?241Ys82B6LY`(SW@<8GgH3E|0gYddVeURbARf@YoR05b=Nx_AY}?sM0NL`7 zt6!!+SKRb@g#6hXy%0v*s#*m0NrWJNJJ-&wvBZga#w5LNE!Y<%j(afm_72QX{{^9! zyBxL0^QuS;6=O@Gj@=@Gz;8=1izWhT8#$2-Wp*h!x7aoPYQuZ`fj#KdajIr_?;7)CGFD( zUZdrjPZJbUIJR${sw%o1zWKq!=`}?qZbGXu`gL?g?s3j8bW2t(ODf+WM!0D30j%`f z^zo4gX;F!@t3CqynO*vzYk#9lQl|jOIPwGUVXeGl6T6ARzMPm&3lQ67UU9ZX3lY=U z5C=E-ecu2R;5%EkcX8;2FPa3&l2si(zZn0Lyun^r-4C4O;GiEpy0W2uqeZ5R)?<1o z*fT_TD;uEZOGj{6m(WtC%(2Ux8{IMC0;ysSWWs}aC`X8T76_j^qhv}U7~C5UWnEe5 zxoznFrUJ^2aHhZMP%otz+#qNHSvHjui4-bBdPsMEp|@HPoUg2m4>LInB#?r9sf_ZC7@Ot66vC&J6zw#%&45o~ zV#mEtIN(CUR;KL@3o@3$0|_C9md8LhT@pOJoQCcqqO=Q{p8zq&4);Z|Ny;JY7Hg5~ zvx{_>{%WHwvRwMa&FWP$Ul0NPG(3{*RYzZSOBK1~S5R*5J`4M9hfl83cu(nr1T5zr zYN`t9JP`f#oOI@=>{~7xvDa&cY?V_jf9}p;H>un+?RcaF#TLH2_~I5GXnW@^uuBs2 z$>(%rX5W^#iLlm!rDm6Eo{cX(|IiiZ6{L&!!qt!ag|5r4ZOjc6q`xV&XXnqm`d0pJAj>ZFPS%9NG6PF$yjSXHPBNn8bu?eTL0;2FQ zEtJ!VKy`Wfy8+Y_=&==VP|HG$?pdwBDExbA)4yO!iq`0&Cm;rgYC$|QAxx^ws_aMI ztb!n{@qMUIHGKFU zy!mM7XGy@xG#I7%cME6)u#Yd;jq-igv6gmbEwIBE8YNaX%HSWy&4GH9lzPa9BnfPK zEASbvC^t7v(xHx6pI5UgJGsy__eTD`6d^WgMyYeH8Oq{)nJ)T~PaYX7Y;VTfb#EpY z;qN7SGT0fZM_I5CccPXM46ty-Om~_oRV0^-mbtHs$P)-*kIJ&^v{r$y>ceJ~!qj>z_yoGDYQU=RFIr`qSj!d^BQW0Tb! z74gR}dAam{4BBif231SV4omZAcfR9`KAyup-iY2)rQ3_p#?a$h z47U;QWg^mTgjQ&?Veae7BaJfj(6}ut8C54vrS1Yzmqr$+N1}%rFdE&V!gfREUZN=I zU_$1mu4W#(KZuVI7HruFD?W0TzY z_hMMA--&%!@dtz(y1|w^TzEQ{X$sKty9gwOA@KK%)T(YDftg&c6-LaSsxlIQ*xDRr zTdK&bf#HY1Z3_U})B#1f{>{l~Bi^cg6OV$U*)-&i>Py;2Ah)KqQ;3P)>J5F}Jcmdm z+GiVH@dOl)Ul0bfRL4y~?NgjdbRf0g!g{b}tB3Q;W^XHZ4-uel-4W6aEAt)}KB`5& zdV-Hs9R4imsH{wT=;A({iH$s+wV=@U$O;OeobQgkZZ^zmgr9EF_5t5M;z$rTBp%#) zEaF|L??z9{zwI8EP@itar-~ycPv#?Id!~l)b12^+KRD=Z!>+95%cZ?(uYt}2UTkL) zRt)msTc5FDc+Q<~OxQ=oUR9P?nS~sfhENR0&=0kZAmkf}Z3P7KH1SE81u* z_pm1%)T!#{DKc@!KCOpWXjd&kM>O0NwRHcUW2>@J7W@bG)SG~3qOubgn!vi}nUGDn z!m=^^+r1{QnBcEpLQIj>VqO5*yA7@wBsZ_5MDj`@x~W?edNGOOtg+jdxVhM|vdt}E zGe5H7Nq!SY(wz(e89!zW-sf~5sTi$CxK6*67P{dX&}ir^0Z6lT?Oihomc5bil?6e) zE=0RB#Edl(*H}u;Un?+_`+4yLZ|IIw`+`QX{(yt(6iUi`eJ@&bAXMrVhz7~m&o zIr$FOizOx{rQ)cs^{^d$KoNRSFy1^N=|}?5rX|!~2!Lwk{c=L(&-P>Oha7U*Dnl^+ zXeWd~4yr&W1Z)_oo&~|kgfnwH8*^Ylbd){&5Qa z;(A0+;x0gP3k!wp%c8m8*ixBaEa8Xp*l*}nq?B-ak!3D6w+ShZ@xnucVt$4kRrG*s z)XW2f2#$?*%pq%hTbi2p_`Z#f(W!s@r?r-@2$f3Q}HC)UT6Uz*8l(tzK_22Fk^nfAU~mmv-JSXMZ6c4xD4KnI046+D$JtHxqh zD5GSqw${x+$RG`5#@jjx7S-^mUM}KE+S{>>P%%JM+~0ot+CsMr%!9pbUkdS^SJ}tV zzqpw)YMP!&^h+sjR%O-B|89iVh79LOAZz`r+xpG=PPKX^iEuzz7>6unde;56L45n~ zr(0|+fJx$*wYbDMhY9{#Q2S1TE|~sNBP#gF*ajiNd_a04^oCs(;`25|h^@v$eXEys zDhvg+&)ur)YW0B=Ms2N{+XQjUm_V$P9{SVM6T|F7StSl4lKl)Meb?x_ytyRb8wUC>HOw$n1v;0eL z{jN7K+XfUt(1%YX{kP{fuOtaa7ewae_(7gzxJvlXbcCb?;a>|b(q zhI$An<$T+#3<&X3ItF2m@GDEjsN;oawEa|7_^I7UuLPAya1B5)Oa0dIaF4{`VO8_8 z8T^DRCbpis^upQ2o)Em%lDF0#Vn>&(zth8m>|O1~i@_>v`}1n{cEt1)(YKQ$?y#ts z9S7M6VtcntJ2laeXb_LMn|`Oc#!|#kiWQLEd17J$NH3tEjvm4zms)?QHaEtg-3&2@ z0>DwYw{V9GlZpvLp{J{Da4Ubpk3*s~gC?%#yk9wgN5&xLLu!mKHnV?D7V_pul&g!B ziRoK;5{bETZTlt!AJy*<0HbvwctD4aC7J#{ei+nUF()~CL9H?n3Cyo5(^~CT(m^qW z>fY*m)y>sXJ@&Yk;H~bK50E5A&+qE>(m1Fl!mtkou!3nyIJh=~?02r)hmWlheXfJF zO!x=pD+WQ#kjWvN0Xd8AON4J;KE(%s?ENoYQe}me@YE9iYg0A5@$W$QJJq_kz9ziz zq*IS1G{C{CGl&lo+V7vdes$8gsT3Sav+7}S%PV0{>xZx$WFp&>d71B*a_^mjvx!q= zxkbQ0Jw*B3st7U&pIuQ0)$@e|8)W)jcK#;Xl??ng42J#y%IN1R#sf%T0xw=Wf#fHE zvz(D1U^qlOb>?PidaY3a0FFp*gyrN5{a^g%2^-!De;$aHDME6^F@ZJuYX4D9Mo2|vp&VLL%mIh z=1A`=$xlI}QFBbgfawNpb~LLZ{lRg3JU@mV^3=$W=r@FlMYyY`a71O?W}$~dv5G1% zFr?ElptHVzs===n6#Uz%Dhs%+fcN>kUGf&7!5T+85>PnQ2G?uk&EOZe`G^faT2`GX zPrC6wiSJtP605O=>;8ta9ZNDzRuhj@7XX@;hA-)SZ{RpD=i5(7q7ena*>XgmB;e@6 zM+ni%Ky^+s1;-X@>#JlZfRx>n-}ZK%)2{|(R8pqR1uMP6Q7lZVv9d)039uIadrXs( zJoqjBq~vsgcv~-NGmk7OKP-k3`1W)Ntu7^i6~$~G|Gi2tr^1iqleB$3M&QF9JRfG)kLUWV%TljOKTfOH5~rvsX7XS zcnxGO+g=WVWMTNb;Q2U1FNcB*3pLd}xf=gjF4uVOkM!4DCTA`fP>WU1@uBMA!8=T| z$CU`8bhWR7F8;6uzB*i$Fy6WwQreKp@6oIi0%tOiJXwbf)w_UCD<&AFiAXT>{zc|a zzsj(ks``6yV|B(h$uDr8N0K=w$V>I?kJAz0C+pPEWuBKRm}P;CX4hS;e;Lhh4_v~L z!Z6+54!4evl^aF04@XCE2@cX3aVl6+{jKs#Ul^MxkV}A+4eS?%et>h_0OOp152tFC z&f8+u*|TVc14TE4%T=Ff3_pd#QAI7tCpAG^AU+fIk%|Hu056zsFYAzZcj8FlXaFOG zzFIfTrw3IvHHlvBt|}6g7-5DERn6buuxN?a_SL6vV>-P0B3z&zhpUl#)aHE)0WT;d~%!miSsfAfB=Gs6J$E_^M@IF5nUD;#Nd1dk@fLP{rP z!f{)WJ7y?tYsxL#B5MNVxNzLh>#fb$yWqoJ>FM~zbcC095=4N3gA{7x4mGI` zC?sDbs(;y&v16v7OX3d31V%{o08N+W4m|tbIE{!~(%`!Hd{+o6&TY`=v`|W;3Ut@6 zehX4(92zH%(cAIg3ar_=54o7=gRx53zz59(S{Wo)l(PE@QafeQaCErk`@kF)EcBl@ z)#Ty2;ZS%{lp2-3;a?0cHXxv>2}W)@%rKk{(68)KIt*d>rnTnYtoS0&uw!uti9h#Ydq)G_8HBy1KX1WIh}yGin^FHGEQsN7KKC1L=?Tw~vIe zX%GfB?;j7TFv9uBLZcyV2i}xAich_v00zYM?yaPYVlpe^`E%ENYEvDs>_eMNb6;@p zRi;I$97U@q>rB5pZ3L0J*iLCy41ea->v&pH z#pWw3sdY}#h-G$6yacekh`e-VUVat!wG+aA0Ef{6v(h-<-XFTV6AMrqtTiYN@T}5Ab6|OXMN>16*`!<*l6f(6791pIg6;DetXY;45$v)die5~80vKQniG~#%g}ZQ|@$(OF;3{2~F>_fCfMUidqchKx zLb`aQea3Nm>*L<(!*l=Q8BC?m&B^?!DvT&mE2Xh&As+#N-=^RE{TcxVOLnspF((Kd zbVe%QUec7L7{)^&BN*B^u}Wvtj?jW0`@VU+WduECdCO@B3Fprn_&FN$&s#?z5m%W|(U3OrVcwJX1*Vv3LrFwNy~G!=ZNXbpI? zm6=csEf7E7y#bTlqT_i2=>L=Jx;@38xgS-3dWAonXx&npz*hPn^w!2M-W|hQz3l0t zoKku(xxvng@1+2-;6%>1fji#m>`WJQKC%dniP$#xhs;1)F@r|s2K|qtmwj+RE&-d& z`{jjJDmPm?NNkqd=)ztD8Z|#fr;N9mUcN6v&t3R6`hx z78N2U1L$`VcQ^?aG^qS@5lq%Wh|I=wFlJ&Z(UN?-5Z#fEX!+t^&s%gbpWp^<3+92)|zcwOdKK?piWIr!^Db27Y-1g=d zdA0r9=LYC6vIVBix=coQEGjh~3L1maqiYO2r`dBv`)NEaZ^$sM^je-d#ugb}IqHu^m2n|{(EknFeDhbBt>C7tXX0*rBJ(UY>+ANjI= zx&5>U1>Y-#!W;DBDiL8F3PvJIe6lc!;SCi#)?>I(5&K>!k{!j zTwFJMx4+3r-S&~aCk29iu!*W3GwE#MjXOTf!5|SH^kG;1O=PL5r;W&~AMmpnYY9+lm|Os`TL>GHF|#P8HGDPk$!*c z@Gwvlc*pd70Cr-`9+B&|=HlU#Tsa45zV+Eur0?E*q1@cuT$;?nHa?YZE;$Bs8O6b1 zABAC+>6e*C>=H3s<00SP&p8F#^q7RyH7fr(Ul!x{EIS4+Xs#K~MOkQPv{N zs*D&bt zE9}QvJB<>h)Px>&Di?U<4VktJaZZ*#r7<>^Z&hjVkQQrNxSMQ)Imj^@Tv`R5-6|WF z5r`|u7EFSO^*1HNIP}DdY5^Mu#W`O-mfzpOYhuv;1!265;DWsdB)RdTB!YkS5!-Ef zj*?o}O0nZ7l`HE|`Mx$Q?`NJX zZ^$mBSmXSuzb}G!&1Jr^gJC#f+8P>^8*xO-%=zlC3>uf;;WIwjS`}hXES8J@)#ylb zv2bZL&h&fp{q?PV-bsf(cSPN-y=cEkYDO%SaYMjD9j9G_%-2Z>r?2nVk345~F_8qS z$wR8#DOutnj6)<<_UwX#Curj_y~)w8^!#1SSVeMXCc6=bR+%(16HDXg=(p1kX+$N6mUae9|VDD zwd!u|8;EQK+zE-orD81R)I3qK=`xsc6)EzYRI_$w3$gL+yY_Cz4eR0P(^EH8FT3<7ql^Ad z3Ho+^?a7P8B^$R@Bh&_L7RBa8mi1 zOJ6qyJd`&SzlVxA`XwCtV_FzFUMcE&HOhOzCWL!J%&Yr&$};(wza_Y*9{ zcuC-s;UywdXRFOHLBaA9qF<~?-L(W4`(U5r=lKjLBQQLJebb;p^E|J+$iLy+B4T4yoF7;#z< zO`oBg<-g53XhiNOQtWnBv}y9(b1uO)Uq+7-qyiVnwx}H;y-j^dk`d}P}+U7`4xoj8^QaDVsQiHF$FCN_VL_F=#>%gLHC=qJf3Ir z<8QC7L<8>AWr)72cQTBLQfn^#ahjyiX5d+fTt|nofmJ7KmJMJO6w`!-Y_(*hgV*H6 znt_L$2^OqCf<||;A{W5A8bpabgoySQ#+WLSCLoD|(>*ZcF zhDJ}E!|3Xk{1WL`)3l`5YMQmC9y(ARJ(E(l=CQY2yq|8px+t77t1@K#I$(SmM)n%~ zPn4_T7D92pRx{g^zi(;nfpiyQS~@#j4Dz_6P;UZOpUyiPW=C>;jjzSn{m}xS1lx#$ zq+&O>NN&9r-mdf#-B< zA06X^S-~JbZekMb03wYM4+%Zw+c-J`^ItnRh|h zrBj#CMls6FeE#rp1j}eJ$#}yhlmbG+>|~Cfe_N%mK6PVY?C2%=U)#6 zJqIw;!E*kw3`31wPT;mxLpFT%QmtP2Sw;22600KWc2$rz?}flfJF#X^?fSnQB9!0` zCyUmX)v+6n8NkDH-r-f_&S@tSZLw}ijaUZCC?(GXdP4T|mBd&!BGlU;eRe(-;FdnL zx(FT~ROLn%^cQH${T^dbtZLM+X(r%-(x*`yfY-3HzQC#gQ(Y6vY2#)JJT6dgy;N$m2@gnhr11jK+{KIo%k79r^0lFMA7#l z$Kq=+IHKfrX@RY8cts*v(RY%Muzvfo|MMRG*LNR9aBqmJM~ucU)G4HqihGx<|KKbi zQ4lYntiYXZ*f5-Bv4!84)rX|4NB|9$D>+4!}W?6ub|HsvPyiZ|$n_x1haLnP?% z;x*?Gm*x;BsihQLaO8Cm7^>ZOdOvUiBdb#^^2(DsKVLiFuiIK%x1GS7<0r5efVY1a zgk`OK0rZ= zg)`e1Z=Kx_(*^%-9BKc^2*Sse=)3HH?0j12`N;@~h=^WCa$gZXefk70eUfRrRP>GE zV=wm=>!0FM6r6^ipDnGS;nVwF_xlpqg|*PXpNxILp22{os#V&#`f1sI*Tx^GLHjlD zCpC|$qW>3L?;KrO(0z+`Cmq|i)3H0YZR5nYZJf9}wr#s(+g8W!*zffB-W~7z-Fwep zIcH?-y=qt0u3EF^T=V(of5L6829irzq(5xr|Jexcc^mKfBk*4GIneW#^7*$-Y}AwZ z^P=aSGm(6E`z^!Y`HF>*qRj>Q+kzGQ$2HRDHFMOz{%!*)EjxEX%6t0qa{m8>EAZ5d z6mOdL{QUf%hX}H~covXIHvK2#`%hq?ShqhOTJQ-74xE!SGvfmMAErNW>giM}7PJ2o zX~y$kE}1m+tKG+P69bi%{bN=RgO=e!TX}Y!Tlrb)4xY|J&0w%TN=$f40^r& z-#$|X33!D6$84ZX6l17r4>e8Gq>tmuIIN6_HJw4s(QePQ96h^njeoK|O%63pXX8du zQ8V6CTE=@)A;`S_V?vT8-olu!jwg_IN-n%U;Ic=Bd3odUOHl^&@Hyit1{{Uci^7 zk|FZ)Zc{}o7e)!oEzer3krN|uf5QN;df9O5Rww-Xh9c5-piDc)bDE{d+LDoCe{wIxhC8@ z2w|u`LZd`=k{f0sEY+Rzq!8sQmg0$skl%7v(l-+D6kHzxJ1rMCeDa8aZYV~TW{!Pu z?D^5x9B3*bYOmliO?MWK67_dOnU6lt7|?5i4Bw27{9)f6)zq;U$~fmf&;i5ma# zy^%aJQB^qq`}*Q;qVW7<+4%C&Psm0&G@f}&4q05YNV-^PZr8hJ@d~vfTef&^5O+|@ z#~O_PU$htX43Wq2&UaC8h5viK_C04Qc>~Aar%VF!vuLC5bN7F zkmy6b)DrSk^g?m!Y+$&2b!3v;s!6y^HJ@dam|hPzL4`Xktfq-62{uVObWRk!!Nr{H znJJ-4Wm?+<9L+BvzIc{+7Q9lwgTBnxMox%TmQ7A4%lF1)! z1ic=)t7O!60$u^~DRL7viDk8Nq^co05(l1EAyH|JwqhgPu^HCsYdp$kRVtS9%^F&6 zw{a0>1X4M%dDn$>S+O8Gxdk0O-xirWbGeeUKTmfJ+yEPZrwPK--Kk^0wIt?iwGPa0syg` zM-ZW6b-ZkTXjumH;=5(+=b*nuJZpubTo{(TkSgosVF{QACcB;5MeDT{vr_}zMJ zeBE>LSD~9Erk;vi+;kji_?wLzi$z+WB`}cB%!`H8s26G&ucf@mgn6vu^0p%NL z;k%LK-FYUm2Mz+1=>~|6UzVro#izK6aT%uvPkLiDGZ zf`>y@ymKxH@^A+(PU<;2xX?~b$q&wcG;8XlqTN<>>^(USPJ4d&w;dns?M0KuYXRK)Xn>?+!@S!n=h>R3C&FtE=bqn)N|tgen~ilMJ-=wSr$<^gUOJHcJy{O@-vM(Kz12FErAHgt@UpeXA6J?Q>Lv3uFB zNsTG$=%;orUm7t?XfTD;GB~!EuerH_;{EyxaQ7~F{K!E8;&~VBkHeKokc2$V#`%%^ zfwm*OTF>U|z=53JXU27sCC z=S#)A8Z)b6p0{|kjy1F+Z8O$5xOikk7KM_D{s#Hj$-^FY@ZjxDIy}-NC>sOV z7ty8aVHvw7Z_W*FIeFIa?s}+9Jg%Kiwyzl1b**IaGTIP!b03)7c|4`I^?P`BGpd^p z#rZ;=0Rg@pCC52hXetP%5;_1|YmLfDr?b8r{Xg$lYM`A6KT9m4O zjSklNZ0}k=>qOOtkzO`++4c2!14{kyK=u%ns&(D(R7FjtsW}#XKdZ{I<11mJ;<#Mm z3g^PqfrI$EkAO6saSL`hP)hG_P{|O->49$#n&;=~*z0dO5lF@!T$t;?TY%}2N8y#* z(N;uX>#N`S&4G&!-DFKPF5Ohzz>;vCPRe(0@UzPl#vnvJnWKqXG?hnY=mchC6%2XXqOzVtwfbB=~v#~w6m8YwVzE>+r@~~a& zNps!q!}Tv8>i+)Op`cWQb+nTG7d&X#TY&RZ0_c+Wt3jz+n?#<3!#Z&Jn!3n3!|o{u z9_CUL=!XMq0e(-a=haidG|-#q>K?|kmBDQ2G<<4s>TeWw1uowj^6en=}hW^B_h;Y;)k1U zVJ)Rnu%vXUO`jhmUG=}oTEB>?7-U&*7v!d5H+-?L!$VX#z(|h>S*tB2hq1iMppz@Z zTOy!|Z&wcgQ%5N;j**8F?}K1 z9o7Mkd70$Wg#}W!#!wX~##}YjY||8V!1r;^x3^c8c2+Jz)djnVIbaK7^Y-VsaU3I# zUju@=H5+3vx$!E(VZhIvWy^bt;Hk5l#9!3awSEp0C#yI|Wbe|%Q*K&m2EBFn-+g5k zKqWoe45zGe5op+G#R&@DFgxs=sW1!|2VzKtdqg_y6f0y;LsLu&Ps9wknn6i<;mHV2 znY9rFuA7dxsaGoU`bQ9FjvvI9xg+S;Dpc z7tnsLyO04vBhOUrgyX4qXv6mYCSHit{1-B#2UG*C)qR_(CoSM@=i3;2Bh(-Ek^BJY zcxy)1AAJSb2Kww2v|SR;C@&$LL_R!=xa@o1!Nt=HRS#YTUK2^l^yEyG6Ys#bBnCJq z!l8SFTYGad3fBk7m-EYSd&2+yNcqXiS0}UXuOL*$>{d))K^+R$UCYDSBk(HO zAI}w;X0lvJsxpb1$YaUrq)+RpD$I#an>4qg3!h-SyRgRg%GRlcuEGxgXUvp8N2tD5 zYLl~$C_gfaAU#jWT9m|3u1pzhh^C)KSz2VQ1AE;D84s~)xv1)rG>KYn0l{43v-ln9 zY<4&WdipbQ`m-@g_fY}?vObC%{2H^xp2|i)E@dF(IJF6M%ho0<;bAKkt5sjfurKQ$ ziEywZ(yp>;EbKT8TPs{h`Xk$-k;-LXv^cn_%IR- zu*vNWUwOb|7=vwc>@P0NrM=#2x+(VKq~cQl$;fzErZW~#O>65PeqoEWeq0ft9Eyq+ zJQPvgSh!m2$V6t7)>ue6CDX_qk4JbZw_*7c_r3ya*l=Gul1lrhGo&O~P>W(^S?2@; z8-!&5mT+EiOpb-D6ny1H{4kw!73O%e>a=K%}I||&K`;b$oF`G{hcG%NE-n7A%ZVRkKCt@6*OcsC&%;Jsi!L^gYxjUH3D6d7lC`Do^g5 zv(DH^L#J_}n@54P4=rFW)ntD2N+t>H8go02NNdZF99=DpjgVQp#3-805M9cF9w^vg z*~4D}POO3y`-6*%)U7dZ(kmrbJPVFtOK)6Ub1o*{W+kUrH?hFW*x;SiC z%s>NKT!tu4n_x{XCMmu|L_z}lj%cH`GGrsgmh}Q$O!ND@0k#nrJ#uD76gL;02rx|J zq-jwm-R?&c&gT+qKY3#7bG7ND7D;43O_ooBUXCo&(ypl^e_}Y6zw*zHD{OfkxV;I2 zqaN9>vXBZmdwDXFrBqXrgWHERbxQvBq#r=!){w8j&rfmA#pNeTNrR05*OZ9L%}{2i z-(e#!g1Xbl6Ebq_3fDB3R50%btsGfy1&A>*%TYcg&)pX@5ya&BCddwS$ov*bTV96P z_3cu7TP1$*sagX0j%CFfGnpaIzig|lnmkLuhKMx=)12ZVfEPC_mK_JxoF^O zfbCuwp+xp*?NGLJLmqxdu>z&#j%f;*6Bqn9CW`Mg$H}1#?pF*ky7s7-jE%~{sJHVgr9(G^SU$_nq|7`qRalM8oxc^I` z&g{6xnW;Ee*GQV<{~&WNAFWjr`-6J$UK;y?M^?W6ThIKEBN>YnsSGP^IrFBsr}lr| zd>Bf|j$eO;xdZiQSvPV*zM-V5$Sz2iM`}M&^t`RQCj_glWpS9<^ULGTSUig7Ryx*gh5a_V;hk{hxzV6G7@RiKd|v0jc>T>+Yy;uwi}O%3#Vjgfov9e zr?#j?-UuCK32gT;b?#`L?NOD@(BHWyn`1UBcQbISjQpPm29-@@d!)N;jhAJ(ibLm@ zl<+=cswE0U8z(W-7W)cgikq(AF^dnB>(*9m;YQWVwDyG&Woev~6HIA@kezzzq~%Wi zIF+|HPrYeTk!08%6zf1Py&Zw53$yD5LeQ7023n%Ss*0y5(hV`29HVQLX0Ie9VJ!7@ zWaGkp$6#hA=qG=9h#i^mn6)b+_i##Gb5^W#bqL6-A}_euOpzLj_XlW%WQHwDN@F;h z=Y`?U78;jgcCnOuLMfLmhNN3;o9N54BlDYKBnU;MEzU-)fU@>R>+}n)fu^gTe&ITj znUq=Xim7^omSyf|^_GI`Fm?i$C^RSZ+CZ@#K7)_9oWBwVpB=x-+1VQ8*KZ>J)_zqO zd(Y_+t(rA!gV*gmXdv=Sv48W8EYCMu(Bax@)l)$#@=5~k={d+mfbeH3DoW@*o@}x_ zZAjCdm`$9|DOug1a{eYzj+Ngq+yy>FA!*kV)>qt)WVJ zfB8dB3vx{QcM|n*LB{}*qQ-ZbsI(XN-2aOUU^U)5 zW^0E($_3iapxpLr+1UPu)z0UNKbpxeig*O6gSaNiZ~F0L<}p#<36VE-`zudxZFN{Zec9{CBLVR zmKm3K(^J0+d5WEHOKixxUY5Xv19(2_{>zjxkab3Z5SQ|G_N}5V(~?bP zAa`zjsI&c&{B&RA{|*ABq7S?}Gqu)`b#!z9*48RE)isd^&wm%L3WDzkyZ0G}|K9BX znLSKj;U?s7rVi6z*PD767=s6xncAPfoqIUzql1#(eFs^_iP!Cly+40M(Sd_Um}C-} z2360HN6qi}z{zJj1MQXWb<#gBAe80T>vofA9dEtjgr{9M$UHPEI2egnn$SKnbQPn{ zy@cj1ZzVOud#C+W^}Mn&;^M=swS^9r*vw87K9lGoDyB)TuDzXhiQ^H<6$zADbG0yt z>+2nv@11AM{Ob67Qj!BZ&n7T27=m2#3c@8^#pviKqMRJ%D=%X+1OzUgSjO5`4Cvtm zf2Ft$S3~eWc%chN5WOEu>`@6kkA`>TBJbI_YfZ>5WDx+Xo`V8{G}j0oiL1}z+eo_R z7BYb#-Q}O>ebBWtK-d0R^n^zyX>yF>lXajn_YlVt)-@L{5Wnh~f@P{jIFSK7ezz&Q-&>HNe$a^3kW0 z0y7GNxr5tpig5~QaLTKNvAWtG={RT#X?alBG0)!D@gB(a8jy7ZqCtc{Z9R5B=CbH( zmKH_GzrvNWziy183Ud-yutRNv(vJD3UyR=?@Y$d?3+H~5Rnsmf*DRFSz5QaWu*TPX zPcB4Vw1T0|L;QA@sJKqpM28oBmF$t49%`Uxy4-}b6%g-foB5NLzU?Y=q(4TcbW#XT zePynWUqNf7nfZlLE}F<>MB^(d8h7&OG+O9nGxH9EYMDCqmniLyd4}6uw0vxKa+Z8z zutSR#*Ox)i-L7SL1@dNPGxRsDj}egSTQU)(!`Y@HZs_lAm9XgxytYf75TpJZiMZe1kQJ@sWm5e zuNiV(*a-*QA#;(xo_Qh%tz!MDU&n!##R9jRL+;;5AsQzGQ(X?<2F`cWnOy}W(ik~Af=wRqLPiENh#wTZI z{O2V@5D=~V>8@iTQ7REv=qqRv%G3v zAdqHM#lLmmWwkVmyIo@W1G~2s8P=WR->S#?Gr@88)jLWFu;;dXBZ&c_r7xIh{KhEX zxM*t2MZ;DdXvFuGi=N5!>=Z<|^e1$pyt`_s_x$ai^9{E^{U_lG*sz&|%n zsteq0BhM9%2e%ZWT9cBjX0^lDT&;C@d9j{ zQvfkpqui-JL=~ixYOe)5D@C&TIKa-;{5PxNPU=PIg9Yh8ms z@9LaKJ3S^GbkunMcB+?KE7=m}(ZJj3J;Ty%uo^RXer+u~VD^kZxZ{#V0PR(0oe%EO z@6j`^ZYA4p5{bWoXT)dp`7)7O5gCZ4hgDp2Rd#Z5&M?6MoZJL=^btu=SzcbP)?^^1 zW{5P}e|+Amrw&Tp_FAbfw!X3mD zGO~<*94TATqJ^afE;`11`Y6z0A)_<$h06~<2p-{&f>(cWTtK*$}$PU*y0{srcdT!^*>RP%OFwJ54 zY9b++-HzLDW6!cBFrg1Q21LAihea=Mu9=3nYsoqd_wfyJb>};%As=?Gpv}Y* zEb*kAY6(FgYjY8$buh*pzQ0&%PmHfN7@4?=@@XkIz%ngv=g>0*N2{9?XdGR+! z_jk3ISx13;Hr{nQTYV3|F7|ZstEVIP`j!m;q)b96fyjY57m-Z|lTK2Ui6Ao9)XF-V-n+mhtH z7;wI33{VczX{n_{>u0iXLA8>L``s<;l(pN$lldho4?(NJI0%Fwx^J553pY(%zKehT z;7L`oCL7Hb`DBS*H4VD3H0`Fm24hg1vHGctRa|w&Lu`%h3_?2nhLAp=czoWkk`<%f z7&*3Pex^2eZ`jGl1zAO(tHX5de0?ThIPuJmCjYL%R8@_^bHmqN7*UR-r8x@yh78Mo zw|l;)6|gSX`CAfWfIvH^C%itE*$z$~AJvuB#I@=;LF5$(M{SKQGW1Dzefx$;6d+y1 z{bG7JZ{b1Y7G9w$G)reAU})Y3-#OeQ;e7gs7X``V1GEIN>Uac>pVB$pK)6x)eak~- z5HZoG*c==6sNeOQvQQM#5YridNHO^)x?3F(|gDmxG zSes6G{aEVa!lLv`D!QL&%*a~h#oxZ|k5e-fhzuv3diZ7R7Jb_KG@UW`Ht}s~p#Q>K zsF)ogC9t{+H}cKl%09wdqm4! z@Q7k^Fkhh3mrS4ixR|kk97*;hpf4_*T@YE@8oru->w`x^EhliO?V9@QlLm&>>3!?` zp~?;k)y+lB`*jSm+1hxWL%u|0*m9n!NvL1&c&`WCjO{M(@zEA`p3aHMn%k``l88$a z4da-v98{Xtc z?JXcH1_RR!_P2NU+j)4YwztbnR(ZFw59dx0SUEpF%Wn5jjuC0lFR{`OgE(WENg)m4m48JfTo_DSO&8eP02Li zO33^h4oP7l%z`L#J;r-?pj+Jo~m_=Dj zuHZbs;Mnnw{2-QEOL^hN-W>7U2S9?7_v71A-3_Zp`i*HS`u3cqi5ysut9e1cMmHfE z7FBC2>`z}-)Ow?RC_*<8iAB5>0z8=n$&RFmN<@3ecP4TIpjY93Vf+7M2xWPHG3n1!9?bd?{6A)o}?5x%0@GEMn<= zJbv03ldEg&al6&;o@V|{|4S(DS}o;|zt;)@I0zzb z1rr+euixzRG*#@&3TRGWtAC+KhXoUrWD?pn@apXB$(f($dVBj)gv>%HiV<+|7WD?l z2y8mFO9zkgV0aHfct#%y|3T{vPFpKomY#9+9L6tZ)&_S(2Pdu=OHDD0I(pGn6lHB6 zN*>=&O4uhFe@b-zt{l4SX@x5u4UZTnERHKS(Bj%3<)wC2V`24zavgt^lOTE%akRul zAtym|O^uP_l~paVQ7L7-!j=5<7XFtN_hVD2OnRtN7?6`A3mTO(mmB}+k&@PF8JtbV z9(q4Bq38<)?P562#eW7JfsL=ZTBB6)Z0k>!^zoW$^o!nCeQ@ttus@SJh{-SDI6%`T@} z;M)z5oU6rO3EWl3gu0{dxg;??zF{f07L)|3mXnUBWW42P>suh|`Gz5+NI_K)f@tHt zlT4riAIw%vSP>fg< zURe0jbP3=tSBl@X({PSP`KncOXbT?asDPFiHLWiT5>?r8r$~+6V?J4WXD8QWE zLayT8SjCO}{h|s!x=Gk@5uF26w1A_|pu<((ARKrf@G`{ooXgcx7aJzhl_1D+z?uT? zxb@0#>zrae(xMFWUhe|V{{stW7gfeW|;>K<%swEMny3oN{aQKfxuvRu^AhGrx{_%mA zq)lc9?;Nz_aS_IOX8_k#6U%^L*sDO6EEouZQB)lEVA%@n{5<$0D_2&WhrZ*>YxFgT za`RiF^BMts3M!|BTv;x)8f?rM@v*gXs zhcDX>RU5~R*RU5yO~q_~nl1gdj9x8GX5QT@tk@i2{0Tk%p7^Niu-6tX9w09@uTOdc zxTpO#J|E4f2N*6ST)fF-hRG>FY*{7fP6v&=W7inFIoo$;pu+`6mV+$)5dVh`HQf@k zz*8S*p7BzoOU6S4oLx=!&_*g-VS%@0NcH$SoX6)7aFyxPT2szmj(FTEmxy3G7ZkhI3?|tLlP;5e< zwaIBuv=S2$jHE#nDXsovdvvu>kXvh$wGG4oVwm>ubS}9D4S3RAt`ozpPUCj;dKKX; z2T!S+H{juVrP)GiX)yrJUHk1E$S5U_nF`|w?;N(YTnjocGtyM@my6n-naRSYRr>>m z9)>_yCez^zW_th8G2uOSF5JY;g(A zG`DJl19$AQ^D|^wvSkFGf5UI4;}MnHWAUt3I;DeU$dl)364QWb*y~6;Qc0~`Ffz|h z)THHxQBbKvUnmbxQOS96IGp$%kL`Ud-um45FQ}{9f5;o{?S?^M!t)s@3UGrK+WK0VhfJlGFp&OpZMj{~3bEf$0CHijgL46!v^T zxfF5hD1JP=DPWE;Q2|+PsCDarvJ;1gKmSD_B;PJ3#586TGR$s{aH^*`RTGpv2=_3u zNN;-z4M0F(R^lzeYYFzdlp=;|wil9W1h}xh=_SWYPbaDTLF5%rK2zX-7Ja*P@9~b# zr*t6aI6NG9*_~N7hXVNeiT|SlW;(X=Q^6i!)cNy2y`S_JYo;5Z>PVyr;QyoXP}f`< z5IFmF(kG8?PW*urvAp=l67nWRvT z&0UvsmGO-O3tx3bP1Fv)uW>CYgL8*Q3R@> znyG0-BQE~SFWl>TsDph$t#-8LdxpMB6VsE>n#k+s!V&v&b+rqVfKQMt{6#$NbKL)# z@f|g)>mWb3c7@(N#JP^=<`KM3Tb!wfCN|uEO$S8`M4k*p7S4>yIuNUyeS{x)?$*o_ zny9=4o~`p?NvzA{>!xBL^#R?ly%XtNsnP=& zN|0a0>Ka)$+J+rLWIGhl9o#@*eza}IFu=SFL_fpZyN*2b(eA#9v5z2z&en;R*!epB z=_5ghi5$8Yt*J?bpHjoMiT0fpguAv2upq*MID);PLxbK$Y?g^MuC;aaac40h5Rz;| zwAr)iKk(1V5A~ncJx3=x)A24Qg%xe>#x|44^(csSoM+FX@GH?j2syWv+-(@ckNpyB zVDF(--;MHN`B1d3m6#(OYGj_Tj#~%$V6cjLdGdAJ8e}H;|AFU6i3M_XigZz-yZ6!m z*ll7;soUuNthMu1o#JMksWcN&i|;oDGdB;3se0J-tVfP>}>t7qK*^X9`R&#KMc@sIV&aPTd>58 zqBAA%#sS8sc-=gp!B)m3cYDG>9Kt1_i*@T<;me(9E$^P(?#d=_;1qWwhF=ZTYQIfe zB{>**-VIA-oT)gH%K1_E!>7$Ukbmue!0Pk*qR@^_)j?mgcDSb8l11~F$S{|nj*`ux z&H&Ylm_VKVL){}#C(TsF^(C&fSt`5vfhKAD?XVHwA5r<1L4c>?CzsEA*TG)yRIPXZ zioQPHY#bkE&&y)Xz&{&A(3wGEgKr&o3o*wKeOO$}fbdr#BlSvzp5SSuffrpN5Y`{Q z)CWRgjP=o@fB=^l5RK7`o8YiT{LcCa${NtDh`%V8a~XBOlF!xi!%g4cb2GR}OG$r& zaB*GFsgdN68vb}4bll|QFGr`au6{Yn=ywBm({<&0C1mRJSEvgAQM`Do%y<#uG(Ai^ zNs^Rk8d$c#x53OGAU)nc>2m5tFkVSQK_Y~lppKxO4fHWZRkm>t zp1OWEM{NpxvSH40lih@~91+CaZ=$a}jC)=kJYY7(Z1K_d<(ZK2%5XC@N=HejR2c<; zZIel=;ny%HMyDjo58E4KLz<~e)D(&e2_nl_+#`M@$)Z|S^oQ927Qbscg&a{(vnTCg zEEfuU*?`uiFRm&tlpau(l0C0M$rtj_ifsNM{9Y--?slGz#u1 z$FnF2N<>iGo)San+g+|Qy1PLhl%Fp{ukF%*l| zI+iq~T24}NT^j;T)M51ERIT@y$>^G5t$9Ma;6YQ z#_T$?i3nmJg}mZ8$^>cQK6fVTSjsr@CZ;1F(&b`PZ&7W$5`XW|!np^x(hS!-aRQmZ z-%U4jxNa*#M2O7lO%C`(RhDy8Y|y$sviLoL_N9%wcdb2>Qi+LD zVo_p}Jlqs5qDA?NR~`!`4j<6C?6Op(evjGXMu+1>-+!IcF7k7NNRg6>?wviyJf46E zvK;ZM*c4L}OXk`R-N<7ptww~wb$(D#pVUFlq!}T zuk@O3Y@%B6kk9F)njvVY&#L0kAUbqKSdkI4B>meH`&j(pCgAL4Vu#1qE*7SNam>J+ zTBfBk+vZ~|7LsOmTCP>ngPM6zhuB8jru9Dv@CD9;`5z!qcDPM5x+9jC!VL)RC zi@+DzcR`56*);x@1*yVpcL>IkQi%?;m$melv}!pmeGTiLCsvbOIvX_ZPaV5K3quZe zZo44Udss=nwLIwp=0!cfMoDS7X**+3jlBGVGFWLf(g*E@48o!!Io*ya$<$BpXvPu9 zrF@z1j#EL?7-h{zHh;!Iu^l8D`wUZntRUqu1R=Gg5NLi>Ezq2kX_}eguD9CU*FoKJ! z-4Cc<>W#tGRd>g1yg~mtC8J-GqH0qk)IT>X&CVuQM5!^7k67iEp{Q>(ZfT655LSds z-y%}JJX;B0Qbr~N6R0v=FVonGcqrMU#54)vLzQP1bGlrpjaTzCKaJLFF28yd`E_Ly zGoe|;5HC7r4#`9ayg{W1BlYJpb-k2xS;&|8Fjn zNhOlxEG=IAFD^jniAsEeD2Y-ciJHl;3Q-2mEL5~G7-co_>Ww>Xg~1n} zRUMHyn#|x#E%q#Mq&mto3DFl6Q}MR_PJ!sdD?lvG0#cV173b5&&6pD<*n^CSZS3t? z1q41f@_FOKc|S|>9^@(>qNJgD3DAdBTL#-b*k^jVgZ~gvHNcNIk>9=$y%zndza3G?W_^gXd(@TINBu&E6 zt^|paZhra5f-1ZJvY*MneZ-!?TllA76$fg={*9E+d2@InC(|&O+bAn z6v9RuqERaf%U>wnZ2s`PyE!2A`Ew6_&G<3cvxD@pgJi*xq2NtIjDW9g7pC4Kjv!8E zBB~EHjTFfWV(8@Iod#U)izK+X{4&Gfw28AbBP4Z`i%u5ZtR@>~pl=bKZ>FT}CmQ=d z#Nu-^{cxmx)R%T^YF4G?J~BPhk-S(f8Yxb463f;|72|Auk3K<6VOBBe+9Fvd@8HCR zB-SA@$o30s%&KmJ>$TU79JUBS&2pvdjX7MIr#bJdIXA23IX6fCAD<16e#~PgNAE}O zevZwW=JcA+VAXy*-^U)N12^%k3MZBI-^ptmF_SDXYVAuW5e6c^xfKQ!{V~5ZM71<> z0xzHrO33^z8CfdDP}-KS&*QXQiS7!jYj&oV@6vP-;e~M~(S#p*N)*k9&+`ollxDD&v~jOXZP0v-t|gjJCH4#DDt1YgWcIjUj3t{GeI;kOO( z$KX{T4MDFJ-|s$P9frmv$sIew+={UMJnz(X01hGcx`#77Qgq3ef6m>}uOJj0erSGI z2mxstLn0gyLL8Z}IoE;dq85B2PFy@lfT+I}7tYShYnWF{G1%P*{iTBGEEROchx@1C8jJQKfPyUw? z`H&Dabo>C{+$$+E`SX+)%#d}^=uOOTtd#gIDqrf@yO{1}Y$OHfJumb#JeUBioE+fL z=iLf~hgT~TI>J$eFmiTxO{FV7$i3_9z?BV~V=fIO19JGtuT7-5MUm(At9=o%;DdBU zHK<7K#eOW};Qw+u|Bq=ouN=ru8Fg8ZDkTj0D8cUvJ|Hxk4pcZ^$epOep=DRlS`rz8 z(B~376PyVbRa8oRdV>$knV5`zK>$`Q+&-h;&Lb)aqVys z0{^CA(*9#>F;q?GTC-ICHC3_X?Kx ziU*CD0JZ<|BpgxVY`FFKzuUPFIfsBo&HprQe>|#cLCm3=-Muwo+H%n}FyZ~G8U25C zh=${`~t!X_ICiXH_lL#;Giq1IG7*{-2Nj!!{ho+-aNv{;w_m{UA9y z(ayi3ELpc)5xcv~eizFi1^3POp1iJ%Uqj;0dt(jNvD zv62hv-yLRv-ACBTa^LFxCs*HtGkEF)1>9>0+MLbPd>qGpK;L`4gIZae4KD*lfEW_xTiel{qW~;5}|f6hgj!p7#GhUS$SZ zE@VAF?Z@4KMEu|O5R*NIN`UshXF5Bcgps0q|2hZ!X>l8UepHIVFe0-*$wC?xz+vN7|qg!Sz z!uWf4ny62V8`8L%a^8=#Pa42-f<0E6&mn70uY&)J3T4l76!eY%r-4#TPmKDXo?T8c zl$w3N8G-kCfq#SOaV&VyPwqGul8{4l??Bb9ctfjSp+~ zzyJ5|C2eXfAoUnaIXK#-ynwP&a`}v#^n?d=D*iUSu8L5Bu4o-~!HS~M1vwsCFyJyd z+O-stxGSD*HX{DB^3 z@G5KCV;9xb2*F>#kwNe{y~1@zTg_wyP@P8}{(*V0?1$PmqH0?~6*Y@6h;>I4=s^?( znUTnZ3b!L{J_~*vRDT_PZdI{hyVP1eA}|s{M`i??$^Gg?H(89R@?Iueu4*I_{Qzny z$=j44?MzUx_%u+vL$Q0m7tl+~zs|euya?~?gAKUg3jdKiF;c)@4s_n%8w?lR>2`83 zw4_zl3pe6+@cnx2h;ot{a+Ws~wAO%}A{O$cHMXI7w5<)l`V8!Pmpe8S_$<-QX_jfm z>#ECToi%y{XSlrrs=P9>e(B2acp9AX?717v`1=L+-`nyscJ(K*s|Wl7;@(#*ahV|M z@nct~ofbK!=BRvXp-3dfbw^Yu0x0NjE1CD{9?(BnaJv0;3qoDw#pIP{c6}WhSqdAY zPIE)=IEo^zjfhJ~@KEj8_^@dkoe9;LnYLv}1HA3AaI!ZvVztM4BJ)l?4zS`6ZwgIE z;E`T;v=yPiEy55&JR+3sq<##0V779P0dT$KgSFX7;7H+fLiJx@9;SSmb&x|5zlljq zRtd`eX8&XEfM)8rADV~jzS(LNHz3v*!b#v+VPP= z&nJBF_TtBqwySP=rA%FI4CSoW$wl2LDxi8EEP5J zF9EYZm27aBs#tX?c7r1R0(o_@s?UB4L3a`hF5z-deVB8Q0*6scbqk$v#HPPWs>^=p7gV_~m_XIAB`BAUtF1Z!t| zc`;FMX+U~@z6bFC;p(lT+UnYH(ctb5!HYw1cP;K#oKlJv3GQyi3luHxP@uSLa4k-8 zcXur({r33J7<;b^xX2=FGLvcVW9D%^zstcxqIg!-AYHM0qyl6%UXO(u-I<3vVnMh< znC=5Ay_0Spwjajs^q{YeWqHJZDuEMJNPo#FH|AajFOX;>FK`WP;kKY6e>6qTi15!n zB0gcqXE<^(SkxQWFix97m|vEm78Tzn2sA*Wh6DEhhPnuTT$z*x&p}Fvgp7nxYKSK! zV{x9Kv=wvJ6=!oB8yeMV$lL#HCVhOfQCN{cW0!Ms5 zg$m&?r-l`yh+r(*?1-6H#~0eLvyA+P4I2cITCNX#rYQeY0<6}F1C5!G=n!DTQ*fv} zgd)54N0e*&KY@IJa3f~^jMy*~!O7AN7BxF&2};sR{8WR|$YD~*Uqlx-mmi&?DjPYR zwi2dkXhzu=8_Y{lU2{UWq6n8H*!05K4jDlMfq{!s4CL>H7-+Kysf%W?AFyG?x*Jpu zY_U32vCad45{IQQ?XPF^S7{k>dj6C*ayXV^agk*bk~kf4p+gQj-tb?Dqfk}&&4eW0 zfh4et*erIAzikVpECmMxM-17J?^6rzVbsZ5?{Fjg@{*&~9|fe;bi!Q$V%O=DzyGbT z(w}ZWrN5{i5teZ)Y|kC26~rd#zC{%LxR)!?1ybjcovkcjT90nfwFbRLU+EK+(P6jjNivJ znMZIE3h(+@{xIFvnQt`{f0r{saaX>U@P+O+-We}YHlXu!lJ7DhV`CTgdMf4r35|;& zP(+Z7)IIpL{mi)=LIuFTCI);?vN%fJyTY={fZB9KWKw8w6TG96FWYN;bdcKi4o^%+ z?{D^MiCakeG0TL5nMg@RrC3xzMtXFT+?q}WuEC9^Y#Lq}O6_{Fe1eM6Zx;K_JUI`w z2E@;irk>>3KX4QbYvd@RyrpnD$QAeo<9^)`$r)+%<)ctt)lAVeZ_nl(0EguRV9c5A zU3qBoNwVUWlj9#zjFM|t@mk#s%tT17tgLqKpDEk^ZObA%Z;IHbpw}kX4+x1iiXVzC%nNbzT8`Kjrtc2&dY-=Rwi z*e?pUrYQfO-F3g@Hre^`&lU;G`vb)~rLHiLaRPFQl!v|NXnM0J=3?|fGwW%)) z(pXpCI|A%up{nsu+LHrASnBm#EsUo4+W_YqR_Por;80E}`=M)GDgK>Sxlgmo&3)IK z-_z4Vmw&ZL+NL?u=l2APmd|8Kn_rTPsDhIz>)2MW%{ZArgnUT_Al|n3&lntP-)H#f z1k{^dWn{F3&iKoO#r*h2!v8R;`3K@=FP*-6et|$fK|LyX8SWgjI;^3K^^z^Z=Rwd7K{G?f`#w>;JJ}w%JnY%Opm#0WWOvLmP-H~g1 zrTutZS@y=BT*TQSTUgE%m`)DZNJgO<_BVe#5E}$d=h$ad8y4mJ6c58KB4Qc07lj^( z+w@_>%7Qr*qJ6c~ZVCHSpR$Sp@XT#h>K+C*d1!vV}AJ;Nr)JdZ5zpseUYEMosQBia{Rvdq9 zl)E(CV@2$g(s|V{d*O*tRB%RE8gbdIPggO<4ybnC-9r!;sT3!I^S{pqKHE6x*@Q4mgsh zr4)SqG%=^1vev^uB)MbIV7SEs2y%sMz>m0&j~Z%Fp5(cckUQ&0ZASh)btK=^_!_t< z!9sTPGI6w{{&GRkEQ3+G{NnZKnQSN<%5Ji?YD7}*;^I7T`mkl0yp75F4C=z9GET-u zbh-p%%mwMuW6tJ>p8Na41e6D516wMg=7~ZH5Pmuo>V;z}GI*yuik;fGtd{mz<87F?Ox;PAWNR#zvz-hiC%Dq*hn0zgUE~XigJe4mGQ#) zBr1M{U|+3(SvPyZpmt*bf^T45i>*sCO_VojmhO`-k&<^sSUj~EB)k3EUUJ#HGgjpoW|8mIl}vgK5geY2(N;#{ne=pA$>b4gSv; zaDnbUUe-W_K)hl?>MPS9A?+leX_%v40+C=Xp?o6l?1Ij#Ege=WsTB?HjdcyXT<$#wqMj1Ymyq z0OprBqb}Qy_p;G7YhJ}~c2D_H_Pz!)ea}Q6j`yb$k2}&YjZ`0X=5PYj2)khf$m(<3 z-313U=9JS~qf82rhn1X;Edx}Xd2}$UUudRBU%}Lnl6jK!%}v4>RXFz=L{7k>Ez(Ga z{{VuM!-wXivxv*w=3-1d0K16SWQdQ&5k06|S|IXmGGZXOI0p)`x&8Ka7a-QQdw77| z(Bz$U$U5B*-QjxowzvPeBx;Q$ur%gKRkcTY=(`K@7A)mLIq}bGCS#0-qXwtxO|NB8^)>gsE^Q%WRn`dSr33LGm%Nun>T_IItCzmJ8?}bE) zbT=>etCv+h^m?GfrP!NiVgRWra2CQ}4N_HL;9-Fqt(h)a7H~lg;~@pP`m^88>JvKM zOwA=1CIUT4N1sIXwDP1Sya)Yeq;d7DtBI=G@_FjV0EI@tJoWAw)Am11`3&{$YYc0Z zz-ooKILuQ#Dpp078Ubi=4%|cAQ9-wx2gcVPrQ8%@E@-D%;5G^4I>{F%HG7QtZf6j= z@aLU}crU2~0?|AyjGXo*L-oY!et)a@ zid}EBjdGEzIN5p>c@z%IQRqzaQ{H*|P^;b8_ zRynv=Juk;4GFojE8+yFs-?Tko6d6fnL9`lIv`j|}fn)~-5yuBx5(~U1?wx?q$wA{o zhsG2Q;skiR^qu}!T@1aM!IE>s)5VI#nuKw}c42eFK_|9xX!(2f36OB9HOZy5`+$RA%KaC z>@kOK4ho9*dbw=NBs5@nhh{PS5rS`baQhTU>M3Ae1o?IUqibrEBA08g%_Kt7FB_K7 zD&PV%jfb_9V~bLvz# zYqN#RVsP&qqo~jQ0Vg@7w15p@A5NI5;Md7YfcMIrUYJv7%VfOUS)gd=r|H89N0>2q z?&aE$dH8-?Joinb&hmz|jp>K+0>Z|KqVbK1POl&#f%gi0qDoI%!)Y zrpjC%2|aKnc`bg|rg#$c9ys{W79_aK(}Ry1wRVgw|RvIfJ2(>7aaWKRf;SnnSC(s9 z7|hzQ$hi1wIqU55L8v%bQZ2+>7?2}ZlLpB;rD}`|vh8)lKt~6_Ajy>=EhEYF0sA5` zDrb7S0q`xTAJPmB*cu|@K6bkYB{c6ij5Oq7c@rPd1Ni}xYvaaA7Uje@+Qe~artjih zRpq=Z_NKxrv3?&P{=yEV();G3eLy53!Y0OKIo_#10>}XXJR^l!wqd9Ml8Vw;tR39a zLEeaf)U!JGamBzPI7)w5;wZ#6UoXwopmOVL6hUHB(LYWs;KG@2bOjY~DpN#B&;Ddo zCNYq=38f!h)49YF-dJILknlCFZl%MD{%>kWc^(TZu5SKMf@!kSCYk(3-{48yh0n5abPsUhx|h0*Pcl|I|Ao(5gxDT+X@N{ z=BOIc+s}%)b699TR7lPl?^LNq7!sGl?07GPHGSuTuKc1F3%6wP_1H3lSve|qFitnj zwP@2LPL7oOXVQ9+p9IZ_4mpwsVu*v^R_x>a!oA0k$?+{M)0 z@15J}1;b?uEr5t|aIEfWRZ~)K7pU0q7f!j%d^G%(B@{rUqmS#Prk)*6i*RNdE+ z@a@8%U5Yxf|3S?t&!$ppToxmdo2->DE$^FJrW6 z`^j<3B&ZQuvmzO|Q^|2hOd~vP+L6vpNa`yi(3d_$g(qo~W{<6}pCms$zT1t+>@nQ4 z!CSCluwd>FPA-iR4Z%?vbW;q2B$u1cJIXPfqSGmDHv}>~@B6XT;gPy6&pHq>_5@*1 zsCTRuySJ&VUWOJIh!iPWWT-wTZ@wg-QflyL7D@&DeK{Q8ww_nf{lF zoS!?H+4azqtH8_5MEns?<;s>o7%Wum(57;#7!?daNTRcCf66$ZJvV70qe)|XI7L5~i5OvlR z{xO|mj)^2j)Bga6#>!pl)i*i#D{3q~cm5xghB}gw;@)ej^d|V3)$fBSAkhNza6@6Rsy|KkGCXOvu4rms*KdAm;+Yh(9?anIhN7P@J6CC;b>)!uCts+LWA?iL(x z>{3{aH%pYgx2ApW4ptJkbU+39DV`P%E{(IKDjqSfelg0Wl8CHAf;Z+k)I7A!^7w<* zgmn2M>yC*ML#tNI;3r*VWU=eYq!!PQ+>yr8Bw?h~PG;hUq-aiI_w~yhu(iIE4dV8p zQ^LmdU{U`Pz3l2Rikp%b^jtW5-c**TqRy&Qa+%V9ZR62d(zXKkj)hi8kVKOyJ=gc` z#(%eUiFO6w$a_M8UwTT$66eHS@%=3;!IM&0HaZg?y4K%fzkEHarQt}$;di^4#4FQ923tbM4f=`jyhif24Wf&p4aXbIU8m8#olb*&eDW|FSa zpQqKobpN~!+t2m-de@~CgNDK!6IW)+q@JgpuUI4#_9aU5k=unr~)!M8*cRk&&3X3Qvj-)0n?f z$toR32leNYjs1S|^)-sBau8sk9f=UUs^+crN(N)69#%6qskJ4m?3N{rtLJrzL{1!( z;?rUR>5h&uEEFNiPL-Qk(;SqvZ{fY?wFRE&4+SC!TBEz^QwrP){vgF70=OY)Zp?}_ zShxsUdGH6-;12u!D+r{~g4%!>tHNwJQ(w~P#Cx@gtNq1D_LxQ<^N8UX%4(o{sPW&i7s_ z5cdtm!{@pm&7ziCpUgQ4C*tAhPFyUxzJkn#>@2XYvXGrg}?g>DI5)zV= zSajE$uvqBLq&Cd){^H!qGjb1VDTHYw0MzVSFaBI4@u(d9u?C+YgLbJE)S~?h7QZ5g z;-|xLI8r`IEZU}*A!=1D$=F4AGtokLgj2EqTx!O5TuZ#3tOe!K@QCBiT~SaDkJ7A| zv09sK4>!4n7&^3kl5KGSEn)l^^tQg-%?^)Xy48y2^s!v+_eAA@z=d48LQz)pWI6{h zc9}X;>fzXIdXVd@;MU z+rkcyU^uiL)-gQDlKriZnQT|C{u9u*bhOJ;K%MuH7xJko#OTu_8Cu3!aF=tfm4$lp zWheRjy6=W9`FK&G-7t~Sy+;IfkugCTA#J#jp0FuJ+Es9Z!|?&Zg73{AxOy?y?){XJ z!whvEGG7gSud0gg)PBzhzJE3|)I^EGKT~0|n|>eUwH?wi?M@}DL?pSCKz zodm_K2-80lx8M%1YWh4Jum)C^!8(-lJmu*`FbDxq(iTesyp9dv30*vF*V zolumZYvwzt^#4h2ZHcn(k0W(hTC@3<6Mx<9gX*1urjW5Pc{G$D?)vSBPd7w2%u@!i zI4Rl*2?D47Z6FCfNHG;FL_2Q?v~AiJvA)da6&tHwYpwD?uQaYj4#h?d+v{@kyST)3 zbptFj1QBg5vJt)>C#PY3tcXaw(`kRcg2Rs%M253zl9)#y5PR^wXbB{1p8QD`!8&*` z;UV6WTaZs(n0m#PtKWMh(n>(&-4J;{*~|F7!2gC0 z9tvmqE;;=O(|Se2@XifW{q(pD=rbVb_34VOT?sBtymBg`>?(Noh{$^LfILamf#-SbzrPZElp+1*jtbGb% zub)Ghn+c52uB1K{`lU?XVL+0Yo40b9>s=vijilIss0Ea0_aMJ#AN1Q@OzbcUc*aJq z6g@8+`3)w7X*8AO^>Us6NEGUfG1S1mm6ab;UnIX9#3*fqCFx^#8;X>eEJ9pZB>|9J{@uWi^=C; zchb9Sj}j2hC&D}xQ>+!ANsw*x^}yQSIZNr5h+${HD)iTGaqo$V*ZHJ^Xyap*+S9C2 zTIPNe)=M(EgHJET?d1^v_GWE)&K9y!c%zsz17Q=_%b)LB_(>Wr=A1cG9LEe!3QISw zwNB}Hm0wz81=8F4F6&o7E4!Yzborwm9Xo3ug$jQLP_H+%PRM<@f=gc9!rcRjWKALXhc!;0|%CshmE&(0d^XSZcb$6| z&MW%^A^dH_V0Z1jlMJNq5nI^&6n|$z429gOsP+(H?T(L<-BJZs8Ui zmqOfOsLZ69h%{J7plqH}%rD5i1l|mOBzK6mc7fc0OC#@b(od2LlYzOvfcqA33&31P zdFwp%acvD_@jXA3968Xy=GHFK!(DY(Ec;75OrHze!GwX3mgIR7THtlh$@nN}-#NjK zbj1}dL$?Ey@#EcZZ!iq}%ur=NfwP-EPMY4LFh>cuwfP0=MKl*5+`==qK5Ap#kNJwD zIGYXhKz95z!~RMbQp)Vf(G&Bv`&EYX4zT$VefK4HO8oZ=!Q>fg0LXP5AOLe{{~qVA zG+wWB+PmL~Jjx$NReqh@GahEO8Q^KYd*jS#Y_bC2%C+5>Fp~0KMYlcrZ3?qlUk_dy znCEGi!R{U4B_*=02uam8wuHGwNcWT`We;uHbDW@^y~GGh@M<|GO>FBde; zYAa-O417CBUu}_n`&eWF*KE@yuBYCY=eCyeI!Km9NK9LB8`AGq13zcwnnw0uZOlc; z;)@bFU-MI!h0?J-3l z4fyG7RF?yU3!zXxkI6>r1o#30PLVS0HyE8Pq7w||oqlim_Z*%rd!pO9M)7DFjmu>G zhFs;U1RZo(bXB_2j}Yvgd?!E`=_CSWpEC}p(Z;S1*T@lu#g1L-_TLlc_c`hzC$8D2 zVvh=>6xd8sa}m~rnvqX1Kf3xN&gHQy1{ArZxt(CBK9J=u9Olj(nsX56&M?w8cr4i(W>Ogi(FB6i!m-F}p=D5l1DD?}2S4G$fP?GT77FD@{hq$Sw{{Mb&y>crq& zH6W=smJUJbX6Mai9a$qo|9z~jk*r&d{GmKp4e-#v5}vrE-VnCsUTM;_C8fn<6c|GF zwFzCh!iK+T9^~o&v<_9ti>{ zY$jQ<5P4pK68K;-KzC5_K{EhJ!@z^7CUfe%1zS-mnzL`oP~(%GXz6H@Jakm#J@E4Q zdGuEoK?K^yKDO8+Q0)CjC8-K?3}yr4=X6MAJGFM{num57{)02^x3OC7YF z001>|tt)m>UVQvyZ0tTWVyoUUE)^T;Mp$0Yg?tS;Tu63H>L$#Eq&2$wS8(@Z1mj3Z zN2~>Ovmx`2WIBs}9Z;ALFAmCeBRrke$VDt%HD+v1UHI$x*t2!a(nRjj&k2oc6Q6FX zg3>q#9MTTvI-}417q-ur$vssoW7LqoDK*iFJ%}K!9AnuZJNxoaG2aC`+s#9~h~8*T}D)Tn5(!4t&4PlWm|&hSC@&%L<#> zu_Z_AFlLwBRSlvouWW{8vfg>YYl~0hQz0hU5f|d`0w0>g|_% z5CY{_Mjh9dw3MOK8qva*!io~u4pIvWY*++%C?12*g^ggZdVke*jNMQAI1*-_RWiJS zzF%(@JO52wJ>LFy9zMMuwx)H7iZV3a$Z!^Jcf`?S->_stN)#H4=Kg{zPX z&>mWTmX=y!k(&(%$nWQxR(@_^5bG;~d%Wu~@XUeS7_B@dRHfj+1#(+PgFm9Bz_9e5 zo2r@u8%#)`neA_-$SszqnQ$RB+%S^8#_UUv)3Q6k-Ti~)=*r!?t}=Huh2ak^iQR4v zk(=ASZh%1Pq3h7KGl3&Be_;XU0_K{a)E)tJo0}7o&)n7G2v>MhHXIZ|kZK+ngb;*7WJTXZ5PlFhvK4H8nB%Q!&Im!kH7*sa7i z`_94AEXxo<5J3H9J&8@|*YQN9Not8mYI7&&uk5dIm1)xN4URA_r?5I&|9fUx%pFg~t>wm7*=d}ZY#)Amh@LdjOEw_yWAelxZI0QZ-sx-TwS<@Hi+FfnC9Z2DEE&Mc&w3F_;FGA0=`{BOE7^1fX&4n>7t347rtkUaw z%*Xl}LD!W71$0E3Wc);p>jS^OQ`|&T6|TIz3oY15IMc8ADrFKSOXO`8n0i60#lpU{ zBURITNp|JtX4!vW)gZHzyl>N!g%>zmN_~g~GMQDsHUN5?vmCS>V(97n*6{M<|6mc$ zGJ`??4_*V}HXu5aaeogqV2P#*R3p`KBod|&u*FJg-iu?Q%F|Hl#o9=0YBh3zr?_)_jV|1y}H_)?e9S6yfK{0WNVo=ah`I6MTfmqL6u7MS<=!G7&QE zdU*$loIm3B*NyAP#=o3m{SWZ+ut?o&`M=ztfXc>uBcp7Q#?^%8ccGplu%MgYL1y;o zJ6y_TA@c)Y>y=avLkJHfo!k(PD$q7w@EFS*(z|P_RdwDs0)yRd`zy_J&L^r5uy@m3 z_ywODNq=Xf!9;2TyAi%D`%LY!G81>Ui`K?fN;d(zJ>mgNE~`c2#L}Ss22vM7J1KGa z%RSkmKZzPH6$d(^n0>9ydOkk2i=>F`CYxJZ1SX8FgA`Lib=D;-jS{0s-?lfKGl71~ z7}jb(7%V-1A!4-OZ{dB3L*ZjZi`-37^Lc_&HWvLex`T98q>nyGFv4cTHA`5}1#U1} zV@w3*HiIp?HAYK?EN`L=9o`9$mdj#%^a87lALQQs9puOw?_CVX=t?mBS^yy1YbMBgcPy( zw0DPupnU=3x)^u8Uat|2a$KNF_KErltr!02`h5R%l29!c_+-l@7rYiSq2!^CEWm+o z$L-!vupEoF>}av5j)VxR`uIUW-3N0zwMhjQ+*fd6VrC$!?PG=fS?FK~6!DDwfQ$q$ zW!L$W?S^zDacVNW{K+A?r;bW9lxv7KhPz#lwW?L^sxMrVoXX@oKf_R9WQwLFbiIhS z#py7-;v(fTV22V%LL~qA^x!6Xt21*twYAoPd1i&glA|*pWuxF+xgonlK}#i1ru^wShz4S8vw_ zM93iHkd=R2`8DrsmVw!~Qhsc(aFEBSzgU zz3n932hWRLlMbko~xw4}2 z{8_lcEW;)Bq<<@AxgrJT7`Ay;0J(c=>Kon8$cVw07=gn2$b8$}?cL*<>D(L`YM)uh$@Tzf?CFaB;6K&GC_@7MtKqibzcR8HsdDcpBT_%aoWSm23<@*Z#?08|-(x4efbB)8>%j8@8Rg5Na z=;9uCWaL4iDraDCQ9*1q{pq`Ztj>AiIVN5_D$raJ6V5o4NIOz}H$3B>C;(D89iEPW z*1dC1|W#O0>$4CYblWT1mt!%9b8T0)Mmzw{#NdL3+h}FW==1JO8ItPrTqOP3b z(?N`CIGv*9{9w;$wVF*D7G7{uLkR){l-`%Ce|>XTAOHUlbWi^y=x+9US{S#W)g^%} zgL9o4&pE5IHHCX{UPuf~rN(mt{$L3zx^;MuCl3@6KfWs1R;gtqL9?iV2wL`&m%i@W z`5Y1wX(GiQG#S&wr3!!2ayH^MI(=#_fo38I6B83d=lA07P_+#rj^Ck@X?_9iWRRO0 z{jAC(%9Pt{e@xsl=N5MHi?s?I2eW!ww5Iu}!DD@9o^@?YqiL3gID~E9h2&_RXK_-s zlp=FdY4{F`7%8M`_Aq|uOXgUZq_ljccs@YEaeDQjyc^qJ^;oC-kaB*nOhc2QE{<2A zy=;M*MXp81XIjnBcp4B11z562=?(I>*=z_&)~E)d3|ukilg~VZ%45$IV#{GH>|e!i7iQC{W4p-WyMxE3cTAbgQ=f@) zeshq$bDA=|8)2ALeqgFG`MUd~m1%2!^ikgLGD7@?+HaS|v}K(;RltUUDdp7Xpre>) zV)EI5WA1i78i!mpj)nDR4DeW&>HWp=jPX5k)UhQ8F+WGgvBrXwb z6>IHbb$Zi(;qMTKB<4qaI&L>oM;l<>HlJla$_W26&q-66$%q!cR_@&sR`GjnH94ja zN19#6dA{^&#v_A-iW&Vmskj%e`nlT061NUH;jf@Mr4Neq z*RyNIp6#q!c`C2wP$&e}lADCtEnYO1eM&zi;}yiK^kF0=Lpw4EoAtLR(<rRZZ~5k~(+T>o9be}i zSM{6zDZth}<$iJ8fgHu9fx+4r`fM@Re=AXwW*nk|YeX8B=|(;=QzUIC58UGS<9gZN zMa()9G7>1MH+t2}G708sP|Hnehqb=)eXmV#q4~sB=*y#=?wzVw783zJa}Ys*z~SJi z49t!V3{5^VWiUYz?vhPUEgc+X{u^*HnWbJOa$}+ z913Bb?}gig4mDDt^m6cD4!UasTaO4H()iN#DlMkWLYZ=@f*E7o4Cri;%1CghCGa8F z+e79(Ly0RFg=SNBiOg@cDdnVrq(MDDQ56V;lUGXv73sAP3{7tIIj;lz^GN0DF5GV+XA`S!WhvM(b3_Mkz%6P73^Fg1+aEMgZ8>b7;oMg7A z5?aSmcau;Q3EPwF2DQ~dBYnoH!;~?aHoh)?s!L2GC#{_R@1Tm$L$J1j(S3+)W*gL! z5m=;O+~FtfoQ2Y#^1Qu!j(1DY-{YEAq;K9{t0C%8Eb^QuPF!sL#pPOzWPynwT7%0l z-@8p^TroSb27Z@+o}grQT!!gnUw1x#;{`uXj)^cD>PV0&zD!x@#47vf9dP^ z7`Pb}`I%vsy@>H!#`(6~`$1QcGfk#VhKZb9skhINzuz}|wyCy+_(v{HcAIm6b@6$- zMo#h&xT)lU@9+pA3e0ZrU0r=;Anrl9J&cx1O(%Km1oMViwIJ|x(H9>1&B9d7Qa_ab z|8W5<{Y&X`lr_pk3okD@$>X236~cxoM;*m~dZxQ^OaAQxMOZGxL_0=q23gAuu8Pnl zkuc9L^8hCY=iJ5Q{2lxy&gAC$dv*kh%*EuUtkYipvOUM1xWf%)?Fx`TSSrjNrVmpFgP!a!%>Dw(MDxm*&wpvo!qy5|_j3aKnhj8macl{j>o%k*5`-EW^O! zP+XGJ6t^{^K%8;5ykr`QD4gtx!($~x;v$9re|>gq2_-*LqfKw??d$lAK{(1NMqvE4 z@Z)6D8x^&=*n`hBt});<3HE#DReq#||sz zFWp+PLyx}PlrkS?N$e!;5rB2<`*Jy$U`fKjz<@M-z9vA=qZ4BO;TJ1WCvtpqLijtm zyYr?v6rDLUVtQ7hNEy!yDN>tFOfNPkHuCaf2oIZn71lRoENV8%oqM;@&E9F9(pHqw z+Knfg$O~|!CTY_^bpX{rRSMLmkmj4bh`UBMGN!UhSUK6RAK36r5i7Ac9>$B|h&tS6 z282d3*k1>!i)H(Ag6qbR_PSnD--7=MJ^Pm(yI!F}P7xQQ!C;%EdjmXV#GmV+)UYq$mRkPnhMMAIjuY&ye1HaiyBo5e0EZ4ihD~=p zER?;4oR4gdl+{aJgM_=)fQ(-dwk)z~5EWwtiEu7KU(@`p4olqrw!DCHR^Z@$T-kB; z2n}$?15#2JET68urrR|)!l=xc6Vsmnu&5~_sF0hEOTS=brJ&|$hq11h`g<@z(KG#H z{2uY?+MRp<^ZN^^vKh0%;MB}Zs2EXYA&*Q#CQ=&P;}1k%-H@D^nq+r{kpJX)V~K+Y zBcm9C*-zbv5J?kI2kJkP!1qqzAvY9ZHnnoROBlWF<`+tULwsoJ0>AFU-Sv09E_d}e zb>6bQJPe9=K67_Cu^p5nuKqYTee?tdQ#s7p8M~MXu7&vw)yzy&@dypcQWO@lygcT- z35q>zz`fi;b=O(fo*Cg0NIgtXmv`_6m+4QB-T))s zh~Eo5@)l?vu@Z`tWF5esWpo0!KgFSlRP}aD!M?LQ!1fv z$l;J^#OwOa>fHb1w%qyiWmnUmk7@WlzlJ1Vvin5wKk_N`ujgUAF!qUl^+E14qH(|^ za4GvE9%!XSm5qS<$st<>lj5F+RF)c)Fwdjj?drqf$F+*j>Bp#Cf;1zcp(SZBV-3(k zR@ac7+4mqGrcmHclq3BRaQ6xezeqX(iSW&i;Pw{Vxh~Ubru4hmyCBD$ru)qz9@L&S;V-xn(s&GfssQ+@(8wqslrWMK&mJOUA z%-K{;&MkH61BbP!k`Zm1M=;w$+Q4WUM!6uozDM--IKOfa8f={ZU8i?~Xd>G3t$fPT zA$u#mLV-W+Aoa%Zk2VXZ*jIomODR1J-z)g;QQ~Zy9*4mVxFth;xPdYB6d%w=6Hd8k zXtwuKLk98({ya7I{AFG22EW-XZ1S}P37P+0R%82L%IHYK_i0^W6qZ^MI;%9`5+)&0 zvKg@sW-tlAtNmkJ5vhjTkNq+~<)+dNCBnC?$W9BbHlQ#l+R=_XzXOMt6Hrf0N|(_6 zpZ=nu$)C)e{ICI&@Cjkxqg6ND*`MX@P9D{Dv?t7$SYqBx$jCH0@_*Mv)#M*drT;Ys z`r9>;*pupi?*x6XuU_wwspAZXumT>WMLaJ6=k3=M?~b7Ned>b7f?Pmz=GXsCExt=S zdE9#oU4ME1&1akcWd1gKVIaUA1C3A>bldd?fyS8F@nnwARH07oQ;07x?E5FS|Gh^l zew-iqv$E0$mG+bQLihSYS7L`>78e)0g`rQP=Vu`wwu$YBKIE-`U;uId6DaTvIy!qy z|L&S@L9oO{oJsIdL|!&2|57iV@)dz zbfAB*pZ(Z_gvZX^67be-|MxKGFG|4zI!#tg@0-GxvWb6W+E|Ys}(?5#Z2gsZat`IP67Wtv_Io1M0@{vmZc3w z9?bOLlmtAL{N}-Mad9azCTIoxg&tgi8O58>DEd9KkL=U4G2lPH z2qY{DUNxHl%P<4Y+(Sg=(cnBTrp4hhjY7_?cakZ33HapU_K>yKPHme= zZLnDxWX+H!`r|vBsGsoon8 zf2QaZ2AW$i?&FA1YJG3M^<2LHuP^p7QVoQvS|xz4Qw|Nk&z>T$kLvAYtTagSEDe7t z!>zw;NH4D9BTZ1AFr4@BEHR#dgmi=AcBxnybp9kI(mL5Mrl4$RQf^2uy!T(y5t4Mn zDX_Ck&_T;;4z^u%62)qy&O;YX`-}!g$yNMaD+>R3K%tR}(%OhPcS7~ub+MA-#RRFU zC_l>RAPRvF_b26gt{)&(#Vb4 z(2_dam(~HQ9P+;dGG^qOW`Zr`BbPBx9D=z{yDxi#I1Q+-Skqb&cRd1#y4qd~jyTxR z8toyCZ2HBRD&MFp5P!G_-i(>19?&Q(LH!wep(DC(`@JrY^-^Yz=<*Qe)~OU1Wt^pi z-uH#qm*`rQE&*TB^4~#E{ioo3i8=H%cckHO>>V^^SI1hv?0 zJq{Sxtb_vg`Wp6=%6CzG8kqNBru5srXtv*}Xyw@~p(OiyPCBwjrz6T(+$A=@x>_9Y zk*VqRU%dqD8>A6RNVBd{bgouB>-8DoeY6G3#xNeKFSlPxt#olQWLQV07wKGjTGM`s z+;3u!4tu1l;h4ehZYN%{qDms zv;jX}{=(qvyMAW*=+(&dI}JyvLaje&^$Pg3w9rWp6`|*3x$|155%Kqb#Dfh?Yk6|* zlOx;ehh%PD8M*ZFI!Lb=XXClJXuUdD#V}hKMneuXeeRA7uJ+sjZq2G93f9rhM#0v0Sn#-kqf;zP@|1oylUE6^h1Dy6tA7#pov;8XEWbtZu}$5zOPt@ zWSs|Lg)PWZL~f0IwLgWRYqXebv56$UH?ao(r@CkXqj1-KHM2#SsBd(-@*;TiCGk}3 zVe(Q$5WR!M+$GUaa+1foagFy;zd0|aDoJ&*3#?)fW)e{uBB$nDjG9#Ham5JuP;?gM z_P>R@FHi`@z3T|ewaahW|4s@niS>z!sH(v9Vc_8pbX1F7Yx()*RExCcB?f-(2Ky6< z?l@{wr&afn<)F_eifpP0#fks791AfJdkRD`%T*ZXoeC$^W{qabx1#)i+`VN~Tut}r*|<9d zhu{Q<;O-I}0>Rx~8+Q#Z!5tFZ-QC@-aR}~Cu<7T$PyX+{Yi7;oS<_!?t?oK?PSvT} zwR`Vh?Tx~W@x=N*T%e0cc|^cs+C3Yq_a#Ykn3Hf?p4cCG-Li)xHidb|c64{|u_vXD z?xF{1w@p>J4WpY1H^KD@^<|Qupii$1tNv8+%ETE_p~_j<7e=_T^^k$R+IK2wj<7Ra z4ZqdFj=yhz9@Dea$G{h5_%cp<@NG;?LtK0&0Mk-sva6+8ri;}`k2yey`H3(wI^{eGs9*ua@^XfVR-hEBBuu z2OW&y0n($D(Q2Y3*k+E#3j)lW&+nLA^l*8**yn@=oLDR!);!o7?dVpx?6ivD>7Ch( z%`v&({-d8AVzXYdRPqLpT3W1V`>Cn7k+?EnSNI3Hz@7sO>V7I1|I8TDH7XWQu7Hpy zZsqJ5?O?=0?97yr@ITLT1)!u(UjDWZO^{pm3dH{OvO!@3naXBM)L25*7dQi`_J!-n zUB1%70X_#HkN4Cp^ev*YWC|$S{ZPi;mIX{35{3z=;1u#ef#>9{LpWiWB_)2u8sHLs zU7>bLycl|&Jr5PgEE7r&<^Ca;kKyFjnpaLXYuL#m;`io^nuZ3v(ZPbOM zeat3-StMOcg!47E63+ZEe;=ooML2G+n2J~d6jbtcI1oPRtTWAhO!Q|fls=?Cw&Slp zVp=9e%yNj-*@lj>)OnZ$TFG=XS}TO~-#v8=GY}E2!UQzZv&a%5K8;n%g=B#rB_Qxa zL7~>e#VVw%I^1FHH=f0GV%WjqH;8d2ctE5|o|oWn9#Jge@oF5DYGJ>dtLJ_0eG*Jb z)zio$Fex$W^57t`N3BDnoY&1va{S#|4mcDsMM4O)kFyv~+TV|epq zM9}tQ0sLWarW3CKAN#5qe_nTcjFb0U1FAcIE*eI%8CZ2^(FlK_qSZcE&rlC9fX)E0 z{OVI0DkgE!NajU1sE8A{>?+5H`h&Nw`Pr3S$S3qJ1tA}~I?C}_#9o?3mr&Ks&hRW0 zrS3d`$VKLwyc)`Y3#?!njsI@!e`dMD2#@DZp5#8LdKLd`QBd|p!O53Hp7Zd#UfF&|tn?L$ z!sWwT??+;&@78&3&zd)EfkoC1SU45gXkAnk4g$~ugl2p_TXKH7KjK^~^mDRfM_o7M z78emb->?964g$_gf=2FzK>+G@@C8eu*^LHhx{)1{B%ae8gdHj&b4NW7ASE%l`^vUd zhXP%i_DKv+ zUKg6cQ??Aet4y2_5#1 zYO$0v)zV3AEgxd@YUz>&T;v|7vS=S2wo~pl_Er0?IB(xGS^0($Xx27(D~Sb^#yr?9 zAkBQhi0g4e9@2$F4KzdivnrW{Uo z(XJLYlX8zgWUAweWM*}<1stE~U^CA_CA*XJI>OA>R0(0qP4!^=OZjqpkL0t7mac~R zrdKhEHn#>SSmt9%!uO#o6LqT^bGHTn*-A{f|BCxB{m}meNZI)Y4kAq%L2!13!wS;D z=F;zYS{UrJHZt`5!mzpCaphdo%1y=6Kx-$ssW$!_pViHFD}@;xDEcVWf@uSr8CJHL zlLinzxFdgMRqcOJW@KrosiUQZonj|Q>~1K=-_B1@U=iL@7CSH))6t39gj>`8k!$`nvp;RIG2LU7rkguQ+O0*3qMXf$U@KcWatCH?gDB#&+H+k2kv5sit)> zo7`UBD91?p27MeY|LG7hw@B4_B)zk$(f)N`7AR)!Vem|GSN-`u-y)an11vp-UU(8X zp8X$D_!>uT2F{PunICRaNY9s-$`(8zO`x~U9B9PSTrfgdS^9h%*fKNbkmKLH2()Z5)??_!#6WY{gfQN zHU{>jkH?k0KbV*})AHM`pR^(ZN9uAY?1#okc zczFfPhqBrtN^>EExuUaVdyAQRm!+7aw)jBwRZGL39~im<8xqLvPWV#9=)`W%zfQyA z{;qNsmqD1=Xla+vsyFa^0nDnP30ON!z4Dcs>U!zs^tx?tl+;Wg84VRiz~X419FlGa zgt577d#8(?gj%3sEA>O1SB$V!ob8sy)!TT#2nXQ0Jd{IK9T8NMkVzjmsoZlPH-{O> zhX|(T^2B1`u*q2;MEnW6@CrLr9MUl=&e6~c5p0GP!zb%iCtn5&Cj?>F>67!*HZ?T} z_wQdWdN<>rYQ@#;VwQIw&m4+D8$5BdfA&Qp zV#nI=uKqS<7+2VJ&Ay)C;BS5-L#84410D2}2fh|k(Y|VH^qPF%Y{P_m)B6dYOOVX~ zE>TXREh+DX(M_2g;7@t?*?xpu@{N(Wk`KuMC6DytcnCkgw|jf`U|t$TBB-4ax=xUd zChDqPeF;y@oH~t#_^iEmOg9~u{zX}yCPt(-ZY}SZmSSAaB}g7El%FL zum40L!qiI3vP?%qe}ouLp``%3*Z(2b;RQQ_)XEx`TxK@)c)nuC2`+X8Kb zVkYNsL%b!c`U)%_9$3l{Gu(r-mn2iMU-!x-aXr%dHgPU_Y&QA6`tdGeis96j1JZec zE@NLp7i#kWw263A)BQ$89rTA^DP)~;S!01iYaCYz6cZ4|uif2~5wR<%VaF-B%w13) z#grSVfl7J2`{ObBb~$Z`3mPG6v}F|^Rh;R+vjC(=GyJ|S2#$oKi6q48sXv){X$nkg zxN|99ah1E=T4L48d43c!Q{&8kWm1;E>vOigKlis zq!{=}31VFkWfLpgP^DQ<+SyhjP1EI7ll`_aJ8Ro~z(rFv1)MDjnR_h)JLO&g9CNYq zH`jMGrLwSoKdgD$0+M{!+?vDgwT4ZG4F#ie5(mA9(q59@6k+F?b&n=qfN{xRPgN>T77cy;%DMWyOJBO@Cf@!QQC-FEJ=~hpN;?+!tV!%G~hYpgL^Yc!JL66PA(n(Pq?ec|1@^KPCcBIC z)(9p_@=Sj;--&R10bYSPfOZ%Dm!&;SolB}G6xX@!{a9&DozVF=g?M`yl0t*S-Fbgh zaMCPo67R9VBfQ7MMOks*;87qN@}mqmaKl+|t(^OQSo75>#7nh57km6U_ZOQX>Wo%F z^-YR&ewffok~0~|fdKQy%Pl=*Av(i0M1KMq=;bUiU(yjQlM_HX=3e}gg2zdNx%4dJ zS;xxeQ1_J-y9dk;*mt+wL6!guszZBS4?or8ko8mPmBd@9Kd8Z# zzvYf~9CCPe@#JZQS2hmHVpUhXvt!B$fRjKwKuw@g?Iu*{mnm~jAoIfj3nld)tk<~7 zVhp_An4=Ku;3v2ccO$#V3vSoO3g4j@A--gz3AKlrpG-L%s1ow1?5$_foIChjaK9eK zMIf)p8jO-~IL47FEJCcW)=^?!Lm$Z+tg_y>bH!5d_pvj9+N`IQ+)-CCL`1KfM~Y{S7ONe*tJn zdUOGa-)LUoaq$6DNPN37R~^G>Me?GWxNXDt`oy2hren>o_7X1uE=DLHD~{sOJ5c+i zPfy!_#|iTLWFSGwJF8#|*J%TFvWtR74w}tSWIzrfu1M1T0gkw@K<1~17VEstSM>q&lQU&*6U-O z?2XRgl|kxk39{M_ZIZQzn6(_#sz*$NxxXyHr0Sl9Fqb6JEzqH7nNSBT-4&;UYs^Er zrO^4I3T?UD%voZm2WjS*rw|q-yetvBsS^wyTmSSe469f!@o>&qP2@uueEtq(II77Z z-#G4?kf;YTnp1;_o96(R(1z@jtHk&TTAMX4DLeHBiV)qO`>)8xN>zg$-!m4YmI4Qu z)rXV{MxPZkPGvn3!^~LhrPFZX?iE*R^SFTRSHq>;r$XPkck^xQwvTQ{LZb@=y=gQ_ zGCvvI#K*G0jnanjDp0D;{1Mr1U8MlIpvXa=~PP{te5?8Tu;jz`T*3 z@4__VP@w!;FJ3(*K#;G(TJ?#z!l(sT?I5-TGb6 zlLn#yYvCsE_O$fG+(RZ$TPTa+IM`BV+gI~0A-0oN*y_6>E3u%$b5DV2YL=0T^G|LD zXngNV>Y;lu!qM|+O-?BFKza5Yla(+f$xAt6GcMv(#l*Z70hd$QkDschKpH+5)2}6> z1|ayDYCF$(6OBz8htIstmu3jm)^6FM48pg_sf|tNp-es+3eC>zZ(?9^{cJk(d0QNp zao`tn8>q({YuS5RWd)EK;o?U^Q|?2YHEaF1uOo(55VF0$_h2Iow-P7#v18&^EC zi>GWVcoaf{gvw&I;35&C+19b?ZJ zQmC|5%DR3a6FelSUnndEDt&y(by9KReW?C!$?(97%XKN8Lz;jvl?Ho>?8_{iYH6RX z&WF4Z%mHOk*L}#Y22+bE+!riB*)^Nz_=1szCzBxghMtB0e5-mt?;L#QPIl?MOTKK* zP>V0cyBiRO=-3qIr5Mq{rK=7TVMTBsqrE|OSQsOKwG8!}$`%Qz1c*SafM7Q1W%?d7wW305S7u=Mg+|^`HF=&qJ8~JG5eDogZUVnFlD*wF-B+~ z5SUKupjAnR+(YrX?cOyaSOV)iZEbc$KzuA3Nv^uL*$@*jq=wdy45>zN;g#e0HNJ4!ge2{Q9!a^o zvKAg*W2znKZ#&r4Kqx)F_4mO?I?*y$w3BFjotQu}9z6?hW(?O>=?A_m(#(Hh{VZ;aVh~Duj7OkV;!EbInQjSQYoqH)e+`Om-d61d;od4RxPg zv@xtuEI<$uh)Q2kN-IUa;pEC;0KKHyNuPjO*eJ*2RM0Zk2kV6`vFelsSQqIw^8)qz zUKUaabW8ZD-IZ}LB<)I4%%|@gmYNoPJlB|q%oOTmwjc|E&yRdI(n{T#ztiA_)n?3&ozZX_l8)s;YzmFomIg(hGth$G#wi!D0O5kW0Y7y8| z*}a=ZG$qQd_nHRiv;k56aZmHqPHsMLJY2p#U)aAgOQqXGrneZ6WN^hKZ{{)4=UUz_ zJy#jIP@tT-w*h>{fl89MvS=c|07`!pMX||5M?~C3Qo0f=07ts`$G zw1q9XPJAQ>3t?(B~!!6E@dBwKKf;$XFi%TMF?_Oy+ zuiWp>IN4Hk!aA=u!BG3259v=}stMU9nYIHRu7U*|l9-B`A$T!hHm+|+*U%7|=eUm| z{Ob#0p7h@8IfbnjK(jOKW5dps#u)nar6cTT8(#n;U_~Ns+4~sAJp_9&f@9Er=gW2Tc_o=Ykg18s; zNvmw0;dPN1n@~p7;-y&W`hsWN1Lv!O(DIZry|`VE1M%ihO}^G!J-8i_l%?DCHtxUR zWJz4#01J`m-%zz0BU??yJ{d!cz^+8cH$-(LYSL%`3ucxd@HTxO)+=rn#hCB5T6q{` zgH&*(6Y(rf$-_bJpJ{mQHVGGV5D(AbW!3|Z`r#ozqH(xT+$o)1hcJ6@Pxy@@|Kl8r zmS)hs$5NbX-rv{~O(q}0UK1E8fLOOSWJ1P(6A*VqtiUyJ&~sk{F0V7!(Mp=$#nn5x zn<2%Mew4*r?y#_bZx+Tb3u9=Sv2K`V`|8372c}=^3FA7vw*qNR%6nMXvNeJiy5k zZs2m6;>~&JWI_r__bYo78J^=xAvN`K1CiC{YV;GMmL7ojMLoO2wU`l=r1=-9pE#Uy zz4-z?+Qd!J%50*^=|3K=ZXmq2if2QWRz_)%Gf1T`DY^K#zppbHM*;CpQ|ucnluhuh zB*K7!Skqt@Ch(*cOt&0;KQm@fi=kAA!-0v&5B+I1je^uz65|JFl|&JPWuhrmQ(bB` zjf|A+7+l*pFA>2l6Mp~`p%qwa#lk>X$a(+TLpzJ-m|j4OIG=#1HfOlHn3neF33g-G zw6;dHw6x4sjN5zOz5%1_$5oe)SH|U)mDxbG!_@yIP|<(8PMJA!0aHXS z(EprNiTV%V2~It71IDI^=l+=uJBtN?G2V$oVdb9C8huUs$o8v<|5j_-SoV>j`9 z7=_qOD1QS>JLdG@7cB>{f2$FZ&P7aMuW4SIP-A8X4Q~Q*!JtUz*0ZduHi8PIjJC?yjljSpoRw{7n205ZXnGJ6Xw^x z&<7ryohHRVyELfxl%~lJpYR8(YFMEN?OCL=#*>-=FX`^T%h z-0*egshXIb^#NM`kf`)CbT-t|lv06kdS#wvi`?jc={0i_C^V>2O3_w?!^I5~Uvs^* zkE8yfHGH2qv!vAKL)~^iTl=zp-3!j98C7I6oDbzIAngIEGO+EX*A?Ziz|NMN&zx{uJd+e;p{Qu<^F=qPP zDT2|5825&R-dKIX=cVNG1^@C~;L;`H4Gg#9{BuYo_T}w6G&qvfe?I`GhX1XqI97i* z_*}#PeB_a#{)Y?$SNp%+m*w)mbfdU9R^R_GFTMbv7wIC9lmGF4DiHcZ;eEei4)!Gc z%VN>KO=}Se)a#&AscTi(hX>;l2rRq z4C_ZVqJ)h<+f1cKHCjr-0AHIgOwyF=T*>4N#_&qZmDF%d`T|O_ffa{0MUrU;w51iD z8uTp0P@|ULPTGrQ_dEhhOO@1da#O3LWwHbsQU0AzGY2CfVD~Q*CiMCT{;8m)Xk~Sn z1WKt6<1(UvgKjogi;IphFrtZe@!GW+GBYs*(p(I!eCc|7-tri@>3lFE`vGV91>X^#X zUxQEA&a1<9UKA9BRDUHVZ5A-$Yn-2nP~DRVx!xx)G&^8{+WIauDXta0Je7wp4-j@f z;w&u{PL{Mdg39I!2Cqe~4&@3opBx;cb35MKAsaAjq9>V>S zD$RUh<@6%m?_$Mq_1f?ebCqyecoHGA+-F}h^&@!y80BlBf*k{LX%5Iwv>`bLpr41H zZBP?!Sq&%q_&=U6c@e1Jqe%Xp3O?C7{@r4sb|fL z0s*E~hsZp*ub18lx10%1P=uz)-vquuBv#J&^NRt)m#@;=?6O(alARIg{$0GhjW?w3 z(on&Q{+dI9yq71u(eZYZ-Q4|*6%h-8pJ8kS55aUHiyW-b%vM@h7w8-B$VdeiZOE5$Z@L!}lf0yqeAdGIRCiD|tXyfjKW~PzP zXz(ux;f{Cl2$NoCa{zz9MbYzlm4f$PA(zt=HE-W29wReg7gZcrHmPyjB^wOYO|}qd zPKiACfH~mcf5i%u|33&#VxFif+|Eh`pjcB|8tT z4&6Z4CPSrL)^%Nus5mveldFgUW?4*Joeb+I)#{K5&UjV`PbIf4=PVVB+#2jzrshu&NK zq)!&bwU4;v_tr|~1^;}ILlmZ=UAKLP@mii9IfCd13nAThO2FaU%@ zRaz=am3H{Z1PpyuC?^&-amkkA- znkOP(R85U#m8@ME&Uvr#Q+x=-3yX-}LNS?$vg@)QQcT|I(U2=i-qIaL@WZ7I7QiW3 zfb{7;GyxUFF@4ebtk31PM1cbNs2tT^4k4}NN*Hrs7rhIi7QrGNha=%9cgP6M2&Ixl zhA7%^8Sq6Vm*4}xTh5y|{3~a4Try5+tEleSv<#x$@e^Z2b66$m$MzfO6F{8Qo|l} zn}Sq;@DkaFu=$h5W+zLTad{B{`WzTqaDO_Qpx>FDZBMlm27KNb?JF{JwbWzKYxzVX z=trj4;m%;kG!+h;Ze;lTsIpi8dl-Gnz;$nw1terDZduhvd+XI>VY8Em=D7VCVYFtA zi>Vqv(Xyls{|9>6&-oDW?1cksvp9~=E$CGwdKh&RmNoT%G;HiUuWlQg`IoRQCL_ik z;E-01&Ye^NC^ar_d(_YFbn5#>18cuQJ5R#e9iE=5I_Z}1>?s51M*3?V3}zW9taa}4 zYko6+bAvZ+JEJ

}JUWXJ=;KS4!oTU|zvGWuO-unuThgSs#m@o?cssYhZUKjHA7= zsVZV@%vt+@)X2(CQ>Wue!zMi17sNDa*RhE0Joc^s_=K1r*R6^nA`KRL8h!3&Y-jb= zS0dKsTz?Haa<0zkX+Pru{^|>VmzTsi2N?kp*MNK2z35s8P(nv*?U*nXYbhJ8{pC1M zqotkUgZZ-$scK4pWwwvg8TVuM^HTqgoT?nN4j7ge#I4fnz+@)b#GxNUGP=61O@)F^ z2lFTzLxS$9QuuJYq|d$z)Gux2FW$bmA=RW6i-(}Y+_zR3t z&w`(VQ3uD3wChm+LSFy}&0Y@!X-?JXe%AKNTZ-yD(mDk^em1HA^yq<%ou^lNBg5?k zjh6SX?e2G?{9S%(<6LB5yG;K&YZXV8oAX0LYMLfCJsKQr{~(g%`)Xh+WdB-B0A2s! zO@@(2Az6Cen0=*CRdz&1ikUoOc?|6JSajjOFkT|~`O05q7mnvW z0FJDGZh?xG%TGo}yMvmEnK5FFi!?Iq+rhx?i>c$;Y<@Gl&Av*wF1RA+IaA~(VfOvX zvrLWEjVUml&5he+zhyWUne>#G=&tRxh6t4V-trXEkr+^A7ZCyrPSzdMM48ZcVS;FUCY|);`EiSUOr7Kpx*46$p7WdiDMpkgu5z7Ip@+-mH$m%Jzj;=uZ>Cd;pQM%SOyj{fQ zt3E1v;S1n(xj!%(cm8mBU7xDeDxlO=kok<_=vMNHAhKzo`uxhsRF8cKmEWd~J~>?s z5)G8Chf@bG?F)!=Hg&L7{ZsWi>F={wQLY|GZT!gJh6BP1qJtb`U#A;9#&+GmZW)@d z^bI}LtnPy!5DMPF^J855YbQR0@VMSOaqzleB@V0KA?M~n>yx({gPaIEuA4qz3L3uiy?JRxTrxQ-fMXXMBk>@9`U#1zb<|aPjC5I9>DBCnkLTSXJBY!$+ zj$jxvOCp~P{ZWy|vd|OU$m6+DGQ4nOFK35PbH+ns z+_NjA06z6vJkaArhz5WfuL{jcey^nrN4naWvCdjapUDxnde4h@W8Po1_KgW#0U02h z&xzY@nDRk&)ov!T)7m71M1@|X+@suh7t2G%6KMoPvxnBJjv&by!wJrrOjb7rC}`|l%-p`TK^T(Z!5NDq1neYS04$7sSg(~TJ#&*KvG8yts}zx*n5)Ta4JfK_zA zj$b$TRxo06N8_t($zu~cmhgvJY@x1Cf=c6o{N9bQZ+13ZmFqlc2PVFQd50Yp8|4VoQ!~)aXw{Du1O)Slk!@J!8dW6ql0KtquK5gH6v+ zye!G%UVA$jdzw2Tx?+MUClCdD= zxpcs$S&vEE90-!nHRP^VVA&j29_#@NPd(eo0d7GcX!wJtW(XZxHH|vM$SaBF2ksgS z-QdG@?Td$@`0w15c!jWARK0rq?M(7ei*XOKnA6?hoCS^}u;ZFrzq4Xy_>{@TOy5fkrP%wU^{oo1jgnM>2EQ68%jr%gpOua(c3}J^`l&EN! zPB$q<(i9ME%D}*jqt}wiU+HUV)Vv2C)@#Xa+0TyxljYeQ1~UOpdI~x4psl z^2|ZHyC%!hN>;hgDd=$t?N;d*#kT~J8&IN&q)--ASw_kl?7&U~ilLgl)$|i8<)u{O zvfKqrnHV1(b3Y=*YTHssOH7Ig@_*3l1Txu$$*pyS;@ReR_K@<^=lWO%dJDj^oUw_+ zJ#3=M6ZBwasCsqayxsO>omcbKmB1PRz|LB?mAi1%3;LoI%O-Y@39$O9i_|D&V}Mgk z5bZnbM8q*J{jVHhUmft+F;w~ScFm*_yB#L+?j{i~?WlN*dV)ovY0(B=L*1nA5fnF2 z(i?F!+@pAB?_C|wVRi)C4}xzU)*aTGS+4Xa>N8&-)vqdcnj$vn1l7Dt57lQX@>RE0 zw?V)9z(sVSs45wqct|k|PCkJ$S*bFeI7hx{$?XT=M@J&*Kzy^U2hB*$pu6SJhUmX6 zfc-^9$AH!p#hJjN(R+$ioZD6J5B@P}bA&L3XQU7FM(8Hk%%lzn`+|JhTozD6Qd2GO zyPHRRShEt_n_aAH_-rypJC83pl#InE3Cqt;Bl$c~LvAYoykJ-6UEn=kCpNuFAKXq=X!;{Zh^diM5Ds_6Nk??u2|i-(c)b{aE#{1sCTd zNAXBAjBSW3IZ&DOALyUwVs~BFG9nmm4_Ab?qOkDfq-!%7RX-RL?I0D|I|U`igBN8ufFX6}A+yWIzwjV-*{VmGovPBG*D&1$pAoLB48QY+ z%hy|HcTHZV4+H8sw!}4wd1Lq-6<=N~fxXD{A>AD9yt->;|LjIg(h$Pm6jTpUdfnT- znY0J7LHT;?i+l7mZhja6KT9wh*RMxe`T-P^AE$}(6C(aBE643s%T{0YCq5PIeYZL0 z;P`dI@m&>vt5;&hJ!_RO3F{M-x$0Bx!%T0jHeg=gptb6uk_WX?<>BPfId*rdi_3$h z|0zd*_$-6ca=ib{=l&a`>E7orOb>A^w$>Y@C&vYwGHR|Iib@)si=_9lqB7|p3^cem zQa`50CvkLjdG~f`^SN;Eyd65cMb+5sH|6JRjA5d3j0}s7iTo=phSg}Vssp#9F6{wT zqJ=VYO2`h(nK#eO-9UV_eSJr{zCbqAVK@p{S&=$&0<2ERMl=KguOrI4mX;B7ij-Up zMU0!0$S$HE91MT@Ft!lVt|8fXZ>Zv4=6N<`6%H(e?NN$Kk_ zN8&`T`5rx6Y#|eCb!YHD8>wFCxDn};oG)D!kqqT{*dOC3_7%1N3gXJzVnB;~u)ku) zhB&tX?*E}z)HcIT8CM|i!7V~*pBRaZe4w9w5;#Q;eKCAz_<^vyOl46AZUu(c-^abyg(h|;slQ5D$)437r z(lntm$~w~i?)xeeAp#qIlmI99{?q(WhPwM0Jt35-o)dCCW5x{@#P6RgS0!VMUrlTN z$lqB*7h74?el#$BS*btLWR$a3rZeu|-sZH82`{{YQAJ1!Eou>eF>DhAF}h8 zW$K^2Xf<qR1(OTSjGTT;=v}xS(VCiu1tm4OG)vYWvHG&*c zbG716{_(5jHoQDFn&{My^di6UUxRu4#j0C|d+`|loJ?)#8(LsM-hi2opD#?q~8(URw9~2IV<*01UEUd*J@Q6>Qpz&+7eISEm@-8 z!e^)*Zd2z;wpR}xj!@ui0QTk(=K5=u(nH4A8>qy&!%oM%G>kT_7gMS#A2=N3o=SRk zwjLL-rxYhUWb`K>d-JE!$xw{tcZhCK%QAXs!3>wABhZ&ZS|WMU}1c!yu1 zli7pv(Y*0?K%9rrITd6B`IYBM#$CNmaVt0V&SBC$XscDSzm?I ze&KbfmI>ma_JK!HHQz+}*i$kUh|h%99Lvwuwi|r71v`)z*`*V}OXH%O?-{A>*nfS^ z>Y6rn@%(&~qlSGGJng7l`J#207_)ipu!oWP98vZW(M)6G@fF)n(q5G4yhiy2X$ggg z583K^xGyqH&gc2G#51xgZZ^DG<0W~Ba{uy_K+3h3-F10SjX+ww(jc}z3$b;B|pa=d(RiSyGq*F#5b|gv6)f$)X>tgBKU0(Xx`Rx zQ_IuV;bZl@U$MU;W%c$9PB}Co>3l=M*Wv5bw$d?Ur*$@A_OPYye6lD~*VeIqy7}7R zvGlUI1_D`VP1o~kPxJ&W-Fy&O)=*A~-rt(}eKA@W6m4dFQMA8twr*za+_s{vHAwHYUyLd~QZyp7kc$q`c&d8dlbPTZ}+K9fdwUjac98pHn8zCKT$N5A>YP?aNly zHf-~W|*X)5!cI+8mZt3P#LPes?8D7sB@@)+>HW$R~O?K-x_ijxYS+8vqRaF-p ze2fIC@0PY}HrX70TRz^eKU?aW7F<>dCl=2|oNxAh!5v?*x!APz^?6dQn+U6|ah&FF zF2b5V{`UC&#&DX&3wTQ%2GWLczQ6n0p6TQtv1y8 zg~08dv`qlP62CSR#sPXnx=a6>U@mrR$5+*pKMzM(hHwnm)a(J?xPFmRxCK( z?$d*UI?T+i>sADtm)dn|{N~svE~d`e+XyQP7gnr*58(GyvA%!alBLfTYiGxi1uR-= zxv_TcDfxHi?(yB*gD0H+=PNS5pAqC$HLZ&@xTBS0neD~JD3NwcgZ!?-x=HhecPmI; z*)1DK&WltYdP;^yAkJiu?_Bqrq{cI6D>+QsYH`1*Le~r08gYz-7CZF|&&q0hGpDLV zb#eBdyuFqLz1GZ25U=xpmdcmgxv|2i%4C0-FAOnFPfh+_qthw0Bgk~mYz@^0;!|r( zSYJtAH=>w^EYwdnu%i@o{2 zhmjlYq2hD<{LvGCY8a#V@2#$h{{S)3?&Geu(J8zX0z&?ue#O&}lz3{C@SE;?Tpjqg zL;n=u;C*7>;fiO2qev9=H~Idz2lhtURNBd-mRE_f=jOg&V)}2)lUUe=xpRQPyQtESNXb@dXmIMi@YP|)RF8{O)Qa_@2E1~05pEZV`P+ZY(=PrX znBK+E5zn<1Gk8ee7lorO?pa>pBEGzW`)%$Wc~Wk{ps$_uJ3U6>uXsVbwWTCE&TJ2^ zoa4i?A5RRX;BKW#{ngywrRDKEqo~GPmrA*~ium8A#oweiC3hfLER3~_5+U#n9|P|v$#xYdoJ_bM zH&C`h7Z=UuO>znjbdX;=H7b~#q&O^=N^DE2kkA7<~~ zZCo$m;AmnenA|w0sNo6`?J|t&9I(#G2;&LtFR%(Lu%iqs9-G|adA{D9shEn32>&qo z!C|m^3r9lX=kHS~KvzrqQJSr^w6N3~d926PcDA@5N$Qq14F)TaW#{eYiE!4G%{1cm zZ44W9h38WBCL^s&89bL-UtWA1(aL#*Dv-%*WTu#gngS}PL@9z+{-U>Fkh=Uz_BJfk zAUODEOxv7QSv|ne0N|>tYRq~Go2n`I;;SvMyJW!A9K-}0M?+?b5Nar_tC}IOw!Kr9 zO-F-TBrc=S!foEf)lKNZePF*BrYqv3o$UM3n@q|C6bvvO12dy*T?Zv+fbwtMOA@*=<*1?~k7{qUn>ke2tzynE_*$ zyQDn2tL-@<{T?#93kIt$;Nh?re&~(Ou2g=Atn^#2@h*AuO}c(t7`%SL=R*+94`X&m ziW`C!x!W#lJ_l^pRO#sbl@L$$_7qqC(WG)|PlCIv0qkUb6f&=oOM={Ph_UgX_q#}k zDB3x#XGH+6+l88^}SLEUC4B!|o84|2H`%EH# z8J%Eqy7Rh3wypT-`=%~$=f^3`ouMlCG0q@^7hk>SR@geB{tE)R_Xjem6k6M~D7_|`5auNz#$najO`35h7v^u{rcJqd&evKK-z)lZb4W<%Z z-`w1_Q|nR*zABHWV)?#V$Lfg|Zq>1=G~4Y zgwj}D$CbPPY@#5H4RZr$uAFZVu`QDto!)+3 zUp(GDjavqDxh{{=A>LnpPhB?rm2$&wKc5QQt@YmTwQrtH-Ta)U*OvWmw-2SB<>As7 z7qj-8aN4@sJ3wpRz(1D?Q0!SjG`M;@cZwjCX`4*J%dZ|6XY~Y!?Ajo{i3u86s`ppD zy1D$kx=ntMrdr4ekuccCjJ7hm*FQyOgaoV469ZH>>26bY92t!1i}#8LC$G;PW=-;Q z8!e!AL7ubqtilBz4WG%Bri_V6-y4gggT%)FtGe_4YHC^gxEuxH(4>eWD5w+_1VV3t z!;vB-AR@g9As|vhmllGk2T*z-fIv`!pah8s5(EXQQ6We*C?!B>(n1J5Cb>E1yu9zd z?_Ku~xbw@bHG5{(+G~BE{e0)MXZHTS|6{8PT{Gnz9*!Of#Oi;c5bjM_*F`Si>I zfl1uk5_rH`;G0vUw*-)Sy**`cL-RVX3Ng-kYt%HA=5oM$RSZVl$sYDSRB(aa63^s-n|pKI!O`G8!e~ogrsPLE1vK8f2d z^ya7TUyha#QJUz*>T1>ukTj4c2kFvsw_8}S6q8AT{(|MMRI^T=S(14o8EbiWa_a~G zzJjn^_qp0@c33_KtdW>-%OMwFF|+Cz+6YTJ9OnB&UvV;WzdqA*9ZagAWbl;TS64o< zI^y@3OWX5#V*#uf6ir)i{SkF^cPJ|wX{&f{yW#|5SKh9n{K$Y%f5k#I%AT~c^-4#s zsH8{zWj?U;&V1XFv_Xl-NAC0YRtaKIM50>J$JBF&p|?tP@&=?3$m1sQ2G^jEX&yK1 zE!&8wE7&b$C2P@3?+il47b*70IJr&QN*ud5PUO+`d;xbuvmkBvEAjnH&3rXQkat$V zpZCiy6{h#?l*If_EvV8hy0l*fCZA%sgPjlZaLawDPkQp!kJ$530<2^_HMcP=1eBO_ z;fPk_@QeU4Ojw19ws-DUNF=9yI4z7#VSI%cVIba$?b-7o77Yh29Fr|aS{{Wi-ISC30H-?bJx5FXzDUQGEyh9CP^ag&pY*a8hklwR}pUg zt4pd7WN!+&KphLP5~=f`njB7?6Zu1pYZB%GWISNO_IrNrY;%oWDW&@K-ULn1FEPkV z46F>ulYpg(duq9RfC>p$a|&e4KV4D*@je_0kc=Ox4NYg()GGdOOeF~m_Eeu`hIEqY zJVrOB_BBO?YUhMtCF37X*q6pz46u>75(sdS#lW&@sBLUEFC!r}<}B z-TKhV+9Br=aT6)y;zAFEsDY-BTc#FQg>2w^o+vpULxS&afIqrtClj;NniNYleMjA+ zrNP_^Rkq_RG6Q1iV1bT{_qvvPQvEh?o({57EiDceh5GZR|1L`v7;Z=9AG22rD^rE0i14AECv3za2&z(g$>TwI3 z|A?YnGLj%*+@VVk-&oNTN;Xj5+R+{S+6mSt=dOL>9yCCK6Q`#HwWdsd%L2OGUbaZs^UEjLpDQn?DJ=b-)66Nk7-9~HP=qt$M3f58A%hR-Vnqfh6 z?z$Lq^Y|f;BOK}X*Tqc{K6gO@{TZAcb9AvZ_7TVfLBOpz0PV3W2uGwA#iyLgtCpF z&H7?%3~qP)uzmKapK{R4FK=jpv%;c835oph)Y|xTCKH%8HxlG%C&oFK@1pnjhYpR6 zXZ3d6<SxDS|G z4=K_#Gaj1zut`79ZN`4zbO>7^$NP&zcPgj|HPT*R{j78Wj(upy`NG12Tt(X?UhA?V zk6q=@!>;S1Xxi;-@h+PHG%YF7~V^9~eGJtE=MxTW79f&CmMhar@WA(F==Yi(%B-d@Y z-5iO6aRq62w@K7+SC0HivBCC#Qf%pJw_e`sY>NHl|55CD2YI8phhg@)y&)$B*nc|} zmVJaFsy%Q=t|YD9@30G9Cp+5d8|s`W#`to04fyHn zN~lu=xY)XqrP32agiMAz+C~t%cxa6F2HQkvUQ9_6M{3Q_BE{eHgf`+$smg9zGKS$- zL1$v3saY@J4Wa>;Dc{t{`>yrTJrZMGt4cw%hA9I0%vUzh-dDOO5F#of;}>_MFipGq zbc1V%Te(l93DRM7y9|&~sv0F<-gCM(tx!(o&o^>d`&cs?;-c@N_cJq(Jnu)l$=XH_FL? z7-+JthJAEm#wcax0&v=Hy6o*{n?GdJ(T{Ad+IY2UBpZ<5tnNQ04hOu2k zaL`+6se=@7E`R+ma@TweUM=1Nlvd>6<3sxz1UyX5&pp!jDM91M^DiHNHOE)}0{xLP zsUm}2>Y~2$+#ObF-VN<87qp)p+yYm{ws5b--xfm{6^Jy;rTR^q9^aagjC8-}rOFp} z4tH}fT)TH!4Wiy_kX$E@4&L@^_PY6MbnI{VPZ7J_7K7>Gg3L z;4Jklx+AN;eo+V5WNL!Ui!kG`!|pJH=7({i7y!bfUA^iR9Tr$u)@wKT8n0b2vxP)x zXv8c|XLwu0B@Vs(h&k(}Uv?+2OYQTq$`k#ivAIUS1#d3yC_ex7wR6Tah}-lqvXYE_ zokhL%doj`Jy#XvvNPR7xr$T8W9O7gbqx`&s{ZzPcReyP06Tb~`2-36dO#2C#t}fG) zoEhbUpln?X+9Ix=76@TdbG26a8yH#9GdH`H=AV9w@HqyuTijm!#$}(4@YU#(xv9E> zD$T7(5r1o7n&07Q9b z6xZhJ<8wXFSA>Q_35$lTwjl&eOCb8XTNHH@F=VsO;4$}C3ppBbB2w%9#k+pO%>t8* z^NWGgoPf6eruosvz`II%NM#bKHM3UV#x!QFpnMH*(kWMG*Xus6K3ph<&kSG>|E##p zEca|W*f;TW50;#oOtG`~nU!^#II~?jgNigqow(r?5w}oj^8%Cey?(y6l|<}p2vVep zWaAMG{vwYZ;Ya66u{;p}o6g;39y&43UQTQ^sxDwI($dOQYrcvRl_Nehz-=ry>dQ4jibI|11e-}S8RtWXI4sPKjc#0a zrlvMI4*#+BbWMKDni#o9A-Ro+jL|<`{%ZQKvq}7S4lZH|I`;~FftAl*Kg2HPCf3F^ Izu!#y2Q&&MEC2ui literal 0 HcmV?d00001 From 59c7e22d489f3ace0a6f7493d385902c2e9305cf Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 18:53:49 +0200 Subject: [PATCH 304/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 9046cfc3d4..ea5e3ffc09 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -4,9 +4,7 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) of pretrained models -| Model name | Dataset | AP0.5 on validation set | AP0.50.95 on validation set | AP0.5 on test set | AP0.50.95 on test set | -|------------|---------|------------------------------------|---------------------------------------------------|------------------------------|-------------------------------------------------------| - +![Alt text](stats_pretrained.png?raw=true "Title") From 51eca40dae0445157dc6579ee12aba5e1e4bbcb6 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 18:58:36 +0200 Subject: [PATCH 305/374] Add files via upload --- .../nms/seq2seq_nms/stats_pretrained.png | Bin 107092 -> 196810 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png index 0cf4e76401daecded231a879d65de350a29cd007..5e6f70ee9a8dd586522a5b584240cf2aa371804b 100644 GIT binary patch literal 196810 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

YB1)A#0;q|6iR~e7)S-u6A5vjjR@P1%q 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�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%0AM-uMA3=6FlILHiQd``&?XwR&z6d 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

YB1)A#0;q|6iR~e7)S-u6A5vjjR@P1%q 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�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%0AM-uMA3=6FlILHiQd``&?XwR&z6d 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 Date: Fri, 1 Apr 2022 11:27:57 +0300 Subject: [PATCH 359/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 27a16f75d1..54272c0e70 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -575,9 +575,19 @@ def count_parameters(self): raise UserWarning("Model is not initialized, can't count trainable parameters.") return sum(p.numel() for p in self.model.parameters() if p.requires_grad) - def download(self, path=None, model_name='seq2seq_pets_jpd', verbose=False, + def download(self, path=None, model_name='seq2seq_pets_jpd_fmod', verbose=False, url=OPENDR_SERVER_URL + "perception/object_detection_2d/nms/"): + supported_pretrained_models = ["seq2seq_pets_jpd_fmod", "seq2seq_pets_ssd_fmod", + "seq2seq_coco_frcn_fmod", "seq2seq_coco_ssd_fmod"] + + if model_name not in supported_pretrained_models: + str_error = model_name + " pretrained model is not supported. The available pretrained models are: " + for i in range(len(supported_pretrained_models)): + str_error = str_error + supported_pretrained_models[i] + ", " + str_error = str_error[:-2] + '.' + raise ValueError(str_error) + if path is None: path = self.temp_path From e8a9d532c4b5af840cb2230b90a2984ab3adf92d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:28:30 +0300 Subject: [PATCH 360/374] Update eval_demo.py --- .../perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py index e241be9487..01437e578b 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py @@ -24,7 +24,7 @@ choices=["EDGEMAP", "FAST", "AKAZE", "BRISK", "ORB"]) parser.add_argument("--iou_filtering", help="Pre-processing IoU threshold", type=float, default=1.0) parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cuda", choices=["cuda", "cpu"]) -parser.add_argument("--pretrained_model", help="Name of pretrained model", type=str, default='seq2seq_pets_jpd', +parser.add_argument("--pretrained_model", help="Name of pretrained model", type=str, default='seq2seq_pets_jpd_fmod', choices=['seq2seq_pets_jpd']) parser.add_argument("--split", help="The split of the corresponding dataset", type=str, default='test', choices=["test", "val", "train"]) From b86a2282b165c196b159ac59b6f968a0227a1b28 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:28:42 +0300 Subject: [PATCH 361/374] Update inference_demo.py --- .../object_detection_2d/nms/seq2seq-nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index a12923fe51..c260546d13 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -27,7 +27,7 @@ choices=["EDGEMAP", "FAST", "AKAZE", "BRISK", "ORB"]) parser.add_argument("--iou_filtering", help="Pre-processing IoU threshold", type=float, default=1.0) parser.add_argument("--device", help="Device to use (cpu, cuda)", type=str, default="cuda", choices=["cuda", "cpu"]) -parser.add_argument("--pretrained_model", help="Name of pretrained model", type=str, default='seq2seq_pets_jpd', +parser.add_argument("--pretrained_model", help="Name of pretrained model", type=str, default='seq2seq_pets_jpd_fmod', choices=['seq2seq_pets_jpd']) args = parser.parse_args() From 36403794a58b07895556d9a06f13d7f7ba353d42 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:29:16 +0300 Subject: [PATCH 362/374] Update test_seq2seq_nms.py --- .../object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index 41b0f29155..fae6caa9a4 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -49,7 +49,7 @@ def setUpClass(cls): device='cpu', checkpoint_after_iter=1, epochs=1) # Download all required files for testing - cls.seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd', path=cls.temp_dir) + cls.seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd_fmod', path=cls.temp_dir) @classmethod def tearDownClass(cls): From 8986a6692a83adc047a7ee32cc147626fde7073e Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:29:37 +0300 Subject: [PATCH 363/374] Update test_seq2seq_nms.py --- .../nms/seq2seq_nms/test_seq2seq_nms.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index fae6caa9a4..66d06bf3a6 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -61,10 +61,10 @@ def tearDownClass(cls): rmfile(os.path.join(cls.temp_dir, "datasets", "TEST_MODULE", "annotations", "test_module_anns.json")) rmdir(os.path.join(cls.temp_dir, "datasets", "TEST_MODULE", "val2014")) rmdir(os.path.join(cls.temp_dir, "datasets", "TEST_MODULE", "FMoD")) - rmfile(os.path.join(cls.temp_dir, "seq2seq_pets_jpd", "fmod_normalization.pkl")) - rmfile(os.path.join(cls.temp_dir, "seq2seq_pets_jpd", "last_weights.json")) - rmfile(os.path.join(cls.temp_dir, "seq2seq_pets_jpd", "last_weights.pth")) - rmdir(os.path.join(cls.temp_dir, "seq2seq_pets_jpd")) + rmfile(os.path.join(cls.temp_dir, "seq2seq_pets_jpd_fmod", "fmod_normalization.pkl")) + rmfile(os.path.join(cls.temp_dir, "seq2seq_pets_jpd_fmod", "last_weights.json")) + rmfile(os.path.join(cls.temp_dir, "seq2seq_pets_jpd_fmod", "last_weights.pth")) + rmdir(os.path.join(cls.temp_dir, "seq2seq_pets_jpd_fmod")) rmdir(os.path.join(cls.temp_dir)) @@ -89,7 +89,7 @@ def test_fit(self): def test_eval(self): print('Starting evaluation test for Seq2Seq-NMS...') - self.seq2SeqNMSLearner.load(self.temp_dir + '/seq2seq_pets_jpd/', verbose=True) + self.seq2SeqNMSLearner.load(self.temp_dir + '/seq2seq_pets_jpd_fmod/', verbose=True) results_dict = self.seq2SeqNMSLearner.eval(dataset='TEST_MODULE', split='test', max_dt_boxes=800, datasets_folder=self.temp_dir + '/datasets', use_ssd=False) @@ -104,7 +104,7 @@ def test_eval(self): def test_infer(self): print('Starting inference test for Seq2Seq-NMS...') - self.seq2SeqNMSLearner.load(self.temp_dir + '/seq2seq_pets_jpd/', verbose=True) + self.seq2SeqNMSLearner.load(self.temp_dir + '/seq2seq_pets_jpd_fmod/', verbose=True) dataset_nms = Dataset_NMS(path=self.temp_dir + '/datasets', dataset_name='TEST_MODULE', split='train', use_ssd=False) image_fln = dataset_nms.src_data[0]['filename'] img = Image.open(os.path.join(self.temp_dir, 'datasets', 'TEST_MODULE', image_fln)) From eb6e552e76355642f91fae5946ba22cc3e6331d0 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:30:39 +0300 Subject: [PATCH 364/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 42db243fc5..34d24fa61f 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -257,8 +257,8 @@ Parameters: seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, app_feats='fmod', device='cpu', temp_path=temp_path) - seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd', path=temp_path) - seq2SeqNMSLearner.load(os.path.join(temp_path, seq2seq_pets_jpd), verbose=True) + seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd_fmod', path=temp_path) + seq2SeqNMSLearner.load(os.path.join(temp_path, seq2seq_pets_jpd_fmod), verbose=True) ssd = SingleShotDetectorLearner(device='cuda') ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) @@ -281,8 +281,8 @@ Parameters: seq2SeqNMSLearner = Seq2SeqNMSLearner(iou_filtering=0.8, app_feats='fmod', temp_path=temp_path, device='cuda') - seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd', path=temp_path) - seq2SeqNMSLearner.load(os.path.join(temp_path, seq2seq_pets_jpd), verbose=True) + seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd_fmod', path=temp_path) + seq2SeqNMSLearner.load(os.path.join(temp_path, seq2seq_pets_jpd_fmod), verbose=True) seq2SeqNMSLearner.eval(dataset='PETS', split='test', max_dt_boxes=800, datasets_folder=datasets_folder, use_ssd=False, threshold=0.0) ``` From 485f103ccdd99de9eaaf9086202ad892b6e7400f Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:52:43 +0300 Subject: [PATCH 365/374] Delete __init__.py --- src/opendr/perception/object_detection_2d/nms/__init__.py | 1 - 1 file changed, 1 deletion(-) delete mode 100644 src/opendr/perception/object_detection_2d/nms/__init__.py diff --git a/src/opendr/perception/object_detection_2d/nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/__init__.py deleted file mode 100644 index 8b13789179..0000000000 --- a/src/opendr/perception/object_detection_2d/nms/__init__.py +++ /dev/null @@ -1 +0,0 @@ - From 4d9c0c7ed29585dca0073cc18bfaa4bf8415e047 Mon Sep 17 00:00:00 2001 From: charsyme Date: Fri, 1 Apr 2022 12:07:30 +0300 Subject: [PATCH 366/374] final changes --- src/opendr/perception/object_detection_2d/nms/__init__.py | 0 .../perception/object_detection_2d/nms/cluster_nms/__init__.py | 0 .../perception/object_detection_2d/nms/fast_nms/__init__.py | 0 .../perception/object_detection_2d/nms/soft_nms/__init__.py | 0 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/opendr/perception/object_detection_2d/nms/__init__.py create mode 100644 src/opendr/perception/object_detection_2d/nms/cluster_nms/__init__.py create mode 100644 src/opendr/perception/object_detection_2d/nms/fast_nms/__init__.py create mode 100644 src/opendr/perception/object_detection_2d/nms/soft_nms/__init__.py diff --git a/src/opendr/perception/object_detection_2d/nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/opendr/perception/object_detection_2d/nms/cluster_nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/cluster_nms/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/opendr/perception/object_detection_2d/nms/fast_nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/fast_nms/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/opendr/perception/object_detection_2d/nms/soft_nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/soft_nms/__init__.py new file mode 100644 index 0000000000..e69de29bb2 From 03155a0d303484c9ee5cf69e8bbf283083c7788f Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 1 Apr 2022 17:56:10 +0300 Subject: [PATCH 367/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 54272c0e70..fd8a97d16c 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -396,13 +396,14 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, threshold= dt_file_path=output_file, only_classes=[1], verbose=verbose, max_dets=[max_dt_boxes]) os.remove(output_file) - for i in range(len(eval_result)): - print('Evaluation results (num_dets={})'.format(str(eval_result[i][1]))) - print(eval_result[i][0][0][1]) - print(eval_result[i][0][1][1]) - print(eval_result[i][0][2][1]) - print(eval_result[i][0][3][1]) - print('\n') + if verbose: + for i in range(len(eval_result)): + print('Evaluation results (num_dets={})'.format(str(eval_result[i][1]))) + print(eval_result[i][0][0][1]) + print(eval_result[i][0][1][1]) + print(eval_result[i][0][2][1]) + print(eval_result[i][0][3][1]) + print('\n') return eval_result def save(self, path, verbose=False, optimizer=None, scheduler=None, current_epoch=None, max_dt_boxes=400): From af7d567a4c0be14e84e5988c44d8d7b51fa8fbd6 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 7 Apr 2022 12:05:04 +0300 Subject: [PATCH 368/374] Update index.md --- docs/reference/index.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/reference/index.md b/docs/reference/index.md index f0926d311e..e588a181a4 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -43,6 +43,7 @@ Neither the copyright holder nor any applicable licensor will be liable for any - [centernet Module](object-detection-2d-centernet.md) - [ssd Module](object-detection-2d-ssd.md) - [yolov3 Module](object-detection-2d-yolov3.md) + - [seq2seq-nms Module](object-detection-2d-nms-seq2seq_nms.md) - object detection 3d: - [voxel Module](voxel-object-detection-3d.md) - object tracking 2d: @@ -109,6 +110,7 @@ Neither the copyright holder nor any applicable licensor will be liable for any - [centernet Demo](/projects/perception/object_detection_2d/centernet) - [ssd Demo](/projects/perception/object_detection_2d/ssd) - [yolov3 Demo](/projects/perception/object_detection_2d/yolov3) + - [seq2seq-nms Demo](projects/perception/object_detection_2d/nms/seq2seq-nms) - object detection 3d: - [voxel Demo](/projects/perception/object_detection_3d/demos/voxel_object_detection_3d) - object tracking 2d: From 046b4b77aaa7c29e6e8a6ad42c8663ed54219c77 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 7 Apr 2022 12:06:04 +0300 Subject: [PATCH 369/374] Update index.md --- docs/reference/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/index.md b/docs/reference/index.md index e588a181a4..72048f6826 100644 --- a/docs/reference/index.md +++ b/docs/reference/index.md @@ -110,7 +110,7 @@ Neither the copyright holder nor any applicable licensor will be liable for any - [centernet Demo](/projects/perception/object_detection_2d/centernet) - [ssd Demo](/projects/perception/object_detection_2d/ssd) - [yolov3 Demo](/projects/perception/object_detection_2d/yolov3) - - [seq2seq-nms Demo](projects/perception/object_detection_2d/nms/seq2seq-nms) + - [seq2seq-nms Demo](/projects/perception/object_detection_2d/nms/seq2seq-nms) - object detection 3d: - [voxel Demo](/projects/perception/object_detection_3d/demos/voxel_object_detection_3d) - object tracking 2d: From 8582164bc7360e98b420c28ff7bd6442cf1d5033 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 11 Apr 2022 11:48:24 +0300 Subject: [PATCH 370/374] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b2cea8f27..0c9fd2ed32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ Released on XX, XXth, 2022. - New Features: - Added end-to-end planning tool ([#223](https://github.com/opendr-eu/opendr/pull/223)). + - Added seq2seq-nms module, along with other custom NMS implementations for 2D object detection.([#232](https://github.com/opendr-eu/opendr/pull/232)). - Enhancements: - Added support for modular pip packages allowing tools to be installed separately ([#201](https://github.com/opendr-eu/opendr/pull/201)). - Simplified the installation process for pip by including the appropriate post-installation scripts ([#201](https://github.com/opendr-eu/opendr/pull/201)). From 3a11340cb4d252583d5228e2a7a9f5ce34a0412f Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 14 May 2022 16:20:05 +0300 Subject: [PATCH 371/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 34d24fa61f..6f5dbbe19c 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -139,7 +139,7 @@ Seq2SeqNMSLearner.run_nms(self, boxes, scores, img, threshold, boxes_sorted, top ``` Performs non-maximum suppression, using seq2seq-nms. -It incorporates the full pipeline needed for inference. +It incorporates the full pipeline needed for inference, including the FMoD's edge/interest-point map computation step. Parameters: From 49a338b0c013e0184de036a06cdebdbb6e96b320 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 14 May 2022 16:37:32 +0300 Subject: [PATCH 372/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 6f5dbbe19c..a56479972d 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -5,7 +5,7 @@ The *seq2seq-nms* module contains the *Seq2SeqNMSLearner* class, which inherits ### Class Seq2SeqNMSLearner Bases: `engine.learners.Learner` -It can be used to perform single-class non-maximum suppression on images (inference) as well as training new seq2seq-nms models. The implementation is based on [[1]](#seq2seq_nms-1). +It can be used to perform single-class non-maximum suppression on images (inference) as well as training new seq2seq-nms models. The implementation is based on [[1]](#seq2seq_nms-1). The method is set-up for performing NMS on the person-detection task, using the implemention of the [SSD](/docs/reference/object-detection-2d-ssd.md) detector. However, the method can also be employed in any single-class detection method, that incorporates a non-maximum suppression step. The [Seq2SeqNMSLearner](/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py) class has the following public methods: From 3926d367e6a9afc0bc775e0ad838e13fec86eacc Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 14 May 2022 17:30:01 +0300 Subject: [PATCH 373/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index a56479972d..af8edcd98d 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -5,7 +5,7 @@ The *seq2seq-nms* module contains the *Seq2SeqNMSLearner* class, which inherits ### Class Seq2SeqNMSLearner Bases: `engine.learners.Learner` -It can be used to perform single-class non-maximum suppression on images (inference) as well as training new seq2seq-nms models. The implementation is based on [[1]](#seq2seq_nms-1). The method is set-up for performing NMS on the person-detection task, using the implemention of the [SSD](/docs/reference/object-detection-2d-ssd.md) detector. However, the method can also be employed in any single-class detection method, that incorporates a non-maximum suppression step. +It can be used to perform single-class non-maximum suppression (NMS) on images (inference) as well as training new seq2seq-nms models. The implementation is based on [[1]](#seq2seq_nms-1). The method is set-up for performing NMS on the person-detection task, using the implemention of the [SSD](/docs/reference/object-detection-2d-ssd.md) detector. The method can also be employed for performing single-class NMS, in any class other than human/pedestrian class. In that case the method needs to be re-trained from scratch. Finally, a pretrained-model can be employed for evaluation or inference on the same class that it was trained with, using RoIs from a different detector than the one used in the training. In that case, we advise to fine-tune the Seq2Seq-nms model using RoIs the detector, employed in the inference/evaluation of the method, in order to achieve the highest possible performance. The [Seq2SeqNMSLearner](/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py) class has the following public methods: From 33107efbd478d3d11408198c31b3b4967caf6100 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Sat, 14 May 2022 17:32:33 +0300 Subject: [PATCH 374/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index af8edcd98d..513233c833 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -5,7 +5,7 @@ The *seq2seq-nms* module contains the *Seq2SeqNMSLearner* class, which inherits ### Class Seq2SeqNMSLearner Bases: `engine.learners.Learner` -It can be used to perform single-class non-maximum suppression (NMS) on images (inference) as well as training new seq2seq-nms models. The implementation is based on [[1]](#seq2seq_nms-1). The method is set-up for performing NMS on the person-detection task, using the implemention of the [SSD](/docs/reference/object-detection-2d-ssd.md) detector. The method can also be employed for performing single-class NMS, in any class other than human/pedestrian class. In that case the method needs to be re-trained from scratch. Finally, a pretrained-model can be employed for evaluation or inference on the same class that it was trained with, using RoIs from a different detector than the one used in the training. In that case, we advise to fine-tune the Seq2Seq-nms model using RoIs the detector, employed in the inference/evaluation of the method, in order to achieve the highest possible performance. +It can be used to perform single-class non-maximum suppression (NMS) on images (inference) as well as training new seq2seq-nms models. The implementation is based on [[1]](#seq2seq_nms-1). The method is set-up for performing NMS on the person-detection task, using the implemention of the [SSD](/docs/reference/object-detection-2d-ssd.md) detector. The Seq2Seq-NMS method can also be employed for performing single-class NMS, in any class other than human/pedestrian class. In that case the method needs to be trained from scratch. Finally, a pretrained-model can be employed for evaluation or inference on the same class that it was trained with, using RoIs from a different detector than the one used in the training. In that case, we advise to fine-tune the Seq2Seq-nms pretrained model using RoIs from the detector, deployed in the inference/evaluation of the method, in order to achieve the highest possible performance. The [Seq2SeqNMSLearner](/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py) class has the following public methods:

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 Izu!#y2Q&&MEC2ui From d761017b409e7b3bdb6efe01accc44f6aaad4d51 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 18:59:28 +0200 Subject: [PATCH 306/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index ea5e3ffc09..6ba0e93dda 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -3,7 +3,7 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). -TABLE-1: Average Precision (AP) of pretrained models +TABLE-1: Average Precision (AP) achieved by pretrained models on PETS and COCO datasets ![Alt text](stats_pretrained.png?raw=true "Title") From 3f391fa2f54c35d06c8aae84062bf955670bcf41 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 19:00:57 +0200 Subject: [PATCH 307/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 6ba0e93dda..489fe71fe3 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -3,7 +3,7 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). -TABLE-1: Average Precision (AP) achieved by pretrained models on PETS and COCO datasets +TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task. The maximum number or RoIs, employed for the performance evaluation was set to 800. ![Alt text](stats_pretrained.png?raw=true "Title") From 1d08628fad449ed834cce205a6a261611d390b2f Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 19:04:48 +0200 Subject: [PATCH 308/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 4da3c14378..1cb90aca33 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -264,6 +264,11 @@ Parameters: boxes = ssd.infer(img, threshold=0.25, custom_nms=seq2SeqNMSLearner) draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) ``` + +#### Performance Evaluation + +TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task. The maximum number or RoIs, employed for the performance evaluation was set to 800. +![Alt text](src/opendr/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png?raw=true "Title") #### References From 07bb3018cc2fe3d97d49771ee93e104645abd1e1 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 19:05:12 +0200 Subject: [PATCH 309/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 1cb90aca33..5b7edd8ae7 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -268,7 +268,7 @@ Parameters: #### Performance Evaluation TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task. The maximum number or RoIs, employed for the performance evaluation was set to 800. -![Alt text](src/opendr/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png?raw=true "Title") +![Alt text](/src/opendr/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png?raw=true "Title") #### References From efb31ff1a5d21f1f7f004f7a431c74e6e6dec919 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 19:07:32 +0200 Subject: [PATCH 310/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 5b7edd8ae7..639bc736bc 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -268,7 +268,7 @@ Parameters: #### Performance Evaluation TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task. The maximum number or RoIs, employed for the performance evaluation was set to 800. -![Alt text](/src/opendr/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png?raw=true "Title") +![Alt text](opendr-eu/opendr/nms-module/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png?raw=true "Title") #### References From 20e15ebd22a23963077c098b2ab651029035b6f5 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 23 Mar 2022 19:08:25 +0200 Subject: [PATCH 311/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 639bc736bc..3e16cd6c6f 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -268,7 +268,7 @@ Parameters: #### Performance Evaluation TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task. The maximum number or RoIs, employed for the performance evaluation was set to 800. -![Alt text](opendr-eu/opendr/nms-module/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png?raw=true "Title") +![Alt text](https://raw.githubusercontent.com/opendr-eu/opendr/nms-module/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png?raw=true "Title") #### References From f59ca275c46b74757e0dc978edb56e99ead19c7a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 11:01:07 +0300 Subject: [PATCH 312/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index c4b7de4b67..22144ace8c 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -316,10 +316,6 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, if "cuda" in self.device: self.model = self.model.to(self.device) - self.model = self.model.eval() - if "cuda" in self.device: - self.model = self.model.to(self.device) - train_ids = np.arange(len(dataset_nms.src_data)) nms_results = [] pbar_eval = None From a60f98f61173127c7d0932261a796a5991d1136b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 11:23:35 +0300 Subject: [PATCH 313/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 22144ace8c..4d57e724c2 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -105,7 +105,8 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, verbose=True, nms_gt_iou=0.5, max_dt_boxes=400, datasets_folder='./datasets', use_ssd=False, lr_step=True): - dataset_nms = Dataset_NMS(path=datasets_folder, dataset_name=dataset, split='train', use_ssd=use_ssd) + dataset_nms = Dataset_NMS(path=datasets_folder, dataset_name=dataset, split='train', use_ssd=use_ssd, + device=self.device) if self.classes is None: self.classes = dataset_nms.classes self.class_ids = dataset_nms.class_ids @@ -289,7 +290,8 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, datasets_folder='./datasets', use_ssd=False): - dataset_nms = Dataset_NMS(path=datasets_folder, dataset_name=dataset, split=split, use_ssd=use_ssd) + dataset_nms = Dataset_NMS(path=datasets_folder, dataset_name=dataset, split=split, use_ssd=use_ssd, + device=self.device) if self.classes is None: self.classes = dataset_nms.classes From 8e659c4baddf7ad5b984e77edd153b61801eff0b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 12:36:45 +0300 Subject: [PATCH 314/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 6bfad909a9..570feb9b54 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -208,6 +208,9 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic pbar.close() if self.detector_type == 'default': fp_dt.close() + elif self.detector == 'SSD': + del ssd + gc.collect() with open(pkl_filename, 'wb') as handle: pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) else: @@ -310,6 +313,9 @@ def __init__(self, path=None, dataset_name=None, split=None, use_ssd=True, devic }) pbar.update(1) pbar.close() + if self.detector == 'SSD': + del ssd + gc.collect() with open(pkl_filename, 'wb') as handle: pickle.dump(self.src_data, handle, protocol=pickle.DEFAULT_PROTOCOL) else: From 54cb46ebbef43301660cdf720759037df0830bab Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 12:44:46 +0300 Subject: [PATCH 315/374] Update nms_dataset.py --- .../perception/object_detection_2d/nms/utils/nms_dataset.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py index 570feb9b54..202f7f18c5 100644 --- a/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py +++ b/src/opendr/perception/object_detection_2d/nms/utils/nms_dataset.py @@ -27,6 +27,7 @@ import numpy as np import math from tqdm import tqdm +import gc class Dataset_NMS(Dataset): From 5f89c0671afae001e05056e3f4398470aa70b94e Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 12:55:50 +0300 Subject: [PATCH 316/374] Update README.md --- .../object_detection_2d/nms/seq2seq_nms/README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 489fe71fe3..3cac84e0fd 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -4,6 +4,13 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task. The maximum number or RoIs, employed for the performance evaluation was set to 800. +| **Pretrained Model** | **Dataset** | **Detector** | **Type of Appearance-based Features** | **Pre-processing IoU Threshold** | | | | | +|:--------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|---|---|---|---| +| | | | | | | | | | +| | | | | | | | | | +| | | | | | | | | | +| | | | | | | | | | + ![Alt text](stats_pretrained.png?raw=true "Title") From c530ddf0d5210391c87e869421b24804c9576c8d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 12:59:22 +0300 Subject: [PATCH 317/374] Update README.md --- .../object_detection_2d/nms/seq2seq_nms/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 3cac84e0fd..07e7925402 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -4,12 +4,12 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task. The maximum number or RoIs, employed for the performance evaluation was set to 800. -| **Pretrained Model** | **Dataset** | **Detector** | **Type of Appearance-based Features** | **Pre-processing IoU Threshold** | | | | | -|:--------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|---|---|---|---| -| | | | | | | | | | -| | | | | | | | | | -| | | | | | | | | | -| | | | | | | | | | +| **Pretrained Model** | **Dataset** | **Detector** | **Type of Appearance-based Features** | **Pre-processing IoU Threshold** | **AP_0.5** | | | | +|:----------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|:----------:|:-:|:-:|---| +| seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | | | | | +| seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | | | | | +| seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | 0.8 | | | | | +| seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | 0.8 | | | | | ![Alt text](stats_pretrained.png?raw=true "Title") From 6a46b6eeb9b06494536fc24ba18037da3225f633 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:02:17 +0300 Subject: [PATCH 318/374] Update README.md --- .../object_detection_2d/nms/seq2seq_nms/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 07e7925402..3243da6380 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -3,13 +3,13 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). -TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task. The maximum number or RoIs, employed for the performance evaluation was set to 800. +TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task on the validation sets. The maximum number or RoIs, employed for the performance evaluation was set to 800. | **Pretrained Model** | **Dataset** | **Detector** | **Type of Appearance-based Features** | **Pre-processing IoU Threshold** | **AP_0.5** | | | | |:----------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|:----------:|:-:|:-:|---| | seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | | | | | | seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | | | | | -| seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | 0.8 | | | | | -| seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | 0.8 | | | | | +| seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | | | | | +| seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | | | | | ![Alt text](stats_pretrained.png?raw=true "Title") From b40112094c375c54892f8c3bebe960d72ee94487 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:08:10 +0300 Subject: [PATCH 319/374] Update README.md --- .../object_detection_2d/nms/seq2seq_nms/README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 3243da6380..77ae6675d8 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -4,12 +4,12 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task on the validation sets. The maximum number or RoIs, employed for the performance evaluation was set to 800. -| **Pretrained Model** | **Dataset** | **Detector** | **Type of Appearance-based Features** | **Pre-processing IoU Threshold** | **AP_0.5** | | | | -|:----------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|:----------:|:-:|:-:|---| -| seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | | | | | -| seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | | | | | -| seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | | | | | -| seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | | | | | +| **Pretrained Model** | **Dataset** | **Detector** | **Type of Appearance-based Features** | **Pre-processing IoU Threshold** | **AP@0.5 on validation set** | **AP@0.5 on test set** | +|:----------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|:----------------------------:|:----------------------:| +| seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | 80.2% | 84.3% | +| seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | +| seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% | 67.5% | +| seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | | | ![Alt text](stats_pretrained.png?raw=true "Title") From eebf28f521a68611fe7da401b17c855419246868 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:19:08 +0300 Subject: [PATCH 320/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 77ae6675d8..568c5cd3e8 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -8,9 +8,10 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete |:----------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|:----------------------------:|:----------------------:| | seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | 80.2% | 84.3% | | seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | -| seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% | 67.5% | +| seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1%* | 67.5%** | | seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | | | - +* +** ![Alt text](stats_pretrained.png?raw=true "Title") From bafc52b6fa32c1f3636ca4338eb6711816b26246 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:20:12 +0300 Subject: [PATCH 321/374] Update README.md --- .../nms/seq2seq_nms/README.md | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 568c5cd3e8..7964c38aad 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -10,8 +10,28 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete | seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | | seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1%* | 67.5%** | | seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | | | -* -** +Seq2Seq-NMS +====== + +This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). + +TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task on the validation sets. The maximum number or RoIs, employed for the performance evaluation was set to 800. +| **Pretrained Model** | **Dataset** | **Detector** | **Type of Appearance-based Features** | **Pre-processing IoU Threshold** | **AP@0.5 on validation set** | **AP@0.5 on test set** | +|:----------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|:----------------------------:|:----------------------:| +| seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | 80.2% | 84.3% | +| seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | +| seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% * | 67.5% ** | +| seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | | | +* The minival set was used as validation set. +** The +![Alt text](stats_pretrained.png?raw=true "Title") + + + + +[1] Neural Attention-driven Non-Maximum Suppression for Person Detection, +[ArXiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). + ![Alt text](stats_pretrained.png?raw=true "Title") From 6e5976667eea87da16b3aaa4d5f92d0988bb0077 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:21:05 +0300 Subject: [PATCH 322/374] Update README.md --- .../nms/seq2seq_nms/README.md | 21 +++---------------- 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 7964c38aad..3a6fedccff 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -1,18 +1,3 @@ -Seq2Seq-NMS -====== - -This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). - -TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task on the validation sets. The maximum number or RoIs, employed for the performance evaluation was set to 800. -| **Pretrained Model** | **Dataset** | **Detector** | **Type of Appearance-based Features** | **Pre-processing IoU Threshold** | **AP@0.5 on validation set** | **AP@0.5 on test set** | -|:----------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|:----------------------------:|:----------------------:| -| seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | 80.2% | 84.3% | -| seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | -| seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1%* | 67.5%** | -| seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | | | -Seq2Seq-NMS -====== - This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task on the validation sets. The maximum number or RoIs, employed for the performance evaluation was set to 800. @@ -20,10 +5,10 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete |:----------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|:----------------------------:|:----------------------:| | seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | 80.2% | 84.3% | | seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | -| seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% * | 67.5% ** | +| seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% \* | 67.5% \*\* | | seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | | | -* The minival set was used as validation set. -** The +\* The minival set was used as validation set. +\*\* The ![Alt text](stats_pretrained.png?raw=true "Title") From 74cb1a59aa3208cde6a993292d76e6c36afb7279 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:21:22 +0300 Subject: [PATCH 323/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 3a6fedccff..deb82f498e 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -7,6 +7,7 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete | seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | | seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% \* | 67.5% \*\* | | seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | | | + \* The minival set was used as validation set. \*\* The ![Alt text](stats_pretrained.png?raw=true "Title") From ed1983e17815f33472d1539f33add13fae2823c7 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:21:31 +0300 Subject: [PATCH 324/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index deb82f498e..e3db613c12 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -9,6 +9,7 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete | seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | | | \* The minival set was used as validation set. + \*\* The ![Alt text](stats_pretrained.png?raw=true "Title") From b1b8dd39b5471b83a1851425ed71b17534723778 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:22:08 +0300 Subject: [PATCH 325/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index e3db613c12..bfa87af569 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -10,7 +10,7 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete \* The minival set was used as validation set. -\*\* The +\*\* The minitest set was used as test set. ![Alt text](stats_pretrained.png?raw=true "Title") From 2ebb780a4f7b4554d5d1896b843d4a825388b943 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:22:45 +0300 Subject: [PATCH 326/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index bfa87af569..ca0d14c3a9 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -1,3 +1,6 @@ +Seq2Seq-NMS +====== + This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task on the validation sets. The maximum number or RoIs, employed for the performance evaluation was set to 800. From f22ce40900e7e2f1261c9a02d006ee9d1e3230b0 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:23:37 +0300 Subject: [PATCH 327/374] Update README.md --- .../object_detection_2d/nms/seq2seq_nms/README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index ca0d14c3a9..3ae48a50f9 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -3,6 +3,10 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). + +[1] Neural Attention-driven Non-Maximum Suppression for Person Detection, +[ArXiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). + TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task on the validation sets. The maximum number or RoIs, employed for the performance evaluation was set to 800. | **Pretrained Model** | **Dataset** | **Detector** | **Type of Appearance-based Features** | **Pre-processing IoU Threshold** | **AP@0.5 on validation set** | **AP@0.5 on test set** | |:----------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|:----------------------------:|:----------------------:| @@ -14,14 +18,8 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete \* The minival set was used as validation set. \*\* The minitest set was used as test set. -![Alt text](stats_pretrained.png?raw=true "Title") - - -[1] Neural Attention-driven Non-Maximum Suppression for Person Detection, -[ArXiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). - ![Alt text](stats_pretrained.png?raw=true "Title") From 2b0507d1f6b1ad08ae596b5e97ac54c5dcf1b916 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:24:03 +0300 Subject: [PATCH 328/374] Update README.md --- .../object_detection_2d/nms/seq2seq_nms/README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 3ae48a50f9..99a2bc6e90 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -3,10 +3,6 @@ Seq2Seq-NMS This folder contains an implementation of Seq2Seq-NMS [[1]](#seq2seq_nms-1). - -[1] Neural Attention-driven Non-Maximum Suppression for Person Detection, -[ArXiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). - TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task on the validation sets. The maximum number or RoIs, employed for the performance evaluation was set to 800. | **Pretrained Model** | **Dataset** | **Detector** | **Type of Appearance-based Features** | **Pre-processing IoU Threshold** | **AP@0.5 on validation set** | **AP@0.5 on test set** | |:----------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|:----------------------------:|:----------------------:| @@ -20,10 +16,5 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete \*\* The minitest set was used as test set. -![Alt text](stats_pretrained.png?raw=true "Title") - - - - [1] Neural Attention-driven Non-Maximum Suppression for Person Detection, [ArXiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). From c201686ce9b8aa75a56aa41ecf44f48b4e92918e Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:24:39 +0300 Subject: [PATCH 329/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 99a2bc6e90..23dbd5cfb1 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -11,10 +11,8 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete | seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% \* | 67.5% \*\* | | seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | | | -\* The minival set was used as validation set. - +\* The minival set was used as validation set.
\*\* The minitest set was used as test set. - [1] Neural Attention-driven Non-Maximum Suppression for Person Detection, [ArXiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). From 1342d5b34952d5174648493bdca7d89d36b3ec4b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:25:21 +0300 Subject: [PATCH 330/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 23dbd5cfb1..205c53ca52 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -9,7 +9,7 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete | seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | 80.2% | 84.3% | | seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | | seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% \* | 67.5% \*\* | -| seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | | | +| seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | 41.9% \* | | \* The minival set was used as validation set.
\*\* The minitest set was used as test set. From 85ba13355047f769c713347af645c16ec733b7c2 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:25:43 +0300 Subject: [PATCH 331/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 205c53ca52..47372ddb77 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -9,7 +9,7 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete | seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | 80.2% | 84.3% | | seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | | seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% \* | 67.5% \*\* | -| seq2seq_coco_frcn_fmod | COCO | SSD | FMoD | - | 41.9% \* | | +| seq2seq_coco_ssd_fmod | COCO | SSD | FMoD | - | 41.9% \* | | \* The minival set was used as validation set.
\*\* The minitest set was used as test set. From 02800d68829e80d4d4796710a518aacaf2a6af8d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:27:42 +0300 Subject: [PATCH 332/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../reference/object-detection-2d-nms-seq2seq_nms.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 3e16cd6c6f..af24c50ef5 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -267,8 +267,16 @@ Parameters: #### Performance Evaluation -TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task. The maximum number or RoIs, employed for the performance evaluation was set to 800. -![Alt text](https://raw.githubusercontent.com/opendr-eu/opendr/nms-module/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png?raw=true "Title") +TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task on the validation sets. The maximum number or RoIs, employed for the performance evaluation was set to 800. +| **Pretrained Model** | **Dataset** | **Detector** | **Type of Appearance-based Features** | **Pre-processing IoU Threshold** | **AP@0.5 on validation set** | **AP@0.5 on test set** | +|:----------------------:|:-----------:|:------------:|:-------------------------------------:|:--------------------------------:|:----------------------------:|:----------------------:| +| seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | 80.2% | 84.3% | +| seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | +| seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% \* | 67.5% \*\* | +| seq2seq_coco_ssd_fmod | COCO | SSD | FMoD | - | 41.9% \* | | + +\* The minival set was used as validation set.
+\*\* The minitest set was used as test set. #### References From b3e8b0817bc46a294d7cca678ae460b2a85c6227 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:29:01 +0300 Subject: [PATCH 333/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 47372ddb77..27e6db66fe 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -14,5 +14,4 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete \* The minival set was used as validation set.
\*\* The minitest set was used as test set. -[1] Neural Attention-driven Non-Maximum Suppression for Person Detection, -[ArXiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). +[1] Neural Attention-driven Non-Maximum Suppression for Person Detection, [ArXiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). From b814c11be6a5eb56f8fc6cb74d9de19a233889cd Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:29:50 +0300 Subject: [PATCH 334/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 27e6db66fe..657600e4fd 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -14,4 +14,4 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete \* The minival set was used as validation set.
\*\* The minitest set was used as test set. -[1] Neural Attention-driven Non-Maximum Suppression for Person Detection, [ArXiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). +[1] Neural Attention-driven Non-Maximum Suppression for Person Detection, [TechRxiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). From ae277802d37febf3048604e8fdb96fd7081e3fae Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Mon, 28 Mar 2022 13:29:52 +0300 Subject: [PATCH 335/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index af24c50ef5..906e6a0b31 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -280,5 +280,4 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete #### References -[1] Neural Attention-driven Non-Maximum Suppression for Person Detection, -[TechRxiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). +[1] Neural Attention-driven Non-Maximum Suppression for Person Detection, [TechRxiv](https://www.techrxiv.org/articles/preprint/Neural_Attention-driven_Non-Maximum_Suppression_for_Person_Detection/16940275). From aca93b16440b9b39926307c0e7d07277bbd3db9f Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:36:59 +0300 Subject: [PATCH 336/374] Update projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- .../opendr_ws/src/perception/scripts/object_detection_2d_ssd.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py index 26c039c21a..f0dd7ca1d3 100755 --- a/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py +++ b/projects/opendr_ws/src/perception/scripts/object_detection_2d_ssd.py @@ -22,7 +22,7 @@ from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes -from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner, SoftNMS, FastNMS, ClusterNMS +from opendr.perception.object_detection_2d import Seq2SeqNMSLearner, SoftNMS, FastNMS, ClusterNMS class ObjectDetectionSSDNode: From 82c41755fa6956f1954c0618a425c2dc3b62fd08 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:37:08 +0300 Subject: [PATCH 337/374] Update projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- .../object_detection_2d/nms/fast_nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py index d277520567..5e0a5b48fa 100644 --- a/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/fast_nms/inference_demo.py @@ -13,7 +13,7 @@ # limitations under the License. -from opendr.perception.object_detection_2d.nms import FastNMS +from opendr.perception.object_detection_2d import FastNMS from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes From 2131ea9e1fe26ef33951cd33964b856e202bf463 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:37:15 +0300 Subject: [PATCH 338/374] Update projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- .../perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py index db7c6f90e8..31a98d73a2 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner +from opendr.perception.object_detection_2d import Seq2SeqNMSLearner import os import argparse OPENDR_HOME = os.environ['OPENDR_HOME'] From aac0af08372761a1df6c367e3e2b5fbc95fee3c8 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:37:22 +0300 Subject: [PATCH 339/374] Update projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- .../object_detection_2d/nms/seq2seq-nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py index 3fe6b568a5..a12923fe51 100755 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/inference_demo.py @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner +from opendr.perception.object_detection_2d import Seq2SeqNMSLearner from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes from opendr.engine.data import Image From 751dcc712a7f59161de9b5d843e26d034cc1e756 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:37:28 +0300 Subject: [PATCH 340/374] Update projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- .../object_detection_2d/nms/seq2seq-nms/train_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py index 6523ee8c4d..4facf2696b 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/train_demo.py @@ -13,7 +13,7 @@ # limitations under the License. -from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner +from opendr.perception.object_detection_2d import Seq2SeqNMSLearner import os import argparse OPENDR_HOME = os.environ['OPENDR_HOME'] From 591f6d4519038269725e4e15a9d1c114a830f91d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:37:35 +0300 Subject: [PATCH 341/374] Update projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- .../object_detection_2d/nms/soft_nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py index c79e885b2c..c05ff4c7c2 100644 --- a/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/soft_nms/inference_demo.py @@ -13,7 +13,7 @@ # limitations under the License. -from opendr.perception.object_detection_2d.nms import SoftNMS +from opendr.perception.object_detection_2d import SoftNMS from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes From c57be6b4f8d36d039a391279ba4bd42978781d11 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:37:46 +0300 Subject: [PATCH 342/374] Update tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- .../object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py index f032cc5210..41b0f29155 100644 --- a/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py +++ b/tests/sources/tools/perception/object_detection_2d/nms/seq2seq_nms/test_seq2seq_nms.py @@ -17,7 +17,7 @@ import shutil import os import numpy as np -from opendr.perception.object_detection_2d.nms import Seq2SeqNMSLearner +from opendr.perception.object_detection_2d import Seq2SeqNMSLearner from opendr.perception.object_detection_2d.nms.utils.nms_dataset import Dataset_NMS from opendr.engine.data import Image From a3c03b50e66810d2ed533394fc088ccb49a02a6a Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 29 Mar 2022 12:39:18 +0300 Subject: [PATCH 343/374] Update __init__.py --- src/opendr/perception/object_detection_2d/__init__.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/__init__.py b/src/opendr/perception/object_detection_2d/__init__.py index 61428cb1bd..9fac6ba424 100644 --- a/src/opendr/perception/object_detection_2d/__init__.py +++ b/src/opendr/perception/object_detection_2d/__init__.py @@ -11,6 +11,11 @@ from opendr.perception.object_detection_2d.utils.vis_utils import draw_bounding_boxes +from opendr.perception.object_detection_2d.nms.cluster_nms.cluster_nms import ClusterNMS +from opendr.perception.object_detection_2d.nms.fast_nms.fast_nms import FastNMS +from opendr.perception.object_detection_2d.nms.soft_nms.soft_nms import SoftNMS +from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner + __all__ = ['CenterNetDetectorLearner', 'DetrLearner', 'GemLearner', 'RetinaFaceLearner', 'SingleShotDetectorLearner', 'YOLOv3DetectorLearner', 'WiderPersonDataset', 'WiderFaceDataset', - 'transforms', 'draw_bounding_boxes'] + 'transforms', 'draw_bounding_boxes', 'ClusterNMS', 'FastNMS', 'SoftNMS', 'Seq2SeqNMSLearner'] From 4199b334de30e8d6bc07cb2da007d4c63d2f8815 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 29 Mar 2022 13:28:38 +0300 Subject: [PATCH 344/374] Update tests_suite.yml --- .github/workflows/tests_suite.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/tests_suite.yml b/.github/workflows/tests_suite.yml index 0fdefc7fec..5024003635 100644 --- a/.github/workflows/tests_suite.yml +++ b/.github/workflows/tests_suite.yml @@ -77,6 +77,7 @@ jobs: - perception/object_detection_2d/ssd - perception/object_detection_2d/yolov3 - perception/object_detection_2d/retinaface + - perception/object_detection_2d/nms - simulation/human_model_generation - perception/facial_expression_recognition - control/single_demo_grasp @@ -179,6 +180,7 @@ jobs: - perception/object_detection_2d/ssd - perception/object_detection_2d/yolov3 - perception/object_detection_2d/retinaface + - perception/object_detection_2d/nms - perception/facial_expression_recognition # - perception/object_detection_3d # - control/mobile_manipulation @@ -248,6 +250,7 @@ jobs: - perception/object_detection_2d/ssd - perception/object_detection_2d/yolov3 - perception/object_detection_2d/retinaface + - perception/object_detection_2d/nms - perception/facial_expression_recognition # - perception/object_detection_3d # - control/mobile_manipulation @@ -323,6 +326,7 @@ jobs: - perception/object_detection_2d/ssd - perception/object_detection_2d/yolov3 - perception/object_detection_2d/retinaface + - perception/object_detection_2d/nms - perception/facial_expression_recognition - perception/object_detection_3d - control/mobile_manipulation From 2edb7dde874baeac6c4c2846c94f81b588dc5252 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 29 Mar 2022 13:29:42 +0300 Subject: [PATCH 345/374] Update tests_suite_develop.yml --- .github/workflows/tests_suite_develop.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/tests_suite_develop.yml b/.github/workflows/tests_suite_develop.yml index 4f6ddaaaa3..954edf4f64 100644 --- a/.github/workflows/tests_suite_develop.yml +++ b/.github/workflows/tests_suite_develop.yml @@ -76,6 +76,7 @@ jobs: - perception/object_detection_2d/ssd - perception/object_detection_2d/yolov3 - perception/object_detection_2d/retinaface + - perception/object_detection_2d/nms - simulation/human_model_generation - perception/facial_expression_recognition - control/single_demo_grasp @@ -179,6 +180,7 @@ jobs: - perception/object_detection_2d/ssd - perception/object_detection_2d/yolov3 - perception/object_detection_2d/retinaface + - perception/object_detection_2d/nms - perception/facial_expression_recognition # - perception/object_detection_3d # - control/mobile_manipulation @@ -249,6 +251,7 @@ jobs: - perception/object_detection_2d/ssd - perception/object_detection_2d/yolov3 - perception/object_detection_2d/retinaface + - perception/object_detection_2d/nms - perception/facial_expression_recognition # - perception/object_detection_3d # - control/mobile_manipulation @@ -325,6 +328,7 @@ jobs: - perception/object_detection_2d/ssd - perception/object_detection_2d/yolov3 - perception/object_detection_2d/retinaface + - perception/object_detection_2d/nms - perception/facial_expression_recognition - perception/object_detection_3d - control/mobile_manipulation From 8c9be11be499d993a24e1ac69ca832f1690c540d Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Tue, 29 Mar 2022 13:30:04 +0300 Subject: [PATCH 346/374] Update test_packages.yml --- .github/workflows/test_packages.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/test_packages.yml b/.github/workflows/test_packages.yml index 7fabc5b512..29c2511dc6 100644 --- a/.github/workflows/test_packages.yml +++ b/.github/workflows/test_packages.yml @@ -45,6 +45,7 @@ jobs: - perception/object_detection_2d/ssd - perception/object_detection_2d/yolov3 - perception/object_detection_2d/retinaface + - perception/object_detection_2d/nms - perception/facial_expression_recognition # - perception/object_detection_3d # - control/mobile_manipulation @@ -93,6 +94,7 @@ jobs: - perception/object_detection_2d/ssd - perception/object_detection_2d/yolov3 - perception/object_detection_2d/retinaface + - perception/object_detection_2d/nms - perception/facial_expression_recognition - perception/object_detection_3d - control/mobile_manipulation From dd7430f20c39cb2b675f5a4b4cd796067dd421cf Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:11:03 +0300 Subject: [PATCH 347/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 906e6a0b31..921b487059 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -273,7 +273,7 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete | seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | 80.2% | 84.3% | | seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | | seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% \* | 67.5% \*\* | -| seq2seq_coco_ssd_fmod | COCO | SSD | FMoD | - | 41.9% \* | | +| seq2seq_coco_ssd_fmod | COCO | SSD | FMoD | - | 41.8% \* | 42.4\% | \* The minival set was used as validation set.
\*\* The minitest set was used as test set. From 4c3c2a29afc08a43ab2271a152063fc12c5e3ca5 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 30 Mar 2022 22:11:30 +0300 Subject: [PATCH 348/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 921b487059..99f67d0594 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -273,7 +273,7 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete | seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | 80.2% | 84.3% | | seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | | seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% \* | 67.5% \*\* | -| seq2seq_coco_ssd_fmod | COCO | SSD | FMoD | - | 41.8% \* | 42.4\% | +| seq2seq_coco_ssd_fmod | COCO | SSD | FMoD | - | 41.8% \* | 42.4% ** | \* The minival set was used as validation set.
\*\* The minitest set was used as test set. From 9a245799312623074e79dbbfdeb434684d57b3c9 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 30 Mar 2022 23:24:27 +0300 Subject: [PATCH 349/374] Update README.md --- .../perception/object_detection_2d/nms/seq2seq_nms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md index 657600e4fd..4e03fce80c 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/README.md @@ -9,7 +9,7 @@ TABLE-1: Average Precision (AP) achieved by pretrained models on the person dete | seq2seq_pets_jpd_fmod | PETS | JPD | FMoD | 0.8 | 80.2% | 84.3% | | seq2seq_pets_ssd_fmod | PETS | SSD | FMoD | 0.8 | 77.4% | 79.1% | | seq2seq_coco_frcn_fmod | COCO | FRCN | FMoD | - | 68.1% \* | 67.5% \*\* | -| seq2seq_coco_ssd_fmod | COCO | SSD | FMoD | - | 41.9% \* | | +| seq2seq_coco_ssd_fmod | COCO | SSD | FMoD | - | 41.8% \* | 42.4% ** | \* The minival set was used as validation set.
\*\* The minitest set was used as test set. From 2d75297d37a477b1c6def150eeb782a20f3a758b Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Wed, 30 Mar 2022 23:25:17 +0300 Subject: [PATCH 350/374] Update projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py Co-authored-by: ad-daniel <44834743+ad-daniel@users.noreply.github.com> --- .../object_detection_2d/nms/cluster_nms/inference_demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py index 25cefa627c..e653f5820c 100644 --- a/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py +++ b/projects/perception/object_detection_2d/nms/cluster_nms/inference_demo.py @@ -13,7 +13,7 @@ # limitations under the License. -from opendr.perception.object_detection_2d.nms import ClusterNMS +from opendr.perception.object_detection_2d import ClusterNMS from opendr.engine.data import Image from opendr.perception.object_detection_2d import SingleShotDetectorLearner from opendr.perception.object_detection_2d import draw_bounding_boxes From a4a416e0ff03d8bb0fcf9b0a1dfcdc2ca42c2472 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 31 Mar 2022 11:13:39 +0300 Subject: [PATCH 351/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 4d57e724c2..26532d831d 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -287,7 +287,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, file_writer.close() return training_dict - def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, + def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, threshold=None, datasets_folder='./datasets', use_ssd=False): dataset_nms = Dataset_NMS(path=datasets_folder, dataset_name=dataset, split=split, use_ssd=use_ssd, @@ -374,6 +374,11 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, preds = self.model(q_geom_feats=q_geom_feats, k_geom_feats=k_geom_feats, msk=msk, app_feats=app_feats) bboxes = dt_boxes.cpu().numpy().astype('float64') + preds = preds.cpu().detach() + if threshold is not None: + ids = (preds > threshold) + preds = preds[ids] + bboxes = bboxes[ids.numpy().squeeze(-1), :] for j in range(len(preds)): nms_results.append({ 'image_id': dataset_nms.src_data[sample_id]['id'], From 244b3ac5527e35f09a96d6ac5ee9d2a717622d30 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 31 Mar 2022 11:48:28 +0300 Subject: [PATCH 352/374] Update eval_demo.py --- .../object_detection_2d/nms/seq2seq-nms/eval_demo.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py index 31a98d73a2..b295cae679 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py @@ -35,6 +35,7 @@ default=os.path.join(OPENDR_HOME, 'projects/perception/object_detection_2d/nms/seq2seq-nms/datasets')) parser.add_argument("--use_ssd", help="Train using SSD as detector", type=bool, default=False) +parser.add_argument("--post_thres", help="Confidence threshold, used for RoI selection after seq2seq-nms rescoring", type=float, default=0.0) args = parser.parse_args() tmp_path = os.path.join(OPENDR_HOME, 'projects/perception/object_detection_2d/nms/seq2seq-nms/tmp') @@ -44,4 +45,4 @@ seq2SeqNMSLearner.download(model_name=args.pretrained_model, path=tmp_path) seq2SeqNMSLearner.load(os.path.join(tmp_path, args.pretrained_model), verbose=True) seq2SeqNMSLearner.eval(dataset=args.dataset, use_ssd=args.use_ssd, split=args.split, max_dt_boxes=args.max_dt_boxes, - datasets_folder=args.data_root) + datasets_folder=args.data_root, threshold=args.post_thres) From 3f6a5db3552cd55a6eb2c15e69d99404cbd75799 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 31 Mar 2022 11:49:09 +0300 Subject: [PATCH 353/374] Update seq2seq_nms_learner.py --- .../nms/seq2seq_nms/seq2seq_nms_learner.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py index 26532d831d..27a16f75d1 100644 --- a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py +++ b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/seq2seq_nms_learner.py @@ -287,7 +287,7 @@ def fit(self, dataset, logging_path='', logging_flush_secs=30, silent=True, file_writer.close() return training_dict - def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, threshold=None, + def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, threshold=0.0, datasets_folder='./datasets', use_ssd=False): dataset_nms = Dataset_NMS(path=datasets_folder, dataset_name=dataset, split=split, use_ssd=use_ssd, @@ -375,7 +375,7 @@ def eval(self, dataset, split='test', verbose=True, max_dt_boxes=400, threshold= app_feats=app_feats) bboxes = dt_boxes.cpu().numpy().astype('float64') preds = preds.cpu().detach() - if threshold is not None: + if threshold > 0.0: ids = (preds > threshold) preds = preds[ids] bboxes = bboxes[ids.numpy().squeeze(-1), :] From 1633ec07f8dd208fff5e2aaac4b165917abaa1e7 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 31 Mar 2022 12:18:34 +0300 Subject: [PATCH 354/374] Update object-detection-2d-nms-seq2seq_nms.md --- .../object-detection-2d-nms-seq2seq_nms.md | 40 ++++++++++++++----- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 99f67d0594..0510561ff1 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -230,15 +230,15 @@ Parameters: import os OPENDR_HOME = os.environ['OPENDR_HOME'] + temp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/tmp' + datasets_folder = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/datasets' + seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering=0.8, app_feats='fmod', checkpoint_after_iter=1, - temp_path=OPENDR_HOME + '/src/opendr/perception/' - 'object_detection_2d/nms/seq2seq_nms/temp', - epochs=8) - seq2SeqNMSLearner.fit(dataset='PETS', use_ssd=False, - datasets_folder=OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/datasets', - logging_path='./logs_pets_exp1', silent=False, verbose=True, nms_gt_iou=0.50, - max_dt_boxes=500) + temp_path=temp_path, epochs=8) + seq2SeqNMSLearner.fit(dataset='PETS', use_ssd=False, datasets_folder=datasets_folder, + logging_path=os.path.join(temp_path, 'logs'), silent=False, + verbose=True, nms_gt_iou=0.50, max_dt_boxes=500) ``` * **Inference and result drawing example on a test .jpg image using OpenCV.** @@ -250,11 +250,13 @@ Parameters: from opendr.perception.object_detection_2d import draw_bounding_boxes import os OPENDR_HOME = os.environ['OPENDR_HOME'] + temp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/tmp' seq2SeqNMSLearner = Seq2SeqNMSLearner(fmod_map_type='EDGEMAP', iou_filtering = 0.8, - app_feats='fmod', device='cpu') - seq2SeqNMSLearner.load(OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/pets_exp0/' - 'checkpoint_epoch_7', verbose=True) + app_feats='fmod', device='cpu', + temp_path=temp_path) + seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd', path=temp_path) + seq2SeqNMSLearner.load(os.path.join(temp_path, seq2seq_pets_jpd), verbose=True) ssd = SingleShotDetectorLearner(device='cuda') ssd.download(".", mode="pretrained") ssd.load("./ssd_default_person", verbose=True) @@ -265,6 +267,24 @@ Parameters: draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) ``` + * **Evaluation of pretrained model on PETS dataset.** + + ```python + from opendr.perception.object_detection_2d import Seq2SeqNMSLearner + import os + OPENDR_HOME = os.environ['OPENDR_HOME'] + + datasets_folder = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/datasets' + temp_path = OPENDR_HOME + '/src/opendr/perception/object_detection_2d/nms/tmp' + + seq2SeqNMSLearner = Seq2SeqNMSLearner(iou_filtering=0.8, app_feats='fmod', + temp_path=temp_path, device='cuda') + seq2SeqNMSLearner.download(model_name='seq2seq_pets_jpd', path=temp_path) + seq2SeqNMSLearner.load(os.path.join(temp_path, seq2seq_pets_jpd), verbose=True) + seq2SeqNMSLearner.eval(dataset='PETS', split='test', max_dt_boxes=800, + datasets_folder=datasets_folder, use_ssd=False, threshold=0.0) + ``` + #### Performance Evaluation TABLE-1: Average Precision (AP) achieved by pretrained models on the person detection task on the validation sets. The maximum number or RoIs, employed for the performance evaluation was set to 800. From ff94249227dd733c91b8fac5095e5489c28613d7 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 31 Mar 2022 12:22:38 +0300 Subject: [PATCH 355/374] Update object-detection-2d-nms-seq2seq_nms.md --- docs/reference/object-detection-2d-nms-seq2seq_nms.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/reference/object-detection-2d-nms-seq2seq_nms.md b/docs/reference/object-detection-2d-nms-seq2seq_nms.md index 0510561ff1..42db243fc5 100644 --- a/docs/reference/object-detection-2d-nms-seq2seq_nms.md +++ b/docs/reference/object-detection-2d-nms-seq2seq_nms.md @@ -100,6 +100,8 @@ Parameters: If True, enables maximum verbosity. - **max_dt_boxes**: *int, default=500*\ Specifies the maximum number of RoIs provided to seq2Seq-nms model as input. +- **threshold**: *float, default=0.0*\ + Specifies the confidence threshold, used for RoI selection after seq2seq-nms rescoring. - **datasets_folder**: *str, default='./datasets'*\ Specifies the path to the folder where the datasets are stored. - **use_ssd**: *bool, default=False*\ @@ -267,7 +269,7 @@ Parameters: draw_bounding_boxes(img.opencv(), boxes, class_names=ssd.classes, show=True) ``` - * **Evaluation of pretrained model on PETS dataset.** +* **Evaluation of pretrained model on PETS dataset.** ```python from opendr.perception.object_detection_2d import Seq2SeqNMSLearner From e72826247ca386d9fc4fe0117f805e16e993117e Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Thu, 31 Mar 2022 12:34:09 +0300 Subject: [PATCH 356/374] Update eval_demo.py --- .../object_detection_2d/nms/seq2seq-nms/eval_demo.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py index b295cae679..e241be9487 100644 --- a/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py +++ b/projects/perception/object_detection_2d/nms/seq2seq-nms/eval_demo.py @@ -35,7 +35,8 @@ default=os.path.join(OPENDR_HOME, 'projects/perception/object_detection_2d/nms/seq2seq-nms/datasets')) parser.add_argument("--use_ssd", help="Train using SSD as detector", type=bool, default=False) -parser.add_argument("--post_thres", help="Confidence threshold, used for RoI selection after seq2seq-nms rescoring", type=float, default=0.0) +parser.add_argument("--post_thres", help="Confidence threshold, used for RoI selection after seq2seq-nms rescoring", + type=float, default=0.0) args = parser.parse_args() tmp_path = os.path.join(OPENDR_HOME, 'projects/perception/object_detection_2d/nms/seq2seq-nms/tmp') From 737b4b55f1cb0d30ff479107d654ed99146b1baf Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:26:41 +0300 Subject: [PATCH 357/374] Update __init__.py --- src/opendr/perception/object_detection_2d/nms/__init__.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/opendr/perception/object_detection_2d/nms/__init__.py b/src/opendr/perception/object_detection_2d/nms/__init__.py index 60903cd475..8b13789179 100644 --- a/src/opendr/perception/object_detection_2d/nms/__init__.py +++ b/src/opendr/perception/object_detection_2d/nms/__init__.py @@ -1,6 +1 @@ -from opendr.perception.object_detection_2d.nms.cluster_nms.cluster_nms import ClusterNMS -from opendr.perception.object_detection_2d.nms.fast_nms.fast_nms import FastNMS -from opendr.perception.object_detection_2d.nms.soft_nms.soft_nms import SoftNMS -from opendr.perception.object_detection_2d.nms.seq2seq_nms.seq2seq_nms_learner import Seq2SeqNMSLearner -__all__ = ['ClusterNMS', 'FastNMS', 'SoftNMS', 'Seq2SeqNMSLearner'] From 595eb070328dba0ece3b81124059fc21767d5cc6 Mon Sep 17 00:00:00 2001 From: charsyme <63857415+charsyme@users.noreply.github.com> Date: Fri, 1 Apr 2022 11:26:58 +0300 Subject: [PATCH 358/374] Delete stats_pretrained.png --- .../nms/seq2seq_nms/stats_pretrained.png | Bin 196810 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/opendr/perception/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png diff --git a/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png b/src/opendr/perception/object_detection_2d/nms/seq2seq_nms/stats_pretrained.png deleted file mode 100644 index 5e6f70ee9a8dd586522a5b584240cf2aa371804b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 196810 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

;T`0?0@jkITpwLK|M->l1os< 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∈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