|
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 |
|
|
|
|