Spaces:
Running
on
Zero
Running
on
Zero
| # Copyright (c) OpenMMLab. All rights reserved. | |
| from itertools import product | |
| from typing import Tuple | |
| import numpy as np | |
| def generate_offset_heatmap( | |
| heatmap_size: Tuple[int, int], | |
| keypoints: np.ndarray, | |
| keypoints_visible: np.ndarray, | |
| radius_factor: float, | |
| ) -> Tuple[np.ndarray, np.ndarray]: | |
| """Generate offset heatmaps of keypoints, where each keypoint is | |
| represented by 3 maps: one pixel-level class label map (1 for keypoint and | |
| 0 for non-keypoint) and 2 pixel-level offset maps for x and y directions | |
| respectively. | |
| Args: | |
| heatmap_size (Tuple[int, int]): Heatmap size in [W, H] | |
| keypoints (np.ndarray): Keypoint coordinates in shape (N, K, D) | |
| keypoints_visible (np.ndarray): Keypoint visibilities in shape | |
| (N, K) | |
| radius_factor (float): The radius factor of the binary label | |
| map. The positive region is defined as the neighbor of the | |
| keypoint with the radius :math:`r=radius_factor*max(W, H)` | |
| Returns: | |
| tuple: | |
| - heatmap (np.ndarray): The generated heatmap in shape | |
| (K*3, H, W) where [W, H] is the `heatmap_size` | |
| - keypoint_weights (np.ndarray): The target weights in shape | |
| (K,) | |
| """ | |
| N, K, _ = keypoints.shape | |
| W, H = heatmap_size | |
| heatmaps = np.zeros((K, 3, H, W), dtype=np.float32) | |
| keypoint_weights = keypoints_visible.copy() | |
| # xy grid | |
| x = np.arange(0, W, 1) | |
| y = np.arange(0, H, 1)[:, None] | |
| # positive area radius in the classification map | |
| radius = radius_factor * max(W, H) | |
| for n, k in product(range(N), range(K)): | |
| if keypoints_visible[n, k] < 0.5: | |
| continue | |
| mu = keypoints[n, k] | |
| x_offset = (mu[0] - x) / radius | |
| y_offset = (mu[1] - y) / radius | |
| heatmaps[k, 0] = np.where(x_offset**2 + y_offset**2 <= 1, 1., 0.) | |
| heatmaps[k, 1] = x_offset | |
| heatmaps[k, 2] = y_offset | |
| heatmaps = heatmaps.reshape(K * 3, H, W) | |
| return heatmaps, keypoint_weights | |
| def generate_displacement_heatmap( | |
| heatmap_size: Tuple[int, int], | |
| keypoints: np.ndarray, | |
| keypoints_visible: np.ndarray, | |
| roots: np.ndarray, | |
| roots_visible: np.ndarray, | |
| diagonal_lengths: np.ndarray, | |
| radius: float, | |
| ): | |
| """Generate displacement heatmaps of keypoints, where each keypoint is | |
| represented by 3 maps: one pixel-level class label map (1 for keypoint and | |
| 0 for non-keypoint) and 2 pixel-level offset maps for x and y directions | |
| respectively. | |
| Args: | |
| heatmap_size (Tuple[int, int]): Heatmap size in [W, H] | |
| keypoints (np.ndarray): Keypoint coordinates in shape (N, K, D) | |
| keypoints_visible (np.ndarray): Keypoint visibilities in shape | |
| (N, K) | |
| roots (np.ndarray): Coordinates of instance centers in shape (N, D). | |
| The displacement fields of each instance will locate around its | |
| center. | |
| roots_visible (np.ndarray): Roots visibilities in shape (N,) | |
| diagonal_lengths (np.ndarray): Diaginal length of the bounding boxes | |
| of each instance in shape (N,) | |
| radius (float): The radius factor of the binary label | |
| map. The positive region is defined as the neighbor of the | |
| keypoint with the radius :math:`r=radius_factor*max(W, H)` | |
| Returns: | |
| tuple: | |
| - displacements (np.ndarray): The generated displacement map in | |
| shape (K*2, H, W) where [W, H] is the `heatmap_size` | |
| - displacement_weights (np.ndarray): The target weights in shape | |
| (K*2, H, W) | |
| """ | |
| N, K, _ = keypoints.shape | |
| W, H = heatmap_size | |
| displacements = np.zeros((K * 2, H, W), dtype=np.float32) | |
| displacement_weights = np.zeros((K * 2, H, W), dtype=np.float32) | |
| instance_size_map = np.zeros((H, W), dtype=np.float32) | |
| for n in range(N): | |
| if (roots_visible[n] < 1 or (roots[n, 0] < 0 or roots[n, 1] < 0) | |
| or (roots[n, 0] >= W or roots[n, 1] >= H)): | |
| continue | |
| diagonal_length = diagonal_lengths[n] | |
| for k in range(K): | |
| if keypoints_visible[n, k] < 1 or keypoints[n, k, 0] < 0 \ | |
| or keypoints[n, k, 1] < 0 or keypoints[n, k, 0] >= W \ | |
| or keypoints[n, k, 1] >= H: | |
| continue | |
| start_x = max(int(roots[n, 0] - radius), 0) | |
| start_y = max(int(roots[n, 1] - radius), 0) | |
| end_x = min(int(roots[n, 0] + radius), W) | |
| end_y = min(int(roots[n, 1] + radius), H) | |
| for x in range(start_x, end_x): | |
| for y in range(start_y, end_y): | |
| if displacements[2 * k, y, | |
| x] != 0 or displacements[2 * k + 1, y, | |
| x] != 0: | |
| if diagonal_length > instance_size_map[y, x]: | |
| # keep the gt displacement of smaller instance | |
| continue | |
| displacement_weights[2 * k:2 * k + 2, y, | |
| x] = 1 / diagonal_length | |
| displacements[2 * k:2 * k + 2, y, | |
| x] = keypoints[n, k] - [x, y] | |
| instance_size_map[y, x] = diagonal_length | |
| return displacements, displacement_weights | |