| | import matplotlib.pyplot as plt |
| | import mmcv |
| | import numpy as np |
| | import pycocotools.mask as mask_util |
| | from matplotlib.collections import PatchCollection |
| | from matplotlib.patches import Polygon |
| | import cv2 |
| |
|
| | from ..utils import mask2ndarray |
| |
|
| | EPS = 1e-2 |
| |
|
| |
|
| | def color_val_matplotlib(color): |
| | """Convert various input in BGR order to normalized RGB matplotlib color |
| | tuples, |
| | |
| | Args: |
| | color (:obj:`Color`/str/tuple/int/ndarray): Color inputs |
| | |
| | Returns: |
| | tuple[float]: A tuple of 3 normalized floats indicating RGB channels. |
| | """ |
| | color = mmcv.color_val(color) |
| | color = [color / 255 for color in color[::-1]] |
| | return tuple(color) |
| |
|
| |
|
| | def imshow_det_bboxes(img, |
| | bboxes, |
| | labels, |
| | segms=None, |
| | class_names=None, |
| | score_thr=0, |
| | bbox_color='green', |
| | text_color='green', |
| | mask_color=None, |
| | thickness=2, |
| | font_size=13, |
| | win_name='', |
| | show=True, |
| | wait_time=0, |
| | out_file=None): |
| | """Draw bboxes and class labels (with scores) on an image. |
| | |
| | Args: |
| | img (str or ndarray): The image to be displayed. |
| | bboxes (ndarray): Bounding boxes (with scores), shaped (n, 4) or |
| | (n, 5). |
| | labels (ndarray): Labels of bboxes. |
| | segms (ndarray or None): Masks, shaped (n,h,w) or None |
| | class_names (list[str]): Names of each classes. |
| | score_thr (float): Minimum score of bboxes to be shown. Default: 0 |
| | bbox_color (str or tuple(int) or :obj:`Color`):Color of bbox lines. |
| | The tuple of color should be in BGR order. Default: 'green' |
| | text_color (str or tuple(int) or :obj:`Color`):Color of texts. |
| | The tuple of color should be in BGR order. Default: 'green' |
| | mask_color (str or tuple(int) or :obj:`Color`, optional): |
| | Color of masks. The tuple of color should be in BGR order. |
| | Default: None |
| | thickness (int): Thickness of lines. Default: 2 |
| | font_size (int): Font size of texts. Default: 13 |
| | show (bool): Whether to show the image. Default: True |
| | win_name (str): The window name. Default: '' |
| | wait_time (float): Value of waitKey param. Default: 0. |
| | out_file (str, optional): The filename to write the image. |
| | Default: None |
| | |
| | Returns: |
| | ndarray: The image with bboxes drawn on it. |
| | """ |
| | assert bboxes.ndim == 2, \ |
| | f' bboxes ndim should be 2, but its ndim is {bboxes.ndim}.' |
| | assert labels.ndim == 1, \ |
| | f' labels ndim should be 1, but its ndim is {labels.ndim}.' |
| | assert bboxes.shape[0] == labels.shape[0], \ |
| | 'bboxes.shape[0] and labels.shape[0] should have the same length.' |
| | assert bboxes.shape[1] == 4 or bboxes.shape[1] == 5, \ |
| | f' bboxes.shape[1] should be 4 or 5, but its {bboxes.shape[1]}.' |
| | img = mmcv.imread(img).astype(np.uint8) |
| |
|
| | if score_thr > 0: |
| | assert bboxes.shape[1] == 5 |
| | scores = bboxes[:, -1] |
| | inds = scores > score_thr |
| | bboxes = bboxes[inds, :] |
| | labels = labels[inds] |
| | if segms is not None: |
| | if len(inds) != len(segms): |
| | inds = np.repeat(a = inds, repeats = 2) |
| | segms = segms[inds, ...] |
| |
|
| | mask_colors = [] |
| | if labels.shape[0] > 0: |
| | if mask_color is None: |
| | |
| | np.random.seed(46) |
| | mask_colors = [ |
| | np.random.randint(0, 256, (1, 3), dtype=np.uint8) |
| | |
| | for _ in range(100) |
| | ] |
| | |
| | |
| | else: |
| | |
| | mask_colors = [ |
| | np.array(mmcv.color_val(mask_color)[::-1], dtype=np.uint8) |
| | ] * ( |
| | max(labels) + 1) |
| |
|
| | bbox_color = color_val_matplotlib(bbox_color) |
| | text_color = color_val_matplotlib(text_color) |
| |
|
| | img = mmcv.bgr2rgb(img) |
| | width, height = img.shape[1], img.shape[0] |
| | img = np.ascontiguousarray(img) |
| |
|
| | fig = plt.figure(win_name, frameon=False) |
| | plt.title(win_name) |
| | canvas = fig.canvas |
| | dpi = fig.get_dpi() |
| | |
| | |
| | fig.set_size_inches((width + EPS) / dpi, (height + EPS) / dpi) |
| |
|
| | |
| | plt.subplots_adjust(left=0, right=1, bottom=0, top=1) |
| | ax = plt.gca() |
| | ax.axis('off') |
| |
|
| | polygons = [] |
| | color = [] |
| | img_bound =img*0 |
| | |
| | for i, (bbox, label) in enumerate(zip(bboxes, labels)): |
| | bbox_int = bbox.astype(np.int32) |
| | poly = [[bbox_int[0], bbox_int[1]], [bbox_int[0], bbox_int[3]], |
| | [bbox_int[2], bbox_int[3]], [bbox_int[2], bbox_int[1]]] |
| | np_poly = np.array(poly).reshape((4, 2)) |
| | polygons.append(Polygon(np_poly)) |
| | color.append(bbox_color) |
| | label_text = class_names[ |
| | label] if class_names is not None else f'class {label}' |
| | if len(bbox) > 4: |
| | label_text += f'|{bbox[-1]:.02f}' |
| | ''' |
| | ax.text( |
| | bbox_int[0], |
| | bbox_int[1], |
| | f'{label_text}', |
| | bbox={ |
| | 'facecolor': 'black', |
| | 'alpha': 0.8, |
| | 'pad': 0.7, |
| | 'edgecolor': 'none' |
| | }, |
| | color=text_color, |
| | fontsize=font_size, |
| | verticalalignment='top', |
| | horizontalalignment='left') |
| | ''' |
| | if segms is not None: |
| | for ll in range(1): |
| | color_mask = mask_colors[np.random.randint(0, 99)] |
| | mask = segms[len(labels)*ll+i].astype(bool) |
| | show_border = True |
| | img[mask] = img[mask] * 0.5 + color_mask * 0.5 |
| | if show_border: |
| | contours,_ = cv2.findContours(mask.copy().astype('uint8'), cv2.RETR_CCOMP, cv2.CHAIN_APPROX_NONE) |
| | border_thick = min(int(4*(max(bbox_int[2]-bbox_int[0],bbox_int[3]-bbox_int[1])/300))+1,6) |
| | cv2.drawContours(img, contours, -1, (int(color_mask[0][0]),int(color_mask[0][1]),int(color_mask[0][2])), border_thick) |
| | |
| | |
| | |
| |
|
| | plt.imshow(img) |
| |
|
| | p = PatchCollection( |
| | polygons, facecolor='none', edgecolors=color, linewidths=thickness) |
| | |
| |
|
| | stream, _ = canvas.print_to_buffer() |
| | buffer = np.frombuffer(stream, dtype='uint8') |
| | img_rgba = buffer.reshape(height, width, 4) |
| | rgb, alpha = np.split(img_rgba, [3], axis=2) |
| | img = rgb.astype('uint8') |
| | img = mmcv.rgb2bgr(img) |
| |
|
| | if show: |
| | |
| | |
| | |
| | |
| | if wait_time == 0: |
| | plt.show() |
| | else: |
| | plt.show(block=False) |
| | plt.pause(wait_time) |
| | if out_file is not None: |
| | mmcv.imwrite(img, out_file) |
| |
|
| | plt.close() |
| |
|
| | return img |
| |
|
| |
|
| | def imshow_gt_det_bboxes(img, |
| | annotation, |
| | result, |
| | class_names=None, |
| | score_thr=0, |
| | gt_bbox_color=(255, 102, 61), |
| | gt_text_color=(255, 102, 61), |
| | gt_mask_color=(255, 102, 61), |
| | det_bbox_color=(72, 101, 241), |
| | det_text_color=(72, 101, 241), |
| | det_mask_color=(72, 101, 241), |
| | thickness=2, |
| | font_size=13, |
| | win_name='', |
| | show=True, |
| | wait_time=0, |
| | out_file=None): |
| | """General visualization GT and result function. |
| | |
| | Args: |
| | img (str or ndarray): The image to be displayed.) |
| | annotation (dict): Ground truth annotations where contain keys of |
| | 'gt_bboxes' and 'gt_labels' or 'gt_masks' |
| | result (tuple[list] or list): The detection result, can be either |
| | (bbox, segm) or just bbox. |
| | class_names (list[str]): Names of each classes. |
| | score_thr (float): Minimum score of bboxes to be shown. Default: 0 |
| | gt_bbox_color (str or tuple(int) or :obj:`Color`):Color of bbox lines. |
| | The tuple of color should be in BGR order. Default: (255, 102, 61) |
| | gt_text_color (str or tuple(int) or :obj:`Color`):Color of texts. |
| | The tuple of color should be in BGR order. Default: (255, 102, 61) |
| | gt_mask_color (str or tuple(int) or :obj:`Color`, optional): |
| | Color of masks. The tuple of color should be in BGR order. |
| | Default: (255, 102, 61) |
| | det_bbox_color (str or tuple(int) or :obj:`Color`):Color of bbox lines. |
| | The tuple of color should be in BGR order. Default: (72, 101, 241) |
| | det_text_color (str or tuple(int) or :obj:`Color`):Color of texts. |
| | The tuple of color should be in BGR order. Default: (72, 101, 241) |
| | det_mask_color (str or tuple(int) or :obj:`Color`, optional): |
| | Color of masks. The tuple of color should be in BGR order. |
| | Default: (72, 101, 241) |
| | thickness (int): Thickness of lines. Default: 2 |
| | font_size (int): Font size of texts. Default: 13 |
| | win_name (str): The window name. Default: '' |
| | show (bool): Whether to show the image. Default: True |
| | wait_time (float): Value of waitKey param. Default: 0. |
| | out_file (str, optional): The filename to write the image. |
| | Default: None |
| | |
| | Returns: |
| | ndarray: The image with bboxes or masks drawn on it. |
| | """ |
| | assert 'gt_bboxes' in annotation |
| | assert 'gt_labels' in annotation |
| | assert isinstance( |
| | result, |
| | (tuple, list)), f'Expected tuple or list, but get {type(result)}' |
| |
|
| | gt_masks = annotation.get('gt_masks', None) |
| | if gt_masks is not None: |
| | gt_masks = mask2ndarray(gt_masks) |
| |
|
| | img = mmcv.imread(img) |
| |
|
| | img = imshow_det_bboxes( |
| | img, |
| | annotation['gt_bboxes'], |
| | annotation['gt_labels'], |
| | gt_masks, |
| | class_names=class_names, |
| | bbox_color=gt_bbox_color, |
| | text_color=gt_text_color, |
| | mask_color=gt_mask_color, |
| | thickness=thickness, |
| | font_size=font_size, |
| | win_name=win_name, |
| | show=False) |
| |
|
| | if isinstance(result, tuple): |
| | bbox_result, segm_result = result |
| | if isinstance(segm_result, tuple): |
| | segm_result = segm_result[0] |
| | 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) |
| |
|
| | segms = None |
| | if segm_result is not None and len(labels) > 0: |
| | segms = mmcv.concat_list(segm_result) |
| | segms = mask_util.decode(segms) |
| | segms = segms.transpose(2, 0, 1) |
| |
|
| | img = imshow_det_bboxes( |
| | img, |
| | bboxes, |
| | labels, |
| | segms=segms, |
| | class_names=class_names, |
| | score_thr=score_thr, |
| | bbox_color=det_bbox_color, |
| | text_color=det_text_color, |
| | mask_color=det_mask_color, |
| | thickness=thickness, |
| | font_size=font_size, |
| | win_name=win_name, |
| | show=show, |
| | wait_time=wait_time, |
| | out_file=out_file) |
| | return img |
| |
|