Spaces:
Runtime error
Runtime error
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: | |
# random color | |
np.random.seed(46) | |
mask_colors = [ | |
np.random.randint(0, 256, (1, 3), dtype=np.uint8) | |
#for _ in range(max(labels) + 2) | |
for _ in range(100) | |
] | |
#print(mask_colors) | |
#asas | |
else: | |
# specify color | |
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() | |
# add a small EPS to avoid precision lost due to matplotlib's truncation | |
# (https://github.com/matplotlib/matplotlib/issues/15363) | |
fig.set_size_inches((width + EPS) / dpi, (height + EPS) / dpi) | |
# remove white edges by set subplot margin | |
plt.subplots_adjust(left=0, right=1, bottom=0, top=1) | |
ax = plt.gca() | |
ax.axis('off') | |
polygons = [] | |
color = [] | |
img_bound =img*0 | |
#img=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) | |
#img = cv2.addWeighted(img,1.0,img_bound,1.0,0) | |
#img[img_bound>0] = img_bound | |
plt.imshow(img) | |
p = PatchCollection( | |
polygons, facecolor='none', edgecolors=color, linewidths=thickness) | |
#ax.add_collection(p) | |
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: | |
# We do not use cv2 for display because in some cases, opencv will | |
# conflict with Qt, it will output a warning: Current thread | |
# is not the object's thread. You can refer to | |
# https://github.com/opencv/opencv-python/issues/46 for details | |
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] # 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) | |
segms = None | |
if segm_result is not None and len(labels) > 0: # non empty | |
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 | |