Spaces:
Paused
Paused
from __future__ import print_function | |
import numpy as np | |
import open3d | |
import trimesh | |
import StructDiffusion.utils.transformations as tra | |
from StructDiffusion.utils.brain2.pose import make_pose | |
def get_camera_from_h5(h5): | |
""" Simple reference to help make these """ | |
proj_near = h5['cam_near'][()] | |
proj_far = h5['cam_far'][()] | |
proj_fov = h5['cam_fov'][()] | |
width = h5['cam_width'][()] | |
height = h5['cam_height'][()] | |
return GenericCameraReference(proj_near, proj_far, proj_fov, width, height) | |
class GenericCameraReference(object): | |
""" Class storing camera information and providing easy image capture """ | |
def __init__(self, proj_near=0.01, proj_far=5., proj_fov=60., img_width=640, | |
img_height=480): | |
self.proj_near = proj_near | |
self.proj_far = proj_far | |
self.proj_fov = proj_fov | |
self.img_width = img_width | |
self.img_height = img_height | |
self.x_offset = self.img_width / 2. | |
self.y_offset = self.img_height / 2. | |
# Compute focal params | |
aspect_ratio = self.img_width / self.img_height | |
e = 1 / (np.tan(np.radians(self.proj_fov/2.))) | |
t = self.proj_near / e | |
b = -t | |
r = t * aspect_ratio | |
l = -r | |
# pixels per meter | |
alpha = self.img_width / (r-l) | |
self.focal_length = self.proj_near * alpha | |
self.fx = self.focal_length | |
self.fy = self.focal_length | |
self.pose = None | |
self.inv_pose = None | |
def set_pose(self, trans, rot): | |
self.pose = make_pose(trans, rot) | |
self.inv_pose = tra.inverse_matrix(self.pose) | |
def set_pose_matrix(self, matrix): | |
self.pose = matrix | |
self.inv_pose = tra.inverse_matrix(matrix) | |
def transform_to_world_coords(self, xyz): | |
""" transform xyz into world coordinates """ | |
#cam_pose = tra.inverse_matrix(self.pose).dot(tra.euler_matrix(np.pi, 0, 0)) | |
#xyz = trimesh.transform_points(xyz, self.inv_pose) | |
#xyz = trimesh.transform_points(xyz, cam_pose) | |
#pose = tra.euler_matrix(np.pi, 0, 0) @ self.pose | |
pose = self.pose | |
xyz = trimesh.transform_points(xyz, pose) | |
return xyz | |
def get_camera_presets(): | |
return [ | |
"n/a", | |
"azure_depth_nfov", | |
"realsense", | |
"azure_720p", | |
"simple256", | |
"simple512", | |
] | |
def get_camera_preset(name): | |
if name == "azure_depth_nfov": | |
# Setting for depth camera is pretty different from RGB | |
height, width, fov = 576, 640, 75 | |
if name == "azure_720p": | |
# This is actually the 720p RGB setting | |
# Used for our color camera most of the time | |
#height, width, fov = 720, 1280, 90 | |
height, width, fov = 720, 1280, 60 | |
elif name == "realsense": | |
height, width, fov = 480, 640, 60 | |
elif name == "simple256": | |
height, width, fov = 256, 256, 60 | |
elif name == "simple512": | |
height, width, fov = 512, 512, 60 | |
else: | |
raise RuntimeError(('camera "%s" not supported, choose from: ' + | |
str(get_camera_presets())) % str(name)) | |
return height, width, fov | |
def get_generic_camera(name): | |
h, w, fov = get_camera_preset(name) | |
return GenericCameraReference(img_height=h, img_width=w, proj_fov=fov) | |
def get_matrix_of_indices(height, width): | |
""" Get indices """ | |
return np.indices((height, width), dtype=np.float32).transpose(1,2,0) | |
# -------------------------------------------------------- | |
# NOTE: this code taken from Arsalan and modified | |
def compute_xyz(depth_img, camera, visualize_xyz=False, | |
xmap=None, ymap=None, max_clip_depth=5): | |
""" Compute xyz image from depth for a camera """ | |
# We need thes eparameters | |
height = camera.img_height | |
width = camera.img_width | |
assert depth_img.shape[0] == camera.img_height | |
assert depth_img.shape[1] == camera.img_width | |
fx = camera.fx | |
fy = camera.fy | |
cx = camera.x_offset | |
cy = camera.y_offset | |
""" | |
# Create the matrix of parameters | |
indices = np.indices((height, width), dtype=np.float32).transpose(1,2,0) | |
# pixel indices start at top-left corner. for these equations, it starts at bottom-left | |
# indices[..., 0] = np.flipud(indices[..., 0]) | |
z_e = depth_img | |
x_e = (indices[..., 1] - x_offset) * z_e / fx | |
y_e = (indices[..., 0] - y_offset) * z_e / fy | |
xyz_img = np.stack([x_e, y_e, z_e], axis=-1) # Shape: [H x W x 3] | |
""" | |
height = depth_img.shape[0] | |
width = depth_img.shape[1] | |
input_x = np.arange(width) | |
input_y = np.arange(height) | |
input_x, input_y = np.meshgrid(input_x, input_y) | |
input_x = input_x.flatten() | |
input_y = input_y.flatten() | |
input_z = depth_img.flatten() | |
# clip points that are farther than max distance | |
input_z[input_z > max_clip_depth] = 0 | |
output_x = (input_x * input_z - cx * input_z) / fx | |
output_y = (input_y * input_z - cy * input_z) / fy | |
raw_pc = np.stack([output_x, output_y, input_z], -1).reshape( | |
height, width, 3 | |
) | |
return raw_pc | |
if visualize_xyz: | |
unordered_pc = xyz_img.reshape(-1, 3) | |
pcd = open3d.geometry.PointCloud() | |
pcd.points = open3d.utility.Vector3dVector(unordered_pc) | |
pcd.transform([[1,0,0,0], [0,1,0,0], [0,0,-1,0], [0,0,0,1]]) # Transform it so it's not upside down | |
open3d.visualization.draw_geometries([pcd]) | |
return xyz_img | |
def show_pcs(xyz, rgb): | |
""" Display point clouds """ | |
if len(xyz.shape) > 2: | |
unordered_pc = xyz.reshape(-1, 3) | |
unordered_rgb = rgb.reshape(-1, 3) / 255. | |
assert(unordered_rgb.shape[0] == unordered_pc.shape[0]) | |
assert(unordered_pc.shape[1] == 3) | |
assert(unordered_rgb.shape[1] == 3) | |
pcd = open3d.geometry.PointCloud() | |
pcd.points = open3d.utility.Vector3dVector(unordered_pc) | |
pcd.colors = open3d.utility.Vector3dVector(unordered_rgb) | |
pcd.transform([[1,0,0,0],[0,1,0,0],[0,0,-1,0],[0,0,0,1]]) # Transform it so it's not upside down | |
open3d.visualization.draw_geometries([pcd]) | |