|
|
|
from typing import Sequence |
|
|
|
import numpy as np |
|
from mmcv.transforms import BaseTransform |
|
|
|
from mmdet3d.registry import TRANSFORMS |
|
|
|
|
|
@TRANSFORMS.register_module() |
|
class SemkittiRangeView(BaseTransform): |
|
"""Convert Semantickitti point cloud dataset to range image.""" |
|
|
|
def __init__(self, |
|
H: int = 64, |
|
W: int = 2048, |
|
fov_up: float = 3.0, |
|
fov_down: float = -25.0, |
|
means: Sequence[float] = (11.71279, -0.1023471, 0.4952, |
|
-1.0545, 0.2877), |
|
stds: Sequence[float] = (10.24, 12.295865, 9.4287, 0.8643, |
|
0.1450), |
|
ignore_index: int = 19) -> None: |
|
self.H = H |
|
self.W = W |
|
self.fov_up = fov_up / 180.0 * np.pi |
|
self.fov_down = fov_down / 180.0 * np.pi |
|
self.fov = abs(self.fov_down) + abs(self.fov_up) |
|
self.means = np.array(means, dtype=np.float32) |
|
self.stds = np.array(stds, dtype=np.float32) |
|
self.ignore_index = ignore_index |
|
|
|
def transform(self, results: dict) -> dict: |
|
points_numpy = results['points'].numpy() |
|
|
|
proj_image = np.full((self.H, self.W, 5), -1, dtype=np.float32) |
|
proj_idx = np.full((self.H, self.W), -1, dtype=np.int64) |
|
|
|
|
|
depth = np.linalg.norm(points_numpy[:, :3], 2, axis=1) |
|
|
|
|
|
yaw = -np.arctan2(points_numpy[:, 1], points_numpy[:, 0]) |
|
pitch = np.arcsin(points_numpy[:, 2] / depth) |
|
|
|
|
|
proj_x = 0.5 * (yaw / np.pi + 1.0) |
|
proj_y = 1.0 - (pitch + abs(self.fov_down)) / self.fov |
|
|
|
|
|
proj_x *= self.W |
|
proj_y *= self.H |
|
|
|
|
|
proj_x = np.floor(proj_x) |
|
proj_x = np.minimum(self.W - 1, proj_x) |
|
proj_x = np.maximum(0, proj_x).astype(np.int64) |
|
|
|
proj_y = np.floor(proj_y) |
|
proj_y = np.minimum(self.H - 1, proj_y) |
|
proj_y = np.maximum(0, proj_y).astype(np.int64) |
|
|
|
results['proj_x'] = proj_x |
|
results['proj_y'] = proj_y |
|
results['unproj_range'] = depth |
|
|
|
|
|
indices = np.arange(depth.shape[0]) |
|
order = np.argsort(depth)[::-1] |
|
proj_idx[proj_y[order], proj_x[order]] = indices[order] |
|
proj_image[proj_y[order], proj_x[order], 0] = depth[order] |
|
proj_image[proj_y[order], proj_x[order], 1:] = points_numpy[order] |
|
proj_mask = (proj_idx > 0).astype(np.int32) |
|
results['proj_range'] = proj_image[..., 0] |
|
|
|
proj_image = (proj_image - |
|
self.means[None, None, :]) / self.stds[None, None, :] |
|
proj_image = proj_image * proj_mask[..., None].astype(np.float32) |
|
results['img'] = proj_image |
|
|
|
if 'pts_semantic_mask' in results: |
|
proj_sem_label = np.full((self.H, self.W), |
|
self.ignore_index, |
|
dtype=np.int64) |
|
proj_sem_label[proj_y[order], |
|
proj_x[order]] = results['pts_semantic_mask'][order] |
|
results['gt_semantic_seg'] = proj_sem_label |
|
return results |
|
|