liyy201912's picture
Upload folder using huggingface_hub
cc0dd3c
raw
history blame
5.67 kB
# Copyright (c) OpenMMLab. All rights reserved.
from typing import Optional, Union
import cv2 as cv
import numpy as np
import torch
from torchvision.transforms import ToPILImage
class SimCCVisualizer:
def draw_instance_xy_heatmap(self,
heatmap: torch.Tensor,
overlaid_image: Optional[np.ndarray],
n: int = 20,
mix: bool = True,
weight: float = 0.5):
"""Draw heatmaps of GT or prediction.
Args:
heatmap (torch.Tensor): Tensor of heatmap.
overlaid_image (np.ndarray): The image to draw.
n (int): Number of keypoint, up to 20.
mix (bool):Whether to merge heatmap and original image.
weight (float): Weight of original image during fusion.
Returns:
np.ndarray: the drawn image which channel is RGB.
"""
heatmap2d = heatmap.data.max(0, keepdim=True)[0]
xy_heatmap, K = self.split_simcc_xy(heatmap)
K = K if K <= n else n
blank_size = tuple(heatmap.size()[1:])
maps = {'x': [], 'y': []}
for i in xy_heatmap:
x, y = self.draw_1d_heatmaps(i['x']), self.draw_1d_heatmaps(i['y'])
maps['x'].append(x)
maps['y'].append(y)
white = self.creat_blank(blank_size, K)
map2d = self.draw_2d_heatmaps(heatmap2d)
if mix:
map2d = cv.addWeighted(overlaid_image, 1 - weight, map2d, weight,
0)
self.image_cover(white, map2d, int(blank_size[1] * 0.1),
int(blank_size[0] * 0.1))
white = self.add_1d_heatmaps(maps, white, blank_size, K)
return white
def split_simcc_xy(self, heatmap: Union[np.ndarray, torch.Tensor]):
"""Extract one-dimensional heatmap from two-dimensional heatmap and
calculate the number of keypoint."""
size = heatmap.size()
k = size[0] if size[0] <= 20 else 20
maps = []
for _ in range(k):
xy_dict = {}
single_heatmap = heatmap[_]
xy_dict['x'], xy_dict['y'] = self.merge_maps(single_heatmap)
maps.append(xy_dict)
return maps, k
def merge_maps(self, map_2d):
"""Synthesis of one-dimensional heatmap."""
x = map_2d.data.max(0, keepdim=True)[0]
y = map_2d.data.max(1, keepdim=True)[0]
return x, y
def draw_1d_heatmaps(self, heatmap_1d):
"""Draw one-dimensional heatmap."""
size = heatmap_1d.size()
length = max(size)
np_heatmap = ToPILImage()(heatmap_1d).convert('RGB')
cv_img = cv.cvtColor(np.asarray(np_heatmap), cv.COLOR_RGB2BGR)
if size[0] < size[1]:
cv_img = cv.resize(cv_img, (length, 15))
else:
cv_img = cv.resize(cv_img, (15, length))
single_map = cv.applyColorMap(cv_img, cv.COLORMAP_JET)
return single_map
def creat_blank(self,
size: Union[list, tuple],
K: int = 20,
interval: int = 10):
"""Create the background."""
blank_height = int(
max(size[0] * 2, size[0] * 1.1 + (K + 1) * (15 + interval)))
blank_width = int(
max(size[1] * 2, size[1] * 1.1 + (K + 1) * (15 + interval)))
blank = np.zeros((blank_height, blank_width, 3), np.uint8)
blank.fill(255)
return blank
def draw_2d_heatmaps(self, heatmap_2d):
"""Draw a two-dimensional heatmap fused with the original image."""
np_heatmap = ToPILImage()(heatmap_2d).convert('RGB')
cv_img = cv.cvtColor(np.asarray(np_heatmap), cv.COLOR_RGB2BGR)
map_2d = cv.applyColorMap(cv_img, cv.COLORMAP_JET)
return map_2d
def image_cover(self, background: np.ndarray, foreground: np.ndarray,
x: int, y: int):
"""Paste the foreground on the background."""
fore_size = foreground.shape
background[y:y + fore_size[0], x:x + fore_size[1]] = foreground
return background
def add_1d_heatmaps(self,
maps: dict,
background: np.ndarray,
map2d_size: Union[tuple, list],
K: int,
interval: int = 10):
"""Paste one-dimensional heatmaps onto the background in turn."""
y_startpoint, x_startpoint = [int(1.1*map2d_size[1]),
int(0.1*map2d_size[0])],\
[int(0.1*map2d_size[1]),
int(1.1*map2d_size[0])]
x_startpoint[1] += interval * 2
y_startpoint[0] += interval * 2
add = interval + 10
for i in range(K):
self.image_cover(background, maps['x'][i], x_startpoint[0],
x_startpoint[1])
cv.putText(background, str(i),
(x_startpoint[0] - 30, x_startpoint[1] + 10),
cv.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
self.image_cover(background, maps['y'][i], y_startpoint[0],
y_startpoint[1])
cv.putText(background, str(i),
(y_startpoint[0], y_startpoint[1] - 5),
cv.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
x_startpoint[1] += add
y_startpoint[0] += add
return background[:x_startpoint[1] + y_startpoint[1] +
1, :y_startpoint[0] + x_startpoint[0] + 1]