| import torch |
| import numpy as np |
| import math |
| import cv2 |
|
|
| world_mat_object = torch.tensor([ |
| [0.5085, 0.3226, 0.7984, 0.0000], |
| [-0.3479, 0.9251, -0.1522, 0.0000], |
| [-0.7877, -0.2003, 0.5826, 0.3384], |
| [0.0000, 0.0000, 0.0000, 1.0000] |
| ]) |
|
|
| world_mat_inv = torch.tensor([ |
| [0.4019, 0.9157, 0.0000, 0.3359], |
| [-0.1932, 0.0848, 0.9775, -1.0227], |
| [0.8951, -0.3928, 0.2110, -7.0748], |
| [-0.0000, 0.0000, -0.0000, 1.0000] |
| ]) |
|
|
|
|
| proj = torch.tensor([ |
| [2.1875, 0.0000, 0.0000, 0.0000], |
| [0.0000, 3.8889, 0.0000, 0.0000], |
| [0.0000, 0.0000, -1.0020, -0.2002], |
| [0.0000, 0.0000, -1.0000, 0.0000] |
| ]) |
|
|
|
|
| RANGES = [[0, 540], [100, 960]] |
|
|
| TARGET = [500, -1] |
|
|
|
|
| def resize(img): |
| if TARGET[1] == -1: |
| r = img.shape[0] / img.shape[1] |
| img = cv2.resize(img, (TARGET[0], int(r * TARGET[0]))) |
| else: |
| img = cv2.resize(img, (TARGET[0], TARGET[1])) |
|
|
| return img |
|
|
|
|
| def scatter(u_pix, v_pix, distances, res, radius=5): |
| distances -= 6 |
| img = np.zeros(res) |
| for (u, v, d) in zip(u_pix, v_pix, distances): |
| v, u = int(v), int(u) |
| f = np.exp(-d / 0.7) |
| if radius == 0: |
| img[v, u] = max(img[v, u], f) |
| else: |
| for t1 in range(-radius, radius): |
| for t2 in range(-radius, radius): |
| ty, tx = v - t1, u - t2 |
| ty, tx = max(0, ty), max(0, tx) |
| ty, tx = min(res[0] - 1, ty), min(res[1] - 1, tx) |
| img[ty, tx] = max(img[ty, tx], f) |
|
|
| return img |
|
|
|
|
| def generate_roation(phi_x, phi_y, phi_z): |
| def Rx(theta): |
| return torch.tensor([[1, 0, 0], |
| [0, math.cos(theta), -math.sin(theta)], |
| [0, math.sin(theta), math.cos(theta)]]) |
|
|
| def Ry(theta): |
| return torch.tensor([[math.cos(theta), 0, math.sin(theta)], |
| [0, 1, 0], |
| [-math.sin(theta), 0, math.cos(theta)]]) |
|
|
| def Rz(theta): |
| return torch.tensor([[math.cos(theta), -math.sin(theta), 0], |
| [math.sin(theta), math.cos(theta), 0], |
| [0, 0, 1]]) |
|
|
| return Rz(phi_z) @ Ry(phi_y) @ Rx(phi_x) |
|
|
|
|
| def rotate_pc(pc, rx, ry, rz): |
| rotation = generate_roation(rx, ry, rz) |
| rotated = pc.clone() |
| rotated[:, :3] = rotated[:, :3] @ rotation.T |
| if rotated.shape[-1] == 6: |
| rotated[:, 3:] = rotated[:, 3:] @ rotation.T |
| return rotated |
|
|
|
|
| def draw_pc(pc: torch.Tensor, res=(540, 960), radius=5, timer=None, dy=0, scale=1): |
| xyz = pc[:, :3] |
| xyz -= xyz.mean(dim=0) |
| t_scale = xyz.norm(dim=-1).max() |
| xyz /= t_scale |
| xyz *= scale |
|
|
| xyz[:, -1] += xyz[:, -1].min() |
|
|
| n, _ = xyz.shape |
|
|
| if timer is not None: |
| with timer('project'): |
| xyz_pad = torch.cat([xyz, torch.ones_like(pc[:, :1])], dim=-1) |
| xyz_local = xyz_pad @ world_mat_inv.T |
| distances = -xyz_local[:, 2] |
|
|
| projected = xyz_local @ proj.T |
| projected = projected / projected[:, 3:4] |
| projected = projected[:, :3] |
|
|
| u_pix = ((projected[0] + 1) / 2) * res[1] |
| v_pix = ((projected[1] + 1) / 2) * res[0] + dy |
|
|
| with timer('z-buffer'): |
| z_buffer = scatter(u_pix, v_pix, distances, res, radius=radius)[:, :] |
| else: |
| xyz_pad = torch.cat([xyz, torch.ones_like(pc[:, :1])], dim=-1) |
| xyz_local = xyz_pad @ world_mat_inv.T |
| distances = -xyz_local[:, 2] |
|
|
| projected = xyz_local @ proj.T |
| projected = projected / projected[:, 3:4] |
| projected = projected[:, :3] |
|
|
| u_pix = ((projected[:, 0] + 1) / 2) * res[1] |
| v_pix = ((projected[:, 1] + 1) / 2) * res[0] + dy |
|
|
| z_buffer = scatter(u_pix, v_pix, distances, res, radius=radius)[:, :] |
|
|
| z_buffer = z_buffer[RANGES[0][0]: RANGES[0][1], :] |
| z_buffer = z_buffer[:, RANGES[1][0]:RANGES[1][1]] |
| z_buffer = resize(z_buffer) |
| return z_buffer |
|
|
|
|