def load_annotations(self, ann_file): contents, _ = bt.load_hrsc(img_dir=self.img_prefix, ann_dir=ann_file, classes=self.CLASSES) if self.imgset is not None: contents = bt.split_imgset(contents, self.imgset) return contents
def mask2bbox(masks, btype): if isinstance(masks, PolygonMasks): tran_func = bt.choice_by_type(polymask2hbb, polymask2obb, polymask2poly, btype) elif isinstance(masks, BitmapMasks): tran_func = bt.choice_by_type(bitmapmask2hbb, bitmapmask2obb, bitmapmask2poly, btype) else: raise NotImplementedError return tran_func(masks)
def __init__(self, imgset, classwise, ann_file, img_prefix, *args, **kwargs): self.imgset = imgset if classwise: HRSCDataset.CLASSES = bt.get_classes('hrsc_cls') else: HRSCDataset.CLASSES = bt.get_classes('hrsc') super(HRSCDataset, self).__init__(*args, ann_file=ann_file, img_prefix=img_prefix, **kwargs)
def main(): args = parse_args() print('Loading ground truth and results information') gt_load_func = getattr(bt.datasets, 'load_' + args.gt_type) res_load_func = getattr(bt.datasets, 'load_' + args.res_type) gt_infos, gt_cls = gt_load_func(img_dir=args.img_dir, ann_dir=args.gt_ann_dir, classes=args.classes, nproc=args.nproc) res_infos, res_cls = res_load_func(img_dir=args.img_dir, ann_dir=args.res_ann_dir, classes=args.classes, nproc=args.nproc) bt.change_cls_order(res_infos, res_cls, gt_cls) print('Parsing ground truth and results information') id_mapper = {info['id']: i for i, info in enumerate(res_infos)} gts, res = [], [] for gt_info in gt_infos: img_id = gt_info['id'] res_info = res_infos[id_mapper[img_id]] assert 'scores' in res_info['ann'], \ "f{args.res_type} don't have scores information" res_bboxes = res_info['ann']['bboxes'] res_labels = res_info['ann']['labels'] res_scores = res_info['ann']['scores'] res_dets = np.concatenate([res_bboxes, res_scores[..., None]], axis=1) res_dets = [res_dets[res_labels == i] for i in range(len(gt_cls))] res.append(res_dets) gt_bboxes = gt_info['ann']['bboxes'] gt_labels = gt_info['ann']['labels'] diffs = gt_info['ann'].get('diffs', np.zeros(gt_bboxes.shape[0], dtype=np.int)) gt_ann = {} if args.ign_diff > 0: gt_ann['bboxes_ignore'] = gt_bboxes[diffs == 1] gt_ann['labels_ignore'] = gt_labels[diffs == 1] gt_bboxes = gt_bboxes[diffs == 0] gt_labels = gt_labels[diffs == 0] gt_ann['bboxes'] = gt_bboxes gt_ann['labels'] = gt_labels gts.append(gt_ann) print('Starting calculating mAP') bt.eval_map(res, gts, iou_thr=args.iou_thr, use_07_metric=args.voc_metric == '07', nproc=args.nproc, dataset=gt_cls)
def polymask2poly(masks): polys = [] for mask in masks: all_mask_points = np.concatenate(mask, axis=0)[None, :] if all_mask_points.size != 8: all_mask_points = bt.bbox2type(all_mask_points, 'obb') all_mask_points = bt.bbox2type(all_mask_points, 'poly') polys.append(all_mask_points) if not polys: polys = np.zeros((0, 8), dtype=np.float32) else: polys = np.concatenate(polys, axis=0) return polys
def get_windows(img_W, img_H, sizes, steps, in_rate_thr=0.6): assert 1 >= in_rate_thr >= 0, 'The `in_rate_thr` should lie in 0~1' windows = [] for size, step in zip(sizes, steps): assert size > step, 'Size should large than step' x_num = 1 if img_W <= size else ceil((img_W - size) / step + 1) x_start = [step * i for i in range(x_num)] if len(x_start) > 1 and x_start[-1] + size > img_W: x_start[-1] = img_W - size y_num = 1 if img_H <= size else ceil((img_H - size) / step + 1) y_start = [step * i for i in range(y_num)] if len(y_start) > 1 and y_start[-1] + size > img_H: y_start[-1] = img_H - size start = np.array(list(product(x_start, y_start)), dtype=np.int64) windows.append(np.concatenate([start, start + size], axis=1)) windows = np.concatenate(windows, axis=0) img_contour = np.array([[0, 0, img_W, img_H]]) win_iofs = bt.bbox_overlaps(windows, img_contour, mode='iof').reshape(-1) if not np.any(win_iofs >= in_rate_thr): win_iofs[abs(win_iofs - win_iofs.max()) < 0.01] = 1 return windows[win_iofs >= in_rate_thr]
def _merge_func(info, CLASSES, iou_thr, task): img_id, label_dets = info label_dets = np.concatenate(label_dets, axis=0) labels, dets = label_dets[:, 0], label_dets[:, 1:] nms_ops = bt.choice_by_type(nms, obb_nms, BT_nms, dets, with_score=True) big_img_results = [] for i in range(len(CLASSES)): cls_dets = dets[labels == i] nms_dets, _ = nms_ops(cls_dets, iou_thr) if task == 'Task2': bboxes = bt.bbox2type(nms_dets[:, :-1], 'hbb') nms_dets = np.concatenate([bboxes, nms_dets[:, -1:]], axis=1) big_img_results.append(nms_dets) return img_id, big_img_results
def get_classes(cls, classes=None): if classes is None: cls.custom_classes = False return cls.CLASSES cls.custom_classes = True return bt.get_classes(classes)
def get_matrix_and_size(self, results): angle = results['angle'] height, width = results['img_shape'][:2] if self.keep_shape: center = ((width - 1) * 0.5, (height - 1) * 0.5) matrix = cv2.getRotationMatrix2D(center, angle, 1) else: matrix = cv2.getRotationMatrix2D((0, 0), angle, 1) img_bbox = np.array([[0, 0, width, 0, width, height, 0, width]]) img_bbox = bt.bbox2type(bt.warp(img_bbox, matrix), 'hbb') width = int(img_bbox[0, 2] - img_bbox[0, 0] + 1) height = int(img_bbox[0, 3] - img_bbox[0, 1] + 1) matrix[0, 2] = -img_bbox[0, 0] matrix[1, 2] = -img_bbox[0, 1] return matrix, width, height
def show_result(self, img, result, colors='green', top_k=300, thickness=1, win_name='', wait_time=0, show=False, out_file=None, score_thr=None): img = mmcv.imread(img) bboxes, scores = result[:, :-1], result[:, -1] idx = scores.argsort()[::-1] bboxes = bboxes[idx] top_k = min(top_k, len(bboxes)) bboxes = bboxes[:top_k, :] if out_file is not None: show = False img = bt.imshow_bboxes( img, bboxes, colors=colors, thickness=thickness, with_text=False, show=show, win_name=win_name, wait_time=wait_time, out_file=out_file) return img
def base_rotate(self, results, matrix, w, h, img_bound): if 'img' in results: img = cv2.warpAffine(results['img'], matrix, (w, h)) results['img'] = img results['img_shape'] = img.shape if 'gt_masks' in results: polygons = switch_mask_type(results['gt_masks'], 'polygon') warped_polygons = rotate_polygonmask(polygons, matrix, w, h) if self.keep_shape: obbs = mask2bbox(warped_polygons, 'obb') iofs = bt.bbox_overlaps(obbs, img_bound, mode='iof') if_inwindow = iofs[:, 0] > self.keep_iof_thr index = np.nonzero(if_inwindow)[0] warped_polygons = warped_polygons[index] if isinstance(results['gt_masks'], BitmapMasks): results['gt_masks'] = switch_mask_type(warped_polygons, 'bitmap') elif isinstance(results['gt_masks'], PolygonMasks): results['gt_masks'] = switch_mask_type(warped_polygons, 'polygon') else: raise NotImplementedError if 'gt_bboxes' in results: results['gt_bboxes'] = mask2bbox(warped_polygons, 'hbb') elif 'gt_bboxes' in results: warped_bboxes = bt.warp(results['gt_bboxes'], matrix, keep_type=True) if self.keep_shape: iofs = bt.bbox_overlaps(warped_bboxes, img_bound, mode='iof') if_inwindow = iofs[:, 0] > self.keep_iof_thr # if ~if_inwindow.any(): # return True warped_bboxes = warped_bboxes[if_inwindow] results['gt_bboxes'] = warped_bboxes if 'gt_labels' in results and self.keep_shape: results['gt_labels'] = results['gt_labels'][if_inwindow] for k in results.get('aligned_fields', []): if self.keep_shape: results[k] = results[k][if_inwindow]
def __call__(self, results): results['rotate_after_flip'] = self.rotate_after_flip if 'angle' not in results: results['angle'] = self.get_random_angle(results) if results['angle'] == 0: results['matrix'] = np.eye(3) return results matrix, w, h = self.get_matrix_and_size(results) results['matrix'] = matrix img_bound = np.array([[0, 0, w, 0, w, h, 0, h]]) self.base_rotate(results, matrix, w, h, img_bound) for k in results.get('img_fields', []): if k != 'img': results[k] = cv2.warpAffine(results[k], matrix, (w, h)) for k in results.get('bbox_fields', []): if k == 'gt_bboxes': continue warped_bboxes = bt.warp(results[k], matrix, keep_type=True) if self.keep_shape: iofs = bt.bbox_overlaps(warped_bboxes, img_bound, mode='iof') warped_bboxes = warped_bboxes[iofs[:, 0] > self.keep_iof_thr] results[k] = warped_bboxes for k in results.get('mask_fields', []): if k == 'gt_masks': continue polys = switch_mask_type(results[k], 'polygon') warped_polys = rotate_polygonmask(polys, matrix, w, h) if self.keep_shape: obbs = mask2bbox(warped_polys, 'obb') iofs = bt.bbox_overlaps(obbs, img_bound, mode='iof') index = np.nonzero(iofs[:, 0] > self.keep_iof_thr)[0] warped_polys = warped_polys[index] if isinstance(results[k], BitmapMasks): results[k] = switch_mask_type(warped_polys, 'bitmap') elif isinstance(results[k], PolygonMasks): results[k] = switch_mask_type(warped_polys, 'polygon') else: raise NotImplementedError for k in results.get('seg_fields', []): results[k] = cv2.warpAffine(results[k], matrix, (w, h)) return results
def format_results(self, results, save_dir=None, **kwargs): assert len(results) == len(self.data_infos) contents = [] for result, data_info in zip(results, self.data_infos): info = copy.deepcopy(data_info) info.pop('ann') ann, bboxes, labels, scores = dict(), list(), list(), list() for i, dets in enumerate(result): bboxes.append(dets[:, :-1]) scores.append(dets[:, -1]) labels.append(np.zeros((dets.shape[0], ), dtype=np.int) + i) ann['bboxes'] = np.concatenate(bboxes, axis=0) ann['labels'] = np.concatenate(labels, axis=0) ann['scores'] = np.concatenate(scores, axis=0) info['ann'] = ann contents.append(info) if save_dir is not None: bt.save_pkl(save_dir, contents, self.CLASSES) return contents
def bbox2mask(bboxes, w, h, mask_type='polygon'): polys = bt.bbox2type(bboxes, 'poly') assert mask_type in ['polygon', 'bitmap'] if mask_type == 'bitmap': masks = [] for poly in polys: rles = maskUtils.frPyObjects([poly.tolist()], h, w) masks.append(maskUtils.decode(rles[0])) gt_masks = BitmapMasks(masks, h, w) else: gt_masks = PolygonMasks([[poly] for poly in polys], h, w) return gt_masks
def single_vis(task, btype, class_names, colors, thickness, text_off, font_size, show_off, wait_time, lock, prog, total): imgpath, out_file, bboxes, labels, scores = task bboxes = bt.bbox2type(bboxes, btype) if btype else bboxes bt.imshow_bboxes(imgpath, bboxes, labels, scores, class_names=class_names, colors=colors, thickness=thickness, with_text=(not text_off), font_size=font_size, show=(not show_off), wait_time=wait_time, out_file=out_file) lock.acquire() prog.value += 1 msg = f'({prog.value/total:3.1%} {prog.value}:{total})' msg += ' - ' + f"Filename: {osp.split(imgpath)[-1]}" print(msg) lock.release()
def _load_bboxes(self, results): ann_info = results['ann_info'] gt_bboxes = ann_info['bboxes'].copy() results['gt_bboxes'] = bt.bbox2type(gt_bboxes, 'hbb') results['bbox_fields'].append('gt_bboxes') if self.obb_as_mask: MaskClass = PolygonMasks if self.bbox_mtype == 'polygon' \ else BitmapMasks h, w = results['img_info']['height'], results['img_info']['width'] results['gt_masks'] = bbox2mask(gt_bboxes, w, h, self.bbox_mtype) results['gt_masks_ignore'] = MaskClass([], h, w) results['mask_fields'].append('gt_masks') return results
def polymask2obb(masks): obbs = [] for mask in masks: all_mask_points = np.concatenate(mask, axis=0).reshape(-1, 2) all_mask_points = all_mask_points.astype(np.float32) (x, y), (w, h), angle = cv2.minAreaRect(all_mask_points) angle = -angle theta = angle / 180 * pi obbs.append([x, y, w, h, theta]) if not obbs: obbs = np.zeros((0, 5), dtype=np.float32) else: obbs = np.array(obbs, dtype=np.float32) obbs = bt.regular_obb(obbs) return obbs
def _proposal2json(self, results): """Convert proposal results to COCO json style""" json_results = [] for idx in range(len(self)): img_id = self.img_ids[idx] bboxes = results[idx] bboxes, scores = bboxes[:, :-1], bboxes[:, [-1]] bboxes = bt.bbox2type(bboxes, 'hbb') bboxes = np.concatenate([bboxes, scores], axis=1) for i in range(bboxes.shape[0]): data = dict() data['image_id'] = img_id data['bbox'] = self.xyxy2xywh(bboxes[i]) data['score'] = float(bboxes[i][4]) data['category_id'] = 1 json_results.append(data) return json_results
def eval_arb_recalls(gts, proposals, with_scores=True, proposal_nums=None, iou_thrs=0.5, logger=None): """Calculate recalls. Args: gts (list[ndarray]): a list of arrays of shape (n, 4) proposals (list[ndarray]): a list of arrays of shape (k, 4) or (k, 5) proposal_nums (int | Sequence[int]): Top N proposals to be evaluated. iou_thrs (float | Sequence[float]): IoU thresholds. Default: 0.5. logger (logging.Logger | str | None): The way to print the recall summary. See `mmdet.utils.print_log()` for details. Default: None. Returns: ndarray: recalls of different ious and proposal nums """ img_num = len(gts) assert img_num == len(proposals) proposal_nums, iou_thrs = set_recall_param(proposal_nums, iou_thrs) all_ious = [] for i in range(img_num): if proposals[i].ndim == 2 and with_scores: scores = proposals[i][:, -1] sort_idx = np.argsort(scores)[::-1] img_proposal = proposals[i][sort_idx, :] else: img_proposal = proposals[i] if with_scores: img_proposal = img_proposal[:, :-1] prop_num = min(img_proposal.shape[0], proposal_nums[-1]) if gts[i] is None or gts[i].shape[0] == 0: ious = np.zeros((0, img_proposal.shape[0]), dtype=np.float32) else: ious = bt.bbox_overlaps(gts[i], img_proposal[:prop_num]) all_ious.append(ious) all_ious = np.array(all_ious) recalls = _recalls(all_ious, proposal_nums, iou_thrs) print_recall_summary(recalls, proposal_nums, iou_thrs, logger=logger) return recalls
def get_window_obj(info, windows, iof_thr): bboxes = info['ann']['bboxes'] iofs = bt.bbox_overlaps(bboxes, windows, mode='iof') window_anns = [] for i in range(windows.shape[0]): win_iofs = iofs[:, i] pos_inds = np.nonzero(win_iofs >= iof_thr)[0].tolist() win_ann = dict() for k, v in info['ann'].items(): try: win_ann[k] = v[pos_inds] except TypeError: win_ann[k] = [v[i] for i in pos_inds] win_ann['trunc'] = win_iofs[pos_inds] < 1 window_anns.append(win_ann) return window_anns
def __call__(self, results): gt_bboxes = results['gt_bboxes'] if len(gt_bboxes) <= self.n: return results if 'gt_masks' in results: areas = results['gt_masks'].areas else: areas = bt.bbox_areas(gt_bboxes) index = np.argsort(areas)[:self.n] results['gt_bboxes'] = gt_bboxes[index] if 'gt_labels' in results: results['gt_labels'] = results['gt_labels'][index] if 'gt_masks' in results: results['gt_masks'] = results['gt_masks'][index] return results
def BT_nms(dets, iou_thr, device_id=None): if isinstance(dets, torch.Tensor): is_tensor = True device = dets.device dets_np = dets.cpu().numpy() elif isinstance(dets, np.ndarray): is_tensor = False dets_np = dets else: raise TypeError('dets must be eithr a Tensor or numpy array, ' f'but got {type(dets)}') bboxes, scores = dets_np[:, :-1], dets_np[:, -1] inds = bt.bbox_nms(bboxes, scores, iou_thr=iou_thr, score_thr=0) if is_tensor: inds = torch.from_numpy(inds).to(device) return dets[inds, :], inds
def crop_and_save_img(info, windows, window_anns, img_dir, no_padding, padding_value, filter_empty, save_dir, img_ext): img = cv2.imread(osp.join(img_dir, info['filename'])) patch_infos = [] for i in range(windows.shape[0]): ann = window_anns[i] if filter_empty and (ann['bboxes'].size == 0): continue patch_info = dict() for k, v in info.items(): if k not in ['id', 'fileanme', 'width', 'height', 'ann']: patch_info[k] = v window = windows[i] x_start, y_start, x_stop, y_stop = window.tolist() ann['bboxes'] = bt.translate(ann['bboxes'], -x_start, -y_start) patch_info['ann'] = ann patch_info['x_start'] = x_start patch_info['y_start'] = y_start patch_info['id'] = info['id'] + f'_{i:04d}' patch_info['ori_id'] = info['id'] patch = img[y_start:y_stop, x_start:x_stop] if not no_padding: height = y_stop - y_start width = x_stop - x_start if height > patch.shape[0] or width > patch.shape[1]: padding_patch = np.empty((height, width, patch.shape[-1]), dtype=np.uint8) if not isinstance(padding_value, (int, float)): assert len(padding_value) == patch.shape[-1] padding_patch[...] = padding_value padding_patch[:patch.shape[0], :patch.shape[1], ...] = patch patch = padding_patch patch_info['height'] = patch.shape[0] patch_info['width'] = patch.shape[1] cv2.imwrite(osp.join(save_dir, patch_info['id'] + img_ext), patch) patch_info['filename'] = patch_info['id'] + img_ext patch_infos.append(patch_info) return patch_infos
def bitmapmask2poly(masks): if len(masks) == 0: return np.zeros((0, 8), dtype=np.float32) height, width = masks.height, masks.width x, y = np.arange(width), np.arange(height) xx, yy = np.meshgrid(x, y) coors = np.stack([xx, yy], axis=-1) coors = coors.astype(np.float32) obbs = [] for mask in masks: points = coors[mask == 1] (x, y), (w, h), angle = cv2.minAreaRect(points) angle = -angle theta = angle / 180 * pi obbs.append([x, y, w, h, theta]) obbs = np.array(obbs, dtype=np.float32) return bt.bbox2type(obbs, 'poly')
def merge_patch_results(results, windows, nms_cfg): nms_cfg_ = nms_cfg.copy() nms_type = nms_cfg_.pop('type', 'BT_nms') try: nms_op = getattr(nms_rotated, nms_type) except AttributeError: nms_op = getattr(nms, nms_type) _results = [] for _cls_result in zip(*results): cls_result = [] for dets, win in zip(_cls_result, windows): bboxes, scores = dets[:, :-1], dets[:, [-1]] x_start, y_start = win[:2] bboxes = bt.translate(bboxes, x_start, y_start) cls_result.append(np.concatenate([bboxes, scores], axis=1)) cls_result = np.concatenate(cls_result, axis=0) _result, _ = nms_op(cls_result, **nms_cfg_) _results.append(_result) return _results
def _segm2json(self, results): """Convert instance segmentation results to COCO json style""" bbox_json_results = [] segm_json_results = [] for idx in range(len(self)): img_id = self.img_ids[idx] det, seg = results[idx] for label in range(len(det)): # bbox results bboxes = det[label] bboxes, scores = bboxes[:, :-1], bboxes[:, [-1]] bboxes = bt.bbox2type(bboxes, 'hbb') bboxes = np.concatenate([bboxes, scores], axis=1) for i in range(bboxes.shape[0]): data = dict() data['image_id'] = img_id data['bbox'] = self.xyxy2xywh(bboxes[i]) data['score'] = float(bboxes[i][4]) data['category_id'] = self.cat_ids[label] bbox_json_results.append(data) # segm results # some detectors use different scores for bbox and mask if isinstance(seg, tuple): segms = seg[0][label] mask_score = seg[1][label] else: segms = seg[label] mask_score = [bbox[4] for bbox in bboxes] for i in range(bboxes.shape[0]): data = dict() data['image_id'] = img_id data['score'] = float(mask_score[i]) data['category_id'] = self.cat_ids[label] if isinstance(segms[i]['counts'], bytes): segms[i]['counts'] = segms[i]['counts'].decode() data['segmentation'] = segms[i] segm_json_results.append(data) return bbox_json_results, segm_json_results
def __call__(self, bboxes1, bboxes2, mode='iou', is_aligned=False): """Calculate IoU between 2D bboxes Args: bboxes1 (Tensor): bboxes have shape (m, 4) in <x1, y1, x2, y2> format, or shape (m, 5) in <x1, y1, x2, y2, score> format. bboxes2 (Tensor): bboxes have shape (m, 4) in <x1, y1, x2, y2> format, shape (m, 5) in <x1, y1, x2, y2, score> format, or be empty. If is_aligned is ``True``, then m and n must be equal. mode (str): "iou" (intersection over union) or iof (intersection over foreground). Returns: ious(Tensor): shape (m, n) if is_aligned == False else shape (m, 1) """ assert bboxes1.size(-1) in [0, 8, 9] assert bboxes2.size(-1) in [0, 8, 9] if bboxes2.size(-1) == 9: bboxes2 = bboxes2[..., :8] if bboxes1.size(-1) == 9: bboxes1 = bboxes1[..., :8] return bt.bbox_overlaps(bboxes1, bboxes2, mode, is_aligned)
def _list_mask_2_obb(dets, segments): new_dets = [] for cls_dets, cls_segments in zip(dets, segments): new_cls_dets = [] for ds, segs in zip(cls_dets, cls_segments): _, scores = ds[:, :-1], ds[:, -1] new_bboxes = [] for seg in segs: try: contours, _ = cv2.findContours(seg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) except ValueError: _, contours, _ = cv2.findContours(seg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) max_contour = max(contours, key=len).reshape(1, -1) new_bboxes.append(bt.bbox2type(max_contour, 'obb')) new_bboxes = np.zeros((0, 5)) if not new_bboxes else \ np.concatenate(new_bboxes, axis=0) new_cls_dets.append( np.concatenate([new_bboxes, scores[:, None]], axis=1)) new_dets.append(new_cls_dets) return new_dets
def __call__(self, results): for k in ['gt_bboxes', 'gt_masks', 'gt_labels']: if k in results: num_objs = len(results[k]) break else: return results ignore = np.zeros((num_objs, ), dtype=np.bool) if self.ignore_diff: assert 'diffs' in results diffs = results['diffs'] ignore[diffs == 1] = True if self.ignore_truncated: assert 'trunc' in results trunc = results['trunc'] ignore[trunc == 1] = True if self.ignore_size: bboxes = results['gt_bboxes'] wh = bboxes[:, 2:] - bboxes[:, :2] ignore[np.min(wh, axis=1) < self.ignore_size] = True if self.ignore_real_scales: assert len(self.ignore_real_scales) == (len(results['split_sizes']) * len(results['split_rates'])) polys = mask2bbox(results['gt_masks'], 'poly') if 'scale_factor' in results: scale_factor = np.tile(results['scale_factor'], 2) polys = polys / scale_factor bbox_scales = np.sqrt(bt.bbox_areas(polys)) split_sizes=[] for rate in results['split_rates']: split_sizes += [int(size / rate) for size in results['split_sizes']] img_scale = results['img_info']['width'] scale_ratio = np.array(split_sizes) / img_scale inds = np.argmin(abs(np.log(scale_ratio))) min_scale, max_scale = self.ignore_real_scales[inds] if min_scale is None: min_scale = 0 if max_scale is None: max_scale = np.inf ignore[bbox_scales < min_scale] = True ignore[bbox_scales > max_scale] = True if 'gt_bboxes' in results: bboxes = results['gt_bboxes'] gt_bboxes = bboxes[~ignore] gt_bboxes_ignore = bboxes[ignore] results['gt_bboxes'] = gt_bboxes results['gt_bboxes_ignore'] = gt_bboxes_ignore if 'gt_bboxes_ignore' not in results['bbox_fields']: results['bbox_fields'].append('gt_bboxes_ignore') if 'gt_masks' in results: gt_inds = np.nonzero(~ignore)[0] ignore_inds = np.nonzero(ignore)[0] if isinstance(results['gt_masks'], PolygonMasks) \ and len(gt_inds) == 0: height = results['gt_masks'].height width = results['gt_masks'].width gt_masks = PolygonMasks([], height, width) else: gt_masks = results['gt_masks'][gt_inds] if isinstance(results['gt_masks'], PolygonMasks) \ and len(ignore_inds) == 0: height = results['gt_masks'].height width = results['gt_masks'].width gt_masks_ignore = PolygonMasks([], height, width) else: gt_masks_ignore = results['gt_masks'][ignore_inds] results['gt_masks'] = gt_masks results['gt_masks_ignore'] = gt_masks_ignore if 'gt_masks_ignore' not in results['mask_fields']: results['mask_fields'].append('gt_masks_ignore') if 'gt_labels' in results: results['gt_labels'] = results['gt_labels'][~ignore] for k in results.get('aligned_fields', []): results[k] = results[k][~ignore] return results
def show_result(self, img, result, score_thr=0.3, colors='green', thickness=1., font_size=10, win_name='', show=False, wait_time=0, out_file=None): img = mmcv.imread(img) img = img.copy() if isinstance(result, tuple): bbox_result, segm_result = result if isinstance(segm_result, tuple): segm_result = segm_result[0] # ms rcnn else: bbox_result, segm_result = result, None bboxes = np.vstack(bbox_result) labels = [ np.full(bbox.shape[0], i, dtype=np.int32) for i, bbox in enumerate(bbox_result) ] labels = np.concatenate(labels) # draw segmentation masks if segm_result is not None and len(labels) > 0: # non empty segms = mmcv.concat_list(segm_result) inds = np.where(bboxes[:, -1] > score_thr)[0] np.random.seed(42) color_masks = [ np.random.randint(0, 256, (1, 3), dtype=np.uint8) for _ in range(max(labels) + 1) ] for i in inds: i = int(i) color_mask = color_masks[labels[i]] mask = segms[i] img[mask] = img[mask] * 0.5 + color_mask * 0.5 # if out_file specified, do not show image in window if out_file is not None: show = False # draw bounding boxes bboxes, scores = bboxes[:, :-1], bboxes[:, -1] bboxes = bboxes[scores > score_thr] labels = labels[scores > score_thr] scores = scores[scores > score_thr] img = bt.imshow_bboxes( img, bboxes, labels, scores, class_names=self.CLASSES, colors=colors, thickness=thickness, font_size=font_size, win_name=win_name, show=show, wait_time=wait_time, out_file=out_file) if not (show or out_file): warnings.warn('show==False and out_file is not specified, only ' 'result image will be returned') return img