|
""" |
|
Adapted from https://github.com/thusiyuan/cooperative_scene_parsing/blob/master/utils/sunrgbd_utils.py |
|
""" |
|
import numpy as np |
|
|
|
|
|
def normalize(vector): |
|
return vector / np.linalg.norm(vector) |
|
|
|
|
|
def parse_camera_info(camera_info, height, width, inverse=False): |
|
""" extract intrinsic and extrinsic matrix |
|
""" |
|
lookat = normalize(camera_info[3:6]) |
|
up = normalize(camera_info[6:9]) |
|
|
|
W = lookat |
|
U = np.cross(W, up) |
|
V = - np.cross(W, U) |
|
|
|
if inverse: |
|
rot = np.linalg.inv(np.vstack((U, -V, W))) |
|
trans = camera_info[:3] |
|
else: |
|
rot = np.vstack((U, V, W)) |
|
trans = camera_info[:3] |
|
|
|
xfov = camera_info[9] |
|
yfov = camera_info[10] |
|
|
|
K = np.diag([1, 1, 1]).astype(np.float32) |
|
|
|
K[0, 2] = (width) / 2. |
|
K[1, 2] = (height) / 2. |
|
|
|
K[0, 0] = K[0, 2] / np.tan(xfov) |
|
K[1, 1] = K[1, 2] / np.tan(yfov) |
|
|
|
|
|
|
|
|
|
return rot, trans, K |
|
|
|
|
|
def flip_towards_viewer(normals, points): |
|
points = points / np.linalg.norm(points) |
|
proj = points.dot(normals[:2, :].T) |
|
flip = np.where(proj > 0) |
|
normals[flip, :] = -normals[flip, :] |
|
return normals |
|
|
|
|
|
def get_corners_of_bb3d(basis, coeffs, centroid): |
|
corners = np.zeros((8, 3)) |
|
|
|
index = np.argsort(np.abs(basis[:, 0]))[::-1] |
|
|
|
if index[2] != 2: |
|
index[1:] = index[1:][::-1] |
|
basis = basis[index, :] |
|
coeffs = coeffs[index] |
|
|
|
basis = flip_towards_viewer(basis, centroid) |
|
coeffs = np.abs(coeffs) |
|
corners[0, :] = -basis[0, :] * coeffs[0] + basis[1, :] * coeffs[1] + basis[2, :] * coeffs[2] |
|
corners[1, :] = basis[0, :] * coeffs[0] + basis[1, :] * coeffs[1] + basis[2, :] * coeffs[2] |
|
corners[2, :] = basis[0, :] * coeffs[0] + -basis[1, :] * coeffs[1] + basis[2, :] * coeffs[2] |
|
corners[3, :] = -basis[0, :] * coeffs[0] + -basis[1, :] * coeffs[1] + basis[2, :] * coeffs[2] |
|
|
|
corners[4, :] = -basis[0, :] * coeffs[0] + basis[1, :] * coeffs[1] + -basis[2, :] * coeffs[2] |
|
corners[5, :] = basis[0, :] * coeffs[0] + basis[1, :] * coeffs[1] + -basis[2, :] * coeffs[2] |
|
corners[6, :] = basis[0, :] * coeffs[0] + -basis[1, :] * coeffs[1] + -basis[2, :] * coeffs[2] |
|
corners[7, :] = -basis[0, :] * coeffs[0] + -basis[1, :] * coeffs[1] + -basis[2, :] * coeffs[2] |
|
corners = corners + np.tile(centroid, (8, 1)) |
|
return corners |
|
|
|
|
|
def get_corners_of_bb3d_no_index(basis, coeffs, centroid): |
|
corners = np.zeros((8, 3)) |
|
coeffs = np.abs(coeffs) |
|
corners[0, :] = -basis[0, :] * coeffs[0] + basis[1, :] * coeffs[1] + basis[2, :] * coeffs[2] |
|
corners[1, :] = basis[0, :] * coeffs[0] + basis[1, :] * coeffs[1] + basis[2, :] * coeffs[2] |
|
corners[2, :] = basis[0, :] * coeffs[0] + -basis[1, :] * coeffs[1] + basis[2, :] * coeffs[2] |
|
corners[3, :] = -basis[0, :] * coeffs[0] + -basis[1, :] * coeffs[1] + basis[2, :] * coeffs[2] |
|
|
|
corners[4, :] = -basis[0, :] * coeffs[0] + basis[1, :] * coeffs[1] + -basis[2, :] * coeffs[2] |
|
corners[5, :] = basis[0, :] * coeffs[0] + basis[1, :] * coeffs[1] + -basis[2, :] * coeffs[2] |
|
corners[6, :] = basis[0, :] * coeffs[0] + -basis[1, :] * coeffs[1] + -basis[2, :] * coeffs[2] |
|
corners[7, :] = -basis[0, :] * coeffs[0] + -basis[1, :] * coeffs[1] + -basis[2, :] * coeffs[2] |
|
|
|
corners = corners + np.tile(centroid, (8, 1)) |
|
return corners |
|
|
|
|
|
def project_3d_points_to_2d(points3d, R_ex, K): |
|
""" |
|
Project 3d points from camera-centered coordinate to 2D image plane |
|
Parameters |
|
---------- |
|
points3d: numpy array |
|
3d location of point |
|
R_ex: numpy array |
|
extrinsic camera parameter |
|
K: numpy array |
|
intrinsic camera parameter |
|
Returns |
|
------- |
|
points2d: numpy array |
|
2d location of the point |
|
""" |
|
points3d = R_ex.dot(points3d.T).T |
|
x3 = points3d[:, 0] |
|
y3 = -points3d[:, 1] |
|
z3 = np.abs(points3d[:, 2]) |
|
xx = x3 * K[0, 0] / z3 + K[0, 2] |
|
yy = y3 * K[1, 1] / z3 + K[1, 2] |
|
points2d = np.vstack((xx, yy)) |
|
return points2d |
|
|
|
|
|
def project_struct_bdb_to_2d(basis, coeffs, center, R_ex, K): |
|
""" |
|
Project 3d bounding box to 2d bounding box |
|
Parameters |
|
---------- |
|
basis, coeffs, center, R_ex, K |
|
: K is the intrinsic camera parameter matrix |
|
: Rtilt is the extrinsic camera parameter matrix in right hand coordinates |
|
Returns |
|
------- |
|
bdb2d: dict |
|
Keys: {'x1', 'x2', 'y1', 'y2'} |
|
The (x1, y1) position is at the top left corner, |
|
the (x2, y2) position is at the bottom right corner |
|
""" |
|
corners3d = get_corners_of_bb3d(basis, coeffs, center) |
|
corners = project_3d_points_to_2d(corners3d, R_ex, K) |
|
bdb2d = dict() |
|
bdb2d['x1'] = int(max(np.min(corners[0, :]), 1)) |
|
bdb2d['y1'] = int(max(np.min(corners[1, :]), 1)) |
|
bdb2d['x2'] = int(min(np.max(corners[0, :]), 2*K[0, 2])) |
|
bdb2d['y2'] = int(min(np.max(corners[1, :]), 2*K[1, 2])) |
|
|
|
|
|
return bdb2d |
|
|