# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import numpy as np from skimage import transform as trans def encode_label(K, ry, dims, locs): """get bbox 3d and 2d by model output Args: K (np.ndarray): camera intrisic matrix ry (np.ndarray): rotation y dims (np.ndarray): dimensions locs (np.ndarray): locations """ l, h, w = dims[0], dims[1], dims[2] x, y, z = locs[0], locs[1], locs[2] x_corners = [0, l, l, l, l, 0, 0, 0] y_corners = [0, 0, h, h, 0, 0, h, h] z_corners = [0, 0, 0, w, w, w, w, 0] x_corners += - np.float32(l) / 2 y_corners += - np.float32(h) z_corners += - np.float32(w) / 2 corners_3d = np.array([x_corners, y_corners, z_corners]) rot_mat = np.array([[np.cos(ry), 0, np.sin(ry)], [0, 1, 0], [-np.sin(ry), 0, np.cos(ry)]]) corners_3d = np.matmul(rot_mat, corners_3d) corners_3d += np.array([x, y, z]).reshape([3, 1]) loc_center = np.array([x, y - h / 2, z]) proj_point = np.matmul(K, loc_center) proj_point = proj_point[:2] / proj_point[2] corners_2d = np.matmul(K, corners_3d) corners_2d = corners_2d[:2] / corners_2d[2] box2d = np.array([min(corners_2d[0]), min(corners_2d[1]), max(corners_2d[0]), max(corners_2d[1])]) return proj_point, box2d, corners_3d def get_transfrom_matrix(center_scale, output_size): """get transform matrix """ center, scale = center_scale[0], center_scale[1] # todo: further add rot and shift here. src_w = scale[0] dst_w = output_size[0] dst_h = output_size[1] src_dir = np.array([0, src_w * -0.5]) dst_dir = np.array([0, dst_w * -0.5]) src = np.zeros((3, 2), dtype=np.float32) dst = np.zeros((3, 2), dtype=np.float32) src[0, :] = center src[1, :] = center + src_dir dst[0, :] = np.array([dst_w * 0.5, dst_h * 0.5]) dst[1, :] = np.array([dst_w * 0.5, dst_h * 0.5]) + dst_dir src[2, :] = get_3rd_point(src[0, :], src[1, :]) dst[2, :] = get_3rd_point(dst[0, :], dst[1, :]) get_matrix = trans.estimate_transform("affine", src, dst) matrix = get_matrix.params return matrix.astype(np.float32) def affine_transform(point, matrix): """do affine transform to label """ point_exd = np.array([point[0], point[1], 1.]) new_point = np.matmul(matrix, point_exd) return new_point[:2] def get_3rd_point(point_a, point_b): """get 3rd point """ d = point_a - point_b point_c = point_b + np.array([-d[1], d[0]]) return point_c def gaussian_radius(h, w, thresh_min=0.7): """gaussian radius """ a1 = 1 b1 = h + w c1 = h * w * (1 - thresh_min) / (1 + thresh_min) sq1 = np.sqrt(b1 ** 2 - 4 * a1 * c1) r1 = (b1 - sq1) / (2 * a1) a2 = 4 b2 = 2 * (h + w) c2 = (1 - thresh_min) * w * h sq2 = np.sqrt(b2 ** 2 - 4 * a2 * c2) r2 = (b2 - sq2) / (2 * a2) a3 = 4 * thresh_min b3 = -2 * thresh_min * (h + w) c3 = (thresh_min - 1) * w * h sq3 = np.sqrt(b3 ** 2 - 4 * a3 * c3) r3 = (b3 + sq3) / (2 * a3) return min(r1, r2, r3) def gaussian2D(shape, sigma=1): """get 2D gaussian map """ m, n = [(ss - 1.) / 2. for ss in shape] y, x = np.ogrid[-m:m + 1, -n:n + 1] h = np.exp(-(x * x + y * y) / (2 * sigma * sigma)) h[h < np.finfo(h.dtype).eps * h.max()] = 0 return h def draw_umich_gaussian(heatmap, center, radius, k=1): """draw umich gaussian """ diameter = 2 * radius + 1 gaussian = gaussian2D((diameter, diameter), sigma=diameter / 6) x, y = int(center[0]), int(center[1]) height, width = heatmap.shape[0:2] left, right = min(x, radius), min(width - x, radius + 1) top, bottom = min(y, radius), min(height - y, radius + 1) masked_heatmap = heatmap[y - top:y + bottom, x - left:x + right] masked_gaussian = gaussian[radius - top:radius + bottom, radius - left:radius + right] if min(masked_gaussian.shape) > 0 and min(masked_heatmap.shape) > 0: np.maximum(masked_heatmap, masked_gaussian * k, out=masked_heatmap) return heatmap