def parse_param(self, roi_settings): """ Parse parameters to extract roi info. """ if lab_tools.is_lab_format(roi_settings): rois = roi_settings["annotations"] elif "roi" in roi_settings.keys(): rois = roi_settings["roi"] else: self.logger.warning("No valid ROI found") return False self.rois = [] for roi in rois: try: bb = tinycv.Rect([ max(0, roi['top']), roi['bottom'], max(0, roi['left']), roi['right'] ]) if bb.b == -1 or bb.r == -1: self.rois.append(None) else: self.rois.append(bb) except BaseException: return False return True
def __init__(self, dyda_config_path='', param=None): super(YTECDataConverter, self).__init__( dyda_config_path=dyda_config_path ) class_name = self.__class__.__name__ self.set_param(class_name, param=param) self.results = {} self.rect = tinycv.Rect()
def parse_param(self): """ Parse parameters to extract roi info. """ if self.use_external_meta: if isinstance(self.external_metadata, list) \ and len(self.external_metadata) == 1: if 'roi' not in self.external_metadata[0].keys(): self.logger.warning( "No roi given and skip roi determinator") return True rois = self.external_metadata[0]['roi'] elif isinstance(self.external_metadata, dict): if 'roi' not in self.external_metadata.keys(): self.logger.warning( "No roi given and skip roi determinator") return True rois = self.external_metadata['roi'] else: self.logger.error("Wrong external_metadata type") self.terminate_flag = True return False self.rois = [] for roi in rois: bb = tinycv.Rect( [roi['top'], roi['bottom'], roi['left'], roi['right']]) if bb.r == -1 or bb.l == -1 or \ bb.t == -1 or bb.b == -1: return True bb.th = roi['overlap_threshold'] self.rois.append(bb) else: self.rois = [] bb = tinycv.Rect([ self.param['top'], self.param['bottom'], self.param['left'], self.param['right'] ]) if bb.r == -1 or bb.l == -1 or \ bb.t == -1 or bb.b == -1: return True bb.th = self.param['threshold'] self.rois.append(bb) return False
def __init__(self, dyda_config_path='', param=None): """ Initialization function of dyda component. """ super(CropBoxProcessor, self).__init__(dyda_config_path=dyda_config_path) class_name = self.__class__.__name__ self.set_param(class_name, param=param) self.roi = tinycv.Rect([ self.param['top'], self.param['bottom'], self.param['left'], self.param['right'] ])
def crop_bb(self, data): """ Crop bounding boxes to roi given by config. """ # check if roi exceeds image size width = data['size']['width'] height = data['size']['height'] if not (isinstance(width, int) and isinstance(height, int)): self.logger.warning("Can not check boundary " "since no image size is given.") else: if self.roi.r >= width or self.roi.b >= height: self.terminate_flag = True self.logger.error("Roi exceeds image size.") data['size']['width'] = self.roi.w data['size']['height'] = self.roi.h # crop bounding boxes for idx in range(len(data['annotations']) - 1, -1, -1): obj = data['annotations'][idx] bb = tinycv.Rect( [obj['top'], obj['bottom'], obj['left'], obj['right']]) # check if object in roi overlap_ratio = lab_tools.calculate_overlap_ratio( [self.roi.t, self.roi.b, self.roi.l, self.roi.r], [bb.t, bb.b, bb.l, bb.r], denominator_type='area_2') if overlap_ratio < self.param['overlap_threshold']: data['annotations'].pop(idx) continue # update bounding box of object obj['top'] = tinycv.check_boundary_limit(bb.t - self.roi.t, self.roi.h) obj['left'] = tinycv.check_boundary_limit(bb.l - self.roi.l, self.roi.w) obj['bottom'] = tinycv.check_boundary_limit( bb.b - self.roi.t, self.roi.h) obj['right'] = tinycv.check_boundary_limit(bb.r - self.roi.l, self.roi.w) return (data)
def main_process(self): """ Main function of dyda component. """ self.reset_output() input_data = self.uniform_input(self.input_data) for data in input_data: img_h = data['size']['height'] img_w = data['size']['width'] for anno in data['annotations']: bb = tinycv.Rect( [anno['top'], anno['bottom'], anno['left'], anno['right']]) self.get_extension(bb.h, bb.w) anno['top'] = max(0, bb.t - self.top_extension) anno['bottom'] = min(img_h, bb.b + self.bottom_extension) anno['left'] = max(0, bb.l - self.left_extension) anno['right'] = min(img_w, bb.r + self.right_extension) self.results.append(data) self.uniform_output()
def transform_anno(self, data, trans_info): """ Transform annotations. """ for anno in data['annotations']: bb = tinycv.Rect( [anno['top'], anno['bottom'], anno['left'], anno['right']]) lt = self.transform_point(bb.l, bb.t, trans_info) lb = self.transform_point(bb.l, bb.b, trans_info) rt = self.transform_point(bb.r, bb.t, trans_info) rb = self.transform_point(bb.r, bb.b, trans_info) anno['left'] = min(max(min([lt[0], lb[0], rt[0], rb[0]]), 0), trans_info['size']['width'] - 1) anno['right'] = min(max(max([lt[0], lb[0], rt[0], rb[0]]), 1), trans_info['size']['width']) anno['top'] = min(max(min([lt[1], lb[1], rt[1], rb[1]]), 0), trans_info['size']['height'] - 1) anno['bottom'] = min(max(max([lt[1], lb[1], rt[1], rb[1]]), 1), trans_info['size']['height']) data['size'] = trans_info['size'] return data
def main_process(self): """ define main_process of dyda component """ if len(self.input_data) != 2: self.terminate_flag = True self.logger.error( "Length of input_data is not 2 but %i." % len(self.input_data) ) return False l1 = len(self.input_data[0]) l2 = len(self.input_data[1]) if l1 != l2: self.terminate_flag = True self.logger.error( "Lengths of two input lists are not the same." ) return False conf_thre = 0.0 if "conf_thre" in self.param.keys(): conf_thre = self.param["conf_thre"] self.results = { "true_pos": 0, "false_pos": 0, "gt_number": 0, "mAP": 0, "lab_info": {}} predictions_data_all = self.input_data[0] ground_truth_data_all = self.input_data[1] nd = 0 for data in predictions_data_all: nd += len(data['annotations']) gt_classes = [] for data in ground_truth_data_all: for anno in data['annotations']: label = anno['label'] if label not in gt_classes: self.add_key_to_results(label) gt_classes.append(label) lab_info = self.results["lab_info"] lab_info[label]['gt_number'] += 1 lab_info = self.results["lab_info"] for class_index, class_name in enumerate(gt_classes): tp = [0] * nd fp = [0] * nd idx_obj = -1 for idx, pred in enumerate(predictions_data_all): pred = lab_tools.extract_target_class( copy.deepcopy(pred), class_name ) pred_anno = pred['annotations'] pred_anno.sort( key=lambda x: float(x['confidence']), reverse=True) gt_anno = ground_truth_data_all[idx]['annotations'] for obj in pred_anno: idx_obj += 1 ovmax = -1 gt_match = -1 bb = tinycv.Rect([ obj['top'], obj['bottom'], obj['left'], obj['right']]) for obj_gt in gt_anno: if obj_gt["label"] != class_name: continue bbgt = tinycv.Rect( [obj_gt['top'], obj_gt['bottom'], obj_gt['left'], obj_gt['right']]) bi = [max(bb.l, bbgt.l), max(bb.t, bbgt.t), min(bb.r, bbgt.r), min(bb.b, bbgt.b)] iw = bi[2] - bi[0] + 1 ih = bi[3] - bi[1] + 1 if iw <= 0 or ih <= 0: continue ua = (bb.r - bb.l + 1) * \ (bb.b - bb.t + 1) + \ (bbgt.r - bbgt.l + 1) * \ (bbgt.b - bbgt.t + 1) - \ iw * ih ov = iw * ih / ua if ov <= ovmax: continue ovmax = ov gt_match = obj_gt min_overlap = self.param['min_overlap'] if ovmax >= min_overlap: if "used" not in gt_match.keys( ) or not bool(gt_match["used"]): # true positive tp[idx_obj] = 1 gt_match["used"] = True lab_info[class_name]['true_pos'] += 1 else: # false positive lab_info[class_name]['false_pos'] += 1 fp[idx_obj] = 1 else: # false positive lab_info[class_name]['false_pos'] += 1 fp[idx_obj] = 1 if ovmax > 0: status = "insufficient overlap" # get precision and recall data = lab_info[class_name] self.get_prec_and_recall(data) self.results['true_pos'] += data['true_pos'] self.results['false_pos'] += data['false_pos'] self.results['gt_number'] += data['gt_number'] # get voc average precision cumsum = 0 for idx, val in enumerate(fp): fp[idx] += cumsum cumsum += val cumsum = 0 for idx, val in enumerate(tp): tp[idx] += cumsum cumsum += val rec = tp[:] for idx, val in enumerate(tp): rec[idx] = self.div( tp[idx], lab_info[class_name]['true_pos']) prec = tp[:] for idx, val in enumerate(tp): prec[idx] = self.div( tp[idx], fp[idx] + tp[idx]) lab_info[class_name]['ap'] = self.get_voc_ap(rec, prec) self.results['mAP'] += lab_info[class_name]['ap'] self.get_prec_and_recall(self.results) self.results['mAP'] = self.div( self.results['mAP'], len(gt_classes))