Spaces:
Paused
Paused
| import copy | |
| import os | |
| import torch | |
| import trimesh | |
| import numpy as np | |
| import open3d | |
| from PIL import Image, ImageDraw, ImageFont | |
| from sklearn.metrics import classification_report | |
| from collections import defaultdict | |
| import matplotlib.pyplot as plt | |
| import itertools | |
| import matplotlib | |
| import h5py | |
| import json | |
| import StructDiffusion.utils.transformations as tra | |
| from StructDiffusion.utils.rotation_continuity import compute_geodesic_distance_from_two_matrices | |
| # from pointnet_utils import farthest_point_sample, index_points | |
| def flatten1d(img): | |
| return img.reshape(-1) | |
| def flatten3d(img): | |
| hw = img.shape[0] * img.shape[1] | |
| return img.reshape(hw, -1) | |
| def array_to_tensor(array): | |
| """ Assume arrays are in numpy (channels-last) format and put them into the right one """ | |
| if array.ndim == 4: # NHWC | |
| tensor = torch.from_numpy(array).permute(0,3,1,2).float() | |
| elif array.ndim == 3: # HWC | |
| tensor = torch.from_numpy(array).permute(2,0,1).float() | |
| else: # everything else - just keep it as-is | |
| tensor = torch.from_numpy(array).float() | |
| return tensor | |
| def get_pts(xyz_in, rgb_in, mask, bg_mask=None, num_pts=1024, center=None, | |
| radius=0.5, filename=None, to_tensor=True): | |
| # Get the XYZ and RGB | |
| mask = flatten1d(mask) | |
| assert(np.sum(mask) > 0) | |
| xyz = flatten3d(xyz_in)[mask > 0] | |
| if rgb_in is not None: | |
| rgb = flatten3d(rgb_in)[mask > 0] | |
| if xyz.shape[0] == 0: | |
| raise RuntimeError('this should not happen') | |
| ok = False | |
| xyz = flatten3d(xyz_in) | |
| if rgb_in is not None: | |
| rgb = flatten3d(rgb_in) | |
| else: | |
| ok = True | |
| # prune to this region | |
| if center is not None: | |
| # numpy matrix | |
| # use the full xyz point cloud to determine what is close enough | |
| # now that we have the closest background point we can place the object on it | |
| # Just center on the point | |
| center = center.numpy() | |
| center = center[None].repeat(xyz.shape[0], axis=0) | |
| dists = np.linalg.norm(xyz - center, axis=-1) | |
| idx = dists < radius | |
| xyz = xyz[idx] | |
| if rgb_in is not None: | |
| rgb = rgb[idx] | |
| center = center[0] | |
| else: | |
| center = None | |
| # Compute number of points we are using | |
| if num_pts is not None: | |
| if xyz.shape[0] < 1: | |
| print("!!!! bad shape:", xyz.shape, filename, "!!!!") | |
| return (None, None, None, None) | |
| idx = np.random.randint(0, xyz.shape[0], num_pts) | |
| xyz = xyz[idx] | |
| if rgb_in is not None: | |
| rgb = rgb[idx] | |
| # Shuffle the points | |
| if rgb_in is not None: | |
| rgb = array_to_tensor(rgb) if to_tensor else rgb | |
| else: | |
| rgb = None | |
| xyz = array_to_tensor(xyz) if to_tensor else xyz | |
| return (ok, xyz, rgb, center) | |
| def align(y_true, y_pred): | |
| """ Add or remove 2*pi to predicted angle to minimize difference from GT""" | |
| y_pred = y_pred.copy() | |
| y_pred[y_true - y_pred > np.pi] += np.pi * 2 | |
| y_pred[y_true - y_pred < -np.pi] -= np.pi * 2 | |
| return y_pred | |
| def random_move_obj_xyz(obj_xyz, | |
| min_translation, max_translation, | |
| min_rotation, max_rotation, mode, | |
| visualize=False, return_perturbed_obj_xyzs=True): | |
| assert mode in ["planar", "6d", "3d_planar"] | |
| if mode == "planar": | |
| random_translation = np.random.uniform(low=min_translation, high=max_translation, size=2) * np.random.choice( | |
| [-1, 1], size=2) | |
| random_rotation = np.random.uniform(low=min_rotation, high=max_rotation) * np.random.choice([-1, 1]) | |
| random_rotation = tra.euler_matrix(0, 0, random_rotation) | |
| elif mode == "6d": | |
| random_rotation = np.random.uniform(low=min_rotation, high=max_rotation, size=3) * np.random.choice([-1, 1], size=3) | |
| random_rotation = tra.euler_matrix(*random_rotation) | |
| random_translation = np.random.uniform(low=min_translation, high=max_translation, size=3) * np.random.choice([-1, 1], size=3) | |
| elif mode == "3d_planar": | |
| random_translation = np.random.uniform(low=min_translation, high=max_translation, size=3) * np.random.choice( | |
| [-1, 1], size=3) | |
| random_rotation = np.random.uniform(low=min_rotation, high=max_rotation) * np.random.choice([-1, 1]) | |
| random_rotation = tra.euler_matrix(0, 0, random_rotation) | |
| if return_perturbed_obj_xyzs: | |
| raise Exception("return_perturbed_obj_xyzs=True is no longer supported") | |
| # xyz_mean = np.mean(obj_xyz, axis=0) | |
| # new_obj_xyz = obj_xyz - xyz_mean | |
| # new_obj_xyz = trimesh.transform_points(new_obj_xyz, random_rotation, translate=False) | |
| # new_obj_xyz = new_obj_xyz + xyz_mean + random_translation | |
| else: | |
| new_obj_xyz = obj_xyz | |
| # test moving the perturbed obj pc back | |
| # new_xyz_mean = np.mean(new_obj_xyz, axis=0) | |
| # old_obj_xyz = new_obj_xyz - new_xyz_mean | |
| # old_obj_xyz = trimesh.transform_points(old_obj_xyz, np.linalg.inv(random_rotation), translate=False) | |
| # old_obj_xyz = old_obj_xyz + new_xyz_mean - random_translation | |
| # even though we are putting perturbation rotation and translation in the same matrix, they should be applied | |
| # independently. More specifically, rotate the object pc in place and then translate it. | |
| perturbation_matrix = random_rotation | |
| perturbation_matrix[:3, 3] = random_translation | |
| if visualize: | |
| show_pcs([new_obj_xyz, obj_xyz], | |
| [np.tile(np.array([1, 0, 0], dtype=np.float), (obj_xyz.shape[0], 1)), | |
| np.tile(np.array([0, 1, 0], dtype=np.float), (obj_xyz.shape[0], 1))], add_coordinate_frame=True) | |
| return new_obj_xyz, perturbation_matrix | |
| def random_move_obj_xyzs(obj_xyzs, | |
| min_translation, max_translation, | |
| min_rotation, max_rotation, mode, move_obj_idxs=None, visualize=False, return_moved_obj_idxs=False, | |
| return_perturbation=False, return_perturbed_obj_xyzs=True): | |
| """ | |
| :param obj_xyzs: | |
| :param min_translation: | |
| :param max_translation: | |
| :param min_rotation: | |
| :param max_rotation: | |
| :param mode: | |
| :param move_obj_idxs: | |
| :param visualize: | |
| :param return_moved_obj_idxs: | |
| :param return_perturbation: | |
| :param return_perturbed_obj_xyzs: | |
| :return: | |
| """ | |
| new_obj_xyzs = [] | |
| new_obj_rgbs = [] | |
| old_obj_rgbs = [] | |
| perturbation_matrices = [] | |
| if move_obj_idxs is None: | |
| move_obj_idxs = list(range(len(obj_xyzs))) | |
| # this many objects will not be randomly moved | |
| stationary_obj_idxs = np.random.choice(move_obj_idxs, np.random.randint(0, len(move_obj_idxs)), replace=False).tolist() | |
| moved_obj_idxs = [] | |
| for obj_idx, obj_xyz in enumerate(obj_xyzs): | |
| if obj_idx in stationary_obj_idxs: | |
| new_obj_xyzs.append(obj_xyz) | |
| perturbation_matrices.append(np.eye(4)) | |
| if visualize: | |
| new_obj_rgbs.append(np.tile(np.array([1, 0, 0], dtype=np.float), (obj_xyz.shape[0], 1))) | |
| old_obj_rgbs.append(np.tile(np.array([0, 0, 1], dtype=np.float), (obj_xyz.shape[0], 1))) | |
| else: | |
| new_obj_xyz, perturbation_matrix = random_move_obj_xyz(obj_xyz, | |
| min_translation=min_translation, max_translation=max_translation, | |
| min_rotation=min_rotation, max_rotation=max_rotation, mode=mode, | |
| return_perturbed_obj_xyzs=return_perturbed_obj_xyzs) | |
| new_obj_xyzs.append(new_obj_xyz) | |
| moved_obj_idxs.append(obj_idx) | |
| perturbation_matrices.append(perturbation_matrix) | |
| if visualize: | |
| new_obj_rgbs.append(np.tile(np.array([1, 0, 0], dtype=np.float), (obj_xyz.shape[0], 1))) | |
| old_obj_rgbs.append(np.tile(np.array([0, 1, 0], dtype=np.float), (obj_xyz.shape[0], 1))) | |
| if visualize: | |
| show_pcs(new_obj_xyzs + obj_xyzs, | |
| new_obj_rgbs + old_obj_rgbs, add_coordinate_frame=True) | |
| if return_moved_obj_idxs: | |
| if return_perturbation: | |
| return new_obj_xyzs, moved_obj_idxs, perturbation_matrices | |
| else: | |
| return new_obj_xyzs, moved_obj_idxs | |
| else: | |
| if return_perturbation: | |
| return new_obj_xyzs, perturbation_matrices | |
| else: | |
| return new_obj_xyzs | |
| def check_pairwise_collision(pcs, visualize=False): | |
| voxel_extents = [0.005] * 3 | |
| collision_managers = [] | |
| collision_objects = [] | |
| for pc in pcs: | |
| # farthest point sample | |
| pc = pc.unsqueeze(0) | |
| fps_idx = farthest_point_sample(pc, 100) # [B, npoint] | |
| pc = index_points(pc, fps_idx).squeeze(0) | |
| pc = np.asanyarray(pc) | |
| # ignore empty pc | |
| if np.all(pc == 0): | |
| continue | |
| n_points = pc.shape[0] | |
| collision_object = [] | |
| collision_manager = trimesh.collision.CollisionManager() | |
| # Construct collision objects | |
| for i in range(n_points): | |
| extents = voxel_extents | |
| transform = np.eye(4) | |
| transform[:3, 3] = pc[i, :3] | |
| voxel = trimesh.primitives.Box(extents=extents, transform=transform) | |
| collision_object.append((voxel, extents, transform)) | |
| # Add to collision manager | |
| for i, (voxel, _, _) in enumerate(collision_object): | |
| collision_manager.add_object("voxel_{}".format(i), voxel) | |
| collision_managers.append(collision_manager) | |
| collision_objects.append(collision_object) | |
| in_collision = False | |
| for i, cm_i in enumerate(collision_managers): | |
| for j, cm_j in enumerate(collision_managers): | |
| if i == j: | |
| continue | |
| if cm_i.in_collision_other(cm_j): | |
| in_collision = True | |
| if visualize: | |
| visualize_collision_objects(collision_objects[i] + collision_objects[j]) | |
| break | |
| if in_collision: | |
| break | |
| return in_collision | |
| def check_collision_with(this_pc, other_pcs, visualize=False): | |
| voxel_extents = [0.005] * 3 | |
| this_collision_manager = None | |
| this_collision_object = None | |
| other_collision_managers = [] | |
| other_collision_objects = [] | |
| for oi, pc in enumerate([this_pc] + other_pcs): | |
| # farthest point sample | |
| pc = pc.unsqueeze(0) | |
| fps_idx = farthest_point_sample(pc, 100) # [B, npoint] | |
| pc = index_points(pc, fps_idx).squeeze(0) | |
| pc = np.asanyarray(pc) | |
| # ignore empty pc | |
| if np.all(pc == 0): | |
| continue | |
| n_points = pc.shape[0] | |
| collision_object = [] | |
| collision_manager = trimesh.collision.CollisionManager() | |
| # Construct collision objects | |
| for i in range(n_points): | |
| extents = voxel_extents | |
| transform = np.eye(4) | |
| transform[:3, 3] = pc[i, :3] | |
| voxel = trimesh.primitives.Box(extents=extents, transform=transform) | |
| collision_object.append((voxel, extents, transform)) | |
| # Add to collision manager | |
| for i, (voxel, _, _) in enumerate(collision_object): | |
| collision_manager.add_object("voxel_{}".format(i), voxel) | |
| if oi == 0: | |
| this_collision_manager = collision_manager | |
| this_collision_object = collision_object | |
| else: | |
| other_collision_managers.append(collision_manager) | |
| other_collision_objects.append(collision_object) | |
| collisions = [] | |
| for i, cm_i in enumerate(other_collision_managers): | |
| if this_collision_manager.in_collision_other(cm_i): | |
| collisions.append(i) | |
| if visualize: | |
| visualize_collision_objects(this_collision_object + other_collision_objects[i]) | |
| return collisions | |
| def visualize_collision_objects(collision_objects): | |
| # Convert from trimesh to open3d | |
| meshes_o3d = [] | |
| for elem in collision_objects: | |
| (voxel, extents, transform) = elem | |
| voxel_o3d = open3d.geometry.TriangleMesh.create_box(width=extents[0], height=extents[1], | |
| depth=extents[2]) | |
| voxel_o3d.compute_vertex_normals() | |
| voxel_o3d.paint_uniform_color([0.8, 0.2, 0]) | |
| voxel_o3d.transform(transform) | |
| meshes_o3d.append(voxel_o3d) | |
| meshes = meshes_o3d | |
| vis = open3d.visualization.Visualizer() | |
| vis.create_window() | |
| for mesh in meshes: | |
| vis.add_geometry(mesh) | |
| vis.run() | |
| vis.destroy_window() | |
| # def test_collision(pc): | |
| # n_points = pc.shape[0] | |
| # voxel_extents = [0.005] * 3 | |
| # collision_objects = [] | |
| # collision_manager = trimesh.collision.CollisionManager() | |
| # | |
| # # Construct collision objects | |
| # for i in range(n_points): | |
| # extents = voxel_extents | |
| # transform = np.eye(4) | |
| # transform[:3, 3] = pc[i, :3] | |
| # voxel = trimesh.primitives.Box(extents=extents, transform=transform) | |
| # collision_objects.append((voxel, extents, transform)) | |
| # | |
| # # Add to collision manager | |
| # for i, (voxel, _, _) in enumerate(collision_objects): | |
| # collision_manager.add_object("voxel_{}".format(i), voxel) | |
| # | |
| # for i, (voxel, _, _) in enumerate(collision_objects): | |
| # c, names = collision_manager.in_collision_single(voxel, return_names=True) | |
| # if c: | |
| # print(i, names) | |
| # | |
| # # Convert from trimesh to open3d | |
| # meshes_o3d = [] | |
| # for elem in collision_objects: | |
| # (voxel, extents, transform) = elem | |
| # voxel_o3d = open3d.geometry.TriangleMesh.create_box(width=extents[0], height=extents[1], | |
| # depth=extents[2]) | |
| # voxel_o3d.compute_vertex_normals() | |
| # voxel_o3d.paint_uniform_color([0.8, 0.2, 0]) | |
| # voxel_o3d.transform(transform) | |
| # meshes_o3d.append(voxel_o3d) | |
| # meshes = meshes_o3d | |
| # | |
| # vis = open3d.visualization.Visualizer() | |
| # vis.create_window() | |
| # | |
| # for mesh in meshes: | |
| # vis.add_geometry(mesh) | |
| # | |
| # vis.run() | |
| # vis.destroy_window() | |
| # | |
| # | |
| # def test_collision2(pc): | |
| # pcd = open3d.geometry.PointCloud() | |
| # pcd.points = open3d.utility.Vector3dVector(pc) | |
| # pcd.estimate_normals() | |
| # open3d.visualization.draw_geometries([pcd]) | |
| # | |
| # # poisson_mesh = open3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd, depth=8, width=0, scale=1.1, linear_fit=False)[0] | |
| # # bbox = pcd.get_axis_aligned_bounding_box() | |
| # # p_mesh_crop = poisson_mesh.crop(bbox) | |
| # # open3d.visualization.draw_geometries([p_mesh_crop, pcd]) | |
| # | |
| # distances = pcd.compute_nearest_neighbor_distance() | |
| # avg_dist = np.mean(distances) | |
| # radius = 3 * avg_dist | |
| # bpa_mesh = open3d.geometry.TriangleMesh.create_from_point_cloud_ball_pivoting(pcd, open3d.utility.DoubleVector( | |
| # [radius, radius * 2])) | |
| # dec_mesh = bpa_mesh.simplify_quadric_decimation(100000) | |
| # dec_mesh.remove_degenerate_triangles() | |
| # dec_mesh.remove_duplicated_triangles() | |
| # dec_mesh.remove_duplicated_vertices() | |
| # dec_mesh.remove_non_manifold_edges() | |
| # open3d.visualization.draw_geometries([dec_mesh, pcd]) | |
| # open3d.visualization.draw_geometries([dec_mesh]) | |
| def make_gifs(imgs, save_path, texts=None, numpy_img=True, duration=10): | |
| gif_filename = os.path.join(save_path) | |
| pil_imgs = [] | |
| for i, img in enumerate(imgs): | |
| if numpy_img: | |
| img = Image.fromarray(img) | |
| if texts: | |
| text = texts[i] | |
| draw = ImageDraw.Draw(img) | |
| font = ImageFont.truetype("FreeMono.ttf", 40) | |
| draw.text((0, 0), text, (120, 120, 120), font=font) | |
| pil_imgs.append(img) | |
| pil_imgs[0].save(gif_filename, save_all=True, | |
| append_images=pil_imgs[1:], optimize=True, | |
| duration=duration*len(pil_imgs), loop=0) | |
| def save_img(img, save_path, text=None, numpy_img=True): | |
| if numpy_img: | |
| img = Image.fromarray(img) | |
| if text: | |
| draw = ImageDraw.Draw(img) | |
| font = ImageFont.truetype("FreeMono.ttf", 40) | |
| draw.text((0, 0), text, (120, 120, 120), font=font) | |
| img.save(save_path) | |
| def move_one_object_pc(obj_xyz, obj_rgb, struct_params, object_params, euler_angles=False): | |
| struct_params = np.asanyarray(struct_params) | |
| object_params = np.asanyarray(object_params) | |
| R_struct = np.eye(4) | |
| if not euler_angles: | |
| R_struct[:3, :3] = struct_params[3:].reshape(3, 3) | |
| else: | |
| R_struct[:3, :3] = tra.euler_matrix(*struct_params[3:])[:3, :3] | |
| R_obj = np.eye(4) | |
| if not euler_angles: | |
| R_obj[:3, :3] = object_params[3:].reshape(3, 3) | |
| else: | |
| R_obj[:3, :3] = tra.euler_matrix(*object_params[3:])[:3, :3] | |
| T_struct = R_struct | |
| T_struct[:3, 3] = [struct_params[0], struct_params[1], struct_params[2]] | |
| # translate to structure frame | |
| t = np.eye(4) | |
| obj_center = torch.mean(obj_xyz, dim=0) | |
| t[:3, 3] = [object_params[0] - obj_center[0], object_params[1] - obj_center[1], object_params[2] - obj_center[2]] | |
| new_obj_xyz = trimesh.transform_points(obj_xyz, t) | |
| # rotate in place | |
| R = R_obj | |
| obj_center = np.mean(new_obj_xyz, axis=0) | |
| centered_obj_xyz = new_obj_xyz - obj_center | |
| new_centered_obj_xyz = trimesh.transform_points(centered_obj_xyz, R, translate=True) | |
| new_obj_xyz = new_centered_obj_xyz + obj_center | |
| # transform to the global frame from the structure frame | |
| new_obj_xyz = trimesh.transform_points(new_obj_xyz, T_struct) | |
| # convert back to torch | |
| new_obj_xyz = torch.tensor(new_obj_xyz, dtype=obj_xyz.dtype) | |
| return new_obj_xyz, obj_rgb | |
| def move_one_object_pc_no_struct(obj_xyz, obj_rgb, object_params, euler_angles=False): | |
| object_params = np.asanyarray(object_params) | |
| R_obj = np.eye(4) | |
| if not euler_angles: | |
| R_obj[:3, :3] = object_params[3:].reshape(3, 3) | |
| else: | |
| R_obj[:3, :3] = tra.euler_matrix(*object_params[3:])[:3, :3] | |
| t = np.eye(4) | |
| obj_center = torch.mean(obj_xyz, dim=0) | |
| t[:3, 3] = [object_params[0] - obj_center[0], object_params[1] - obj_center[1], object_params[2] - obj_center[2]] | |
| new_obj_xyz = trimesh.transform_points(obj_xyz, t) | |
| # rotate in place | |
| R = R_obj | |
| obj_center = np.mean(new_obj_xyz, axis=0) | |
| centered_obj_xyz = new_obj_xyz - obj_center | |
| new_centered_obj_xyz = trimesh.transform_points(centered_obj_xyz, R, translate=True) | |
| new_obj_xyz = new_centered_obj_xyz + obj_center | |
| # convert back to torch | |
| new_obj_xyz = torch.tensor(new_obj_xyz, dtype=obj_xyz.dtype) | |
| return new_obj_xyz, obj_rgb | |
| def modify_language(sentence, radius=None, position_x=None, position_y=None, rotation=None, shape=None): | |
| # "radius": [0.0, 0.5, 3], "position_x": [-0.1, 1.0, 3], "position_y": [-0.5, 0.5, 3], "rotation": [-3.15, 3.15, 4] | |
| sentence = copy.deepcopy(sentence) | |
| for pi, pair in enumerate(sentence): | |
| if radius is not None and len(pair) == 2 and pair[1] == "radius": | |
| sentence[pi] = (radius, 'radius') | |
| if position_y is not None and len(pair) == 2 and pair[1] == "position_y": | |
| sentence[pi] = (position_y, 'position_y') | |
| if position_x is not None and len(pair) == 2 and pair[1] == "position_x": | |
| sentence[pi] = (position_x, 'position_x') | |
| if rotation is not None and len(pair) == 2 and pair[1] == "rotation": | |
| sentence[pi] = (rotation, 'rotation') | |
| if shape is not None and len(pair) == 2 and pair[1] == "shape": | |
| sentence[pi] = (shape, 'shape') | |
| return sentence | |
| def sample_gaussians(mus, sigmas, sample_size): | |
| # mus: [number of individual gaussians] | |
| # sigmas: [number of individual gaussians] | |
| normal = torch.distributions.Normal(mus, sigmas) | |
| samples = normal.sample((sample_size,)) | |
| # samples: [sample_size, number of individual gaussians] | |
| return samples | |
| def fit_gaussians(samples, sigma_eps=0.01): | |
| # samples: [sample_size, number of individual gaussians] | |
| num_gs = samples.shape[1] | |
| mus = torch.mean(samples, dim=0) | |
| sigmas = torch.std(samples, dim=0) + sigma_eps * torch.ones(num_gs) | |
| # mus: [number of individual gaussians] | |
| # sigmas: [number of individual gaussians] | |
| return mus, sigmas | |
| def show_pcs_with_trimesh(obj_xyzs, obj_rgbs=None, return_scene=False): | |
| if obj_rgbs is not None: | |
| vis_pcs = [trimesh.PointCloud(obj_xyz, colors=np.concatenate([obj_rgb * 255, np.ones([obj_rgb.shape[0], 1]) * 255], axis=-1)) for | |
| obj_xyz, obj_rgb in zip(obj_xyzs, obj_rgbs)] | |
| else: | |
| vis_pcs = [trimesh.PointCloud(obj_xyz) for obj_xyz in obj_xyzs] | |
| scene = trimesh.Scene() | |
| # add the coordinate frame first | |
| geom = trimesh.creation.axis(0.01) | |
| # scene.add_geometry(geom) | |
| table = trimesh.creation.box(extents=[1.0, 1.0, 0.02]) | |
| table.apply_translation([0.5, 0, -0.01]) | |
| table.visual.vertex_colors = [150, 111, 87, 125] | |
| scene.add_geometry(table) | |
| # bounds = trimesh.creation.box(extents=[4.0, 4.0, 4.0]) | |
| bounds = trimesh.creation.icosphere(subdivisions=3, radius=3.1) | |
| bounds.apply_translation([0, 0, 0]) | |
| bounds.visual.vertex_colors = [30, 30, 30, 30] | |
| # scene.add_geometry(bounds) | |
| scene.add_geometry(vis_pcs) | |
| RT_4x4 = np.array([[-0.39560353822208355, -0.9183993826406329, 0.006357240869497738, 0.2651463080169481], | |
| [-0.797630370081598, 0.3401340617616391, -0.4980909683511864, 0.2225696480721997], | |
| [0.45528412367406523, -0.2021172778236285, -0.8671014777611122, 0.9449050652025951], | |
| [0.0, 0.0, 0.0, 1.0]]) | |
| RT_4x4 = np.linalg.inv(RT_4x4) | |
| RT_4x4 = RT_4x4 @ np.diag([1, -1, -1, 1]) | |
| scene.camera_transform = RT_4x4 | |
| if return_scene: | |
| return scene | |
| else: | |
| scene.show() | |
| def get_trimesh_scene_with_table(): | |
| scene = trimesh.Scene() | |
| # add the coordinate frame first | |
| geom = trimesh.creation.axis(0.01) | |
| scene.add_geometry(geom) | |
| table = trimesh.creation.box(extents=[1.0, 1.0, 0.02]) | |
| table.apply_translation([0.5, 0, -0.01]) | |
| table.visual.vertex_colors = [150, 111, 87, 125] | |
| scene.add_geometry(table) | |
| # bounds = trimesh.creation.box(extents=[4.0, 4.0, 4.0]) | |
| bounds = trimesh.creation.icosphere(subdivisions=3, radius=3.1) | |
| bounds.apply_translation([0, 0, 0]) | |
| bounds.visual.vertex_colors = [30, 30, 30, 30] | |
| # scene.add_geometry(bounds) | |
| RT_4x4 = np.array([[-0.39560353822208355, -0.9183993826406329, 0.006357240869497738, 0.2651463080169481], | |
| [-0.797630370081598, 0.3401340617616391, -0.4980909683511864, 0.2225696480721997], | |
| [0.45528412367406523, -0.2021172778236285, -0.8671014777611122, 0.9449050652025951], | |
| [0.0, 0.0, 0.0, 1.0]]) | |
| RT_4x4 = np.linalg.inv(RT_4x4) | |
| RT_4x4 = RT_4x4 @ np.diag([1, -1, -1, 1]) | |
| scene.camera_transform = RT_4x4 | |
| return scene | |
| def show_pcs_with_predictions(xyz, rgb, gts, predictions, add_coordinate_frame=False, return_buffer=False, add_table=True, side_view=True): | |
| """ Display point clouds """ | |
| assert len(gts) == len(predictions) == len(xyz) == len(rgb) | |
| unordered_pc = np.concatenate(xyz, axis=0) | |
| unordered_rgb = np.concatenate(rgb, axis=0) | |
| pcd = open3d.geometry.PointCloud() | |
| pcd.points = open3d.utility.Vector3dVector(unordered_pc) | |
| pcd.colors = open3d.utility.Vector3dVector(unordered_rgb) | |
| vis = open3d.visualization.Visualizer() | |
| vis.create_window() | |
| vis.add_geometry(pcd) | |
| if add_table: | |
| table_color = [0.7, 0.7, 0.7] | |
| origin = [0, -0.5, -0.05] | |
| table = open3d.geometry.TriangleMesh.create_box(width=1.0, height=1.0, depth=0.02) | |
| table.paint_uniform_color(table_color) | |
| table.translate(origin) | |
| vis.add_geometry(table) | |
| if add_coordinate_frame: | |
| mesh_frame = open3d.geometry.TriangleMesh.create_coordinate_frame(size=0.1, origin=[0, 0, 0]) | |
| vis.add_geometry(mesh_frame) | |
| for i in range(len(xyz)): | |
| pred_color = [0.0, 1.0, 0] if predictions[i] else [1.0, 0.0, 0] | |
| gt_color = [0.0, 1.0, 0] if gts[i] else [1.0, 0.0, 0] | |
| origin = torch.mean(xyz[i], dim=0) | |
| origin[2] += 0.02 | |
| pred_vis = open3d.geometry.TriangleMesh.create_torus(torus_radius=0.02, tube_radius=0.01) | |
| pred_vis.paint_uniform_color(pred_color) | |
| pred_vis.translate(origin) | |
| gt_vis = open3d.geometry.TriangleMesh.create_sphere(radius=0.01) | |
| gt_vis.paint_uniform_color(gt_color) | |
| gt_vis.translate(origin) | |
| vis.add_geometry(pred_vis) | |
| vis.add_geometry(gt_vis) | |
| if side_view: | |
| open3d_set_side_view(vis) | |
| if return_buffer: | |
| vis.poll_events() | |
| vis.update_renderer() | |
| buffer = vis.capture_screen_float_buffer(False) | |
| vis.destroy_window() | |
| return buffer | |
| else: | |
| vis.run() | |
| vis.destroy_window() | |
| def show_pcs_with_only_predictions(xyz, rgb, gts, predictions, add_coordinate_frame=False, return_buffer=False, add_table=True, side_view=True): | |
| """ Display point clouds """ | |
| assert len(gts) == len(predictions) == len(xyz) == len(rgb) | |
| unordered_pc = np.concatenate(xyz, axis=0) | |
| unordered_rgb = np.concatenate(rgb, axis=0) | |
| pcd = open3d.geometry.PointCloud() | |
| pcd.points = open3d.utility.Vector3dVector(unordered_pc) | |
| pcd.colors = open3d.utility.Vector3dVector(unordered_rgb) | |
| vis = open3d.visualization.Visualizer() | |
| vis.create_window() | |
| vis.add_geometry(pcd) | |
| if add_table: | |
| table_color = [0.7, 0.7, 0.7] | |
| origin = [0, -0.5, -0.05] | |
| table = open3d.geometry.TriangleMesh.create_box(width=1.0, height=1.0, depth=0.02) | |
| table.paint_uniform_color(table_color) | |
| table.translate(origin) | |
| vis.add_geometry(table) | |
| if add_coordinate_frame: | |
| mesh_frame = open3d.geometry.TriangleMesh.create_coordinate_frame(size=0.1, origin=[0, 0, 0]) | |
| vis.add_geometry(mesh_frame) | |
| for i in range(len(xyz)): | |
| pred_color = [0.0, 1.0, 0] if predictions[i] else [1.0, 0.0, 0] | |
| pcd = open3d.geometry.PointCloud() | |
| pcd.points = open3d.utility.Vector3dVector(xyz[i]) | |
| pcd.colors = open3d.utility.Vector3dVector(np.tile(np.array(pred_color, dtype=np.float), (xyz[i].shape[0], 1))) | |
| # pcd = pcd.uniform_down_sample(10) | |
| # vis.add_geometry(pcd) | |
| obb = pcd.get_axis_aligned_bounding_box() | |
| obb.color = pred_color | |
| vis.add_geometry(obb) | |
| # origin = torch.mean(xyz[i], dim=0) | |
| # origin[2] += 0.02 | |
| # pred_vis = open3d.geometry.TriangleMesh.create_torus(torus_radius=0.02, tube_radius=0.01) | |
| # pred_vis.paint_uniform_color(pred_color) | |
| # pred_vis.translate(origin) | |
| # gt_vis = open3d.geometry.TriangleMesh.create_sphere(radius=0.01) | |
| # gt_vis.paint_uniform_color(gt_color) | |
| # gt_vis.translate(origin) | |
| # vis.add_geometry(pred_vis) | |
| # vis.add_geometry(gt_vis) | |
| if side_view: | |
| open3d_set_side_view(vis) | |
| if return_buffer: | |
| vis.poll_events() | |
| vis.update_renderer() | |
| buffer = vis.capture_screen_float_buffer(False) | |
| vis.destroy_window() | |
| return buffer | |
| else: | |
| vis.run() | |
| vis.destroy_window() | |
| def test_new_vis(xyz, rgb): | |
| pass | |
| # unordered_pc = np.concatenate(xyz, axis=0) | |
| # unordered_rgb = np.concatenate(rgb, axis=0) | |
| # pcd = open3d.geometry.PointCloud() | |
| # pcd.points = open3d.utility.Vector3dVector(unordered_pc) | |
| # pcd.colors = open3d.utility.Vector3dVector(unordered_rgb) | |
| # | |
| # # Some platforms do not require OpenGL implementations to support wide lines, | |
| # # so the renderer requires a custom shader to implement this: "unlitLine". | |
| # # The line_width field is only used by this shader; all other shaders ignore | |
| # # it. | |
| # # mat = o3d.visualization.rendering.Material() | |
| # # mat.shader = "unlitLine" | |
| # # mat.line_width = 10 # note that this is scaled with respect to pixels, | |
| # # # so will give different results depending on the | |
| # # # scaling values of your system | |
| # # mat.transmission = 0.5 | |
| # open3d.visualization.draw({ | |
| # "name": "pcd", | |
| # "geometry": pcd, | |
| # # "material": mat | |
| # }) | |
| # | |
| # for i in range(len(xyz)): | |
| # pred_color = [0.0, 1.0, 0] if predictions[i] else [1.0, 0.0, 0] | |
| # pcd = open3d.geometry.PointCloud() | |
| # pcd.points = open3d.utility.Vector3dVector(xyz[i]) | |
| # pcd.colors = open3d.utility.Vector3dVector(np.tile(np.array(pred_color, dtype=np.float), (xyz[i].shape[0], 1))) | |
| # # pcd = pcd.uniform_down_sample(10) | |
| # # vis.add_geometry(pcd) | |
| # | |
| # obb = pcd.get_axis_aligned_bounding_box() | |
| # obb.color = pred_color | |
| # vis.add_geometry(obb) | |
| def show_pcs(xyz, rgb, add_coordinate_frame=False, side_view=False, add_table=True): | |
| """ Display point clouds """ | |
| unordered_pc = np.concatenate(xyz, axis=0) | |
| unordered_rgb = np.concatenate(rgb, axis=0) | |
| pcd = open3d.geometry.PointCloud() | |
| pcd.points = open3d.utility.Vector3dVector(unordered_pc) | |
| pcd.colors = open3d.utility.Vector3dVector(unordered_rgb) | |
| if add_table: | |
| table_color = [0.78, 0.64, 0.44] | |
| origin = [0, -0.5, -0.02] | |
| table = open3d.geometry.TriangleMesh.create_box(width=1.0, height=1.0, depth=0.001) | |
| table.paint_uniform_color(table_color) | |
| table.translate(origin) | |
| if not add_coordinate_frame: | |
| vis = open3d.visualization.Visualizer() | |
| vis.create_window() | |
| vis.add_geometry(pcd) | |
| if add_table: | |
| vis.add_geometry(table) | |
| if side_view: | |
| open3d_set_side_view(vis) | |
| vis.run() | |
| vis.destroy_window() | |
| else: | |
| mesh_frame = open3d.geometry.TriangleMesh.create_coordinate_frame(size=0.1, origin=[0, 0, 0]) | |
| # open3d.visualization.draw_geometries([pcd, mesh_frame]) | |
| vis = open3d.visualization.Visualizer() | |
| vis.create_window() | |
| vis.add_geometry(pcd) | |
| vis.add_geometry(mesh_frame) | |
| if add_table: | |
| vis.add_geometry(table) | |
| if side_view: | |
| open3d_set_side_view(vis) | |
| vis.run() | |
| vis.destroy_window() | |
| def show_pcs_color_order(xyzs, rgbs, add_coordinate_frame=False, side_view=False, add_table=True, save_path=None, texts=None, visualize=False): | |
| rgb_colors = get_rgb_colors() | |
| order_rgbs = [] | |
| for i, xyz in enumerate(xyzs): | |
| order_rgbs.append(np.tile(np.array(rgb_colors[i][1], dtype=np.float), (xyz.shape[0], 1))) | |
| if visualize: | |
| show_pcs(xyzs, order_rgbs, add_coordinate_frame=add_coordinate_frame, side_view=side_view, add_table=add_table) | |
| if save_path: | |
| if not texts: | |
| save_pcs(xyzs, order_rgbs, save_path=save_path, add_coordinate_frame=add_coordinate_frame, side_view=side_view, add_table=add_table) | |
| if texts: | |
| buffer = save_pcs(xyzs, order_rgbs, add_coordinate_frame=add_coordinate_frame, | |
| side_view=side_view, add_table=add_table, return_buffer=True) | |
| img = np.uint8(np.asarray(buffer) * 255) | |
| img = Image.fromarray(img) | |
| draw = ImageDraw.Draw(img) | |
| font = ImageFont.truetype("FreeMono.ttf", 20) | |
| for it, text in enumerate(texts): | |
| draw.text((0, it*20), text, (120, 120, 120), font=font) | |
| img.save(save_path) | |
| def get_rgb_colors(): | |
| rgb_colors = [] | |
| # each color is a tuple of (name, (r,g,b)) | |
| for name, hex in matplotlib.colors.cnames.items(): | |
| rgb_colors.append((name, matplotlib.colors.to_rgb(hex))) | |
| rgb_colors = sorted(rgb_colors, key=lambda x: x[0]) | |
| priority_colors = [('red', (1.0, 0.0, 0.0)), ('green', (0.0, 1.0, 0.0)), ('blue', (0.0, 0.0, 1.0)), ('orange', (1.0, 0.6470588235294118, 0.0)), ('purple', (0.5019607843137255, 0.0, 0.5019607843137255)), ('magenta', (1.0, 0.0, 1.0)),] | |
| rgb_colors = priority_colors + rgb_colors | |
| return rgb_colors | |
| def open3d_set_side_view(vis): | |
| ctr = vis.get_view_control() | |
| # ctr.set_front([-0.61959040621518757, 0.46765094085676973, 0.63040489055992976]) | |
| # ctr.set_lookat([0.28810001969337462, 0.10746435821056366, 0.23499999999999999]) | |
| # ctr.set_up([0.64188154672853504, -0.16037991603449936, 0.74984422549096852]) | |
| # ctr.set_zoom(0.7) | |
| # ctr.rotate(10.0, 0.0) | |
| # ctr.set_front([ -0.51720189814974493, 0.55636089622063711, 0.65035740151617438 ]) | |
| # ctr.set_lookat([ 0.23103321183824999, 0.26154772406860449, 0.15131956132592411 ]) | |
| # ctr.set_up([ 0.47073865286968591, -0.44969907810742304, 0.75906248744340343 ]) | |
| # ctr.set_zoom(3) | |
| # ctr.set_front([-0.86019269757539152, 0.40355968763418076, 0.31178213796587784]) | |
| # ctr.set_lookat([0.28810001969337462, 0.10746435821056366, 0.23499999999999999]) | |
| # ctr.set_up([0.30587875107201218, -0.080905438599338214, 0.94862663869811026]) | |
| # ctr.set_zoom(0.69999999999999996) | |
| # ctr.set_front([0.40466417238365116, 0.019007526352692254, 0.91426780624224468]) | |
| # ctr.set_lookat([0.61287602731590907, 0.010181152776318789, -0.073166629933366326]) | |
| # ctr.set_up([-0.91444954965885639, 0.0025306059632757057, 0.40469200283941076]) | |
| # ctr.set_zoom(0.84000000000000008) | |
| ctr.set_front([-0.45528412367406523, 0.20211727782362851, 0.86710147776111224]) | |
| ctr.set_lookat([0.48308104105920047, 0.078726411326627957, -0.27298814087096795]) | |
| ctr.set_up([0.79763037008159798, -0.34013406176163907, 0.49809096835118638]) | |
| ctr.set_zoom(0.80000000000000004) | |
| init_param = ctr.convert_to_pinhole_camera_parameters() | |
| print("camera extrinsic", init_param.extrinsic.tolist()) | |
| def save_pcs(xyz, rgb, save_path=None, return_buffer=False, add_coordinate_frame=False, side_view=False, add_table=True): | |
| assert save_path or return_buffer, "provide path to save or set return_buffer to true" | |
| unordered_pc = np.concatenate(xyz, axis=0) | |
| unordered_rgb = np.concatenate(rgb, axis=0) | |
| pcd = open3d.geometry.PointCloud() | |
| pcd.points = open3d.utility.Vector3dVector(unordered_pc) | |
| pcd.colors = open3d.utility.Vector3dVector(unordered_rgb) | |
| vis = open3d.visualization.Visualizer() | |
| vis.create_window() | |
| vis.add_geometry(pcd) | |
| vis.update_geometry(pcd) | |
| if add_table: | |
| table_color = [0.7, 0.7, 0.7] | |
| origin = [0, -0.5, -0.03] | |
| table = open3d.geometry.TriangleMesh.create_box(width=1.0, height=1.0, depth=0.02) | |
| table.paint_uniform_color(table_color) | |
| table.translate(origin) | |
| vis.add_geometry(table) | |
| if add_coordinate_frame: | |
| mesh_frame = open3d.geometry.TriangleMesh.create_coordinate_frame(size=0.1, origin=[0, 0, 0]) | |
| vis.add_geometry(mesh_frame) | |
| vis.update_geometry(mesh_frame) | |
| if side_view: | |
| open3d_set_side_view(vis) | |
| vis.poll_events() | |
| vis.update_renderer() | |
| if save_path: | |
| vis.capture_screen_image(save_path) | |
| elif return_buffer: | |
| buffer = vis.capture_screen_float_buffer(False) | |
| vis.destroy_window() | |
| if return_buffer: | |
| return buffer | |
| else: | |
| return None | |
| def get_initial_scene_idxs(dataset): | |
| """ | |
| This function finds initial scenes from the dataset | |
| :param dataset: | |
| :return: | |
| """ | |
| initial_scene2idx_t = {} | |
| for idx in range(len(dataset)): | |
| filename, t = dataset.get_data_index(idx) | |
| if filename not in initial_scene2idx_t: | |
| initial_scene2idx_t[filename] = (idx, t) | |
| else: | |
| if t > initial_scene2idx_t[filename][1]: | |
| initial_scene2idx_t[filename] = (idx, t) | |
| initial_scene_idxs = [initial_scene2idx_t[f][0] for f in initial_scene2idx_t] | |
| return initial_scene_idxs | |
| def get_initial_scene_idxs_raw_data(data): | |
| """ | |
| This function finds initial scenes from the dataset | |
| :param dataset: | |
| :return: | |
| """ | |
| initial_scene2idx_t = {} | |
| for idx in range(len(data)): | |
| filename, t = data[idx] | |
| if filename not in initial_scene2idx_t: | |
| initial_scene2idx_t[filename] = (idx, t) | |
| else: | |
| if t > initial_scene2idx_t[filename][1]: | |
| initial_scene2idx_t[filename] = (idx, t) | |
| initial_scene_idxs = [initial_scene2idx_t[f][0] for f in initial_scene2idx_t] | |
| return initial_scene_idxs | |
| def evaluate_target_object_predictions(all_gts, all_predictions, all_sentences, initial_scene_idxs, tokenizer): | |
| """ | |
| This function evaluates target object predictions | |
| :param all_gts: a list of predictions for scenes. Each element is a list of booleans for objects in the scene | |
| :param all_predictions: | |
| :param all_sentences: a list of descriptions for scenes | |
| :param initial_scene_idxs: | |
| :param tokenizer: | |
| :return: | |
| """ | |
| # overall accuracy | |
| print("\noverall accuracy") | |
| report = classification_report(list(itertools.chain(*all_gts)), list(itertools.chain(*all_predictions)), | |
| output_dict=True) | |
| print(report) | |
| # scene average | |
| print("\naccuracy per scene") | |
| acc_per_scene = [] | |
| for gts, preds in zip(all_gts, all_predictions): | |
| acc_per_scene.append(sum(np.array(gts) == np.array(preds)) * 1.0 / len(gts)) | |
| print(np.mean(acc_per_scene)) | |
| plt.hist(acc_per_scene, 10, range=(0, 1), facecolor='g', alpha=0.75) | |
| plt.xlabel('Accuracy') | |
| plt.ylabel('# Scene') | |
| plt.title('Predicting objects to be rearranged') | |
| plt.xticks(np.linspace(0, 1, 11), np.linspace(0, 1, 11).round(1)) | |
| plt.grid(True) | |
| plt.show() | |
| # initial scene accuracy | |
| print("\noverall accuracy for initial scenes") | |
| tested_initial_scene_idxs = [i for i in initial_scene_idxs if i < len(all_gts)] | |
| initial_gts = [all_gts[i] for i in tested_initial_scene_idxs] | |
| initial_predictions = [all_predictions[i] for i in tested_initial_scene_idxs] | |
| report = classification_report(list(itertools.chain(*initial_gts)), list(itertools.chain(*initial_predictions)), | |
| output_dict=True) | |
| print(report) | |
| # break down by the number of objects | |
| print("\naccuracy for # objects in scene") | |
| num_objects_in_scenes = np.array([len(gts) for gts in all_gts]) | |
| unique_num_objects = np.unique(num_objects_in_scenes) | |
| acc_per_scene = np.array(acc_per_scene) | |
| assert len(acc_per_scene) == len(num_objects_in_scenes) | |
| for num_objects in unique_num_objects: | |
| this_scene_idxs = [i for i in range(len(all_gts)) if len(all_gts[i]) == num_objects] | |
| this_num_obj_gts = [all_gts[i] for i in this_scene_idxs] | |
| this_num_obj_predictions = [all_predictions[i] for i in this_scene_idxs] | |
| report = classification_report(list(itertools.chain(*this_num_obj_gts)), list(itertools.chain(*this_num_obj_predictions)), | |
| output_dict=True) | |
| print("{} objects".format(num_objects)) | |
| print(report) | |
| # reference | |
| print("\noverall accuracy break down") | |
| direct_gts_by_type = defaultdict(list) | |
| direct_preds_by_type = defaultdict(list) | |
| d_anchor_gts_by_type = defaultdict(list) | |
| d_anchor_preds_by_type = defaultdict(list) | |
| c_anchor_gts_by_type = defaultdict(list) | |
| c_anchor_preds_by_type = defaultdict(list) | |
| for i, s in enumerate(all_sentences): | |
| v, t = s[0] | |
| if t[-2:] == "_c" or t[-2:] == "_d": | |
| t = t[:-2] | |
| if v != "MASK" and t in tokenizer.discrete_types: | |
| # direct reference | |
| direct_gts_by_type[t].extend(all_gts[i]) | |
| direct_preds_by_type[t].extend(all_predictions[i]) | |
| else: | |
| if v == "MASK": | |
| # discrete anchor | |
| d_anchor_gts_by_type[t].extend(all_gts[i]) | |
| d_anchor_preds_by_type[t].extend(all_predictions[i]) | |
| else: | |
| c_anchor_gts_by_type[t].extend(all_gts[i]) | |
| c_anchor_preds_by_type[t].extend(all_predictions[i]) | |
| print("direct") | |
| for t in direct_gts_by_type: | |
| report = classification_report(direct_gts_by_type[t], direct_preds_by_type[t], output_dict=True) | |
| print(t, report) | |
| print("discrete anchor") | |
| for t in d_anchor_gts_by_type: | |
| report = classification_report(d_anchor_gts_by_type[t], d_anchor_preds_by_type[t], output_dict=True) | |
| print(t, report) | |
| print("continuous anchor") | |
| for t in c_anchor_gts_by_type: | |
| report = classification_report(c_anchor_gts_by_type[t], c_anchor_preds_by_type[t], output_dict=True) | |
| print(t, report) | |
| # break down by object class | |
| def combine_and_sample_xyzs(xyzs, rgbs, center=None, radius=0.5, num_pts=1024): | |
| xyz = torch.cat(xyzs, dim=0) | |
| rgb = torch.cat(rgbs, dim=0) | |
| if center is not None: | |
| center = center.repeat(xyz.shape[0], 1) | |
| dists = torch.linalg.norm(xyz - center, dim=-1) | |
| idx = dists < radius | |
| xyz = xyz[idx] | |
| rgb = rgb[idx] | |
| idx = np.random.randint(0, xyz.shape[0], num_pts) | |
| xyz = xyz[idx] | |
| rgb = rgb[idx] | |
| return xyz, rgb | |
| def evaluate_prior_prediction(gts, predictions, keys, debug=False): | |
| """ | |
| :param gts: expect a list of tensors | |
| :param predictions: expect a list of tensor | |
| :return: | |
| """ | |
| total_mses = 0 | |
| obj_dists = [] | |
| struct_dists = [] | |
| for key in keys: | |
| # predictions[key][0]: [batch_size * number_of_objects, dim] | |
| predictions_for_key = torch.cat(predictions[key], dim=0) | |
| # gts[key][0]: [batch_size * number_of_objects, dim] | |
| gts_for_key = torch.cat(gts[key], dim=0) | |
| assert gts_for_key.shape == predictions_for_key.shape | |
| target_indices = gts_for_key != -100 | |
| gts_for_key = gts_for_key[target_indices] | |
| predictions_for_key = predictions_for_key[target_indices] | |
| num_objects = len(predictions_for_key) | |
| distances = predictions_for_key - gts_for_key | |
| me = torch.mean(torch.abs(distances)) | |
| mse = torch.mean(distances ** 2) | |
| med = torch.median(torch.abs(distances)) | |
| if "obj_x" in key or "obj_y" in key or "obj_z" in key: | |
| obj_dists.append(distances) | |
| if "struct_x" in key or "struct_y" in key or "struct_z" in key: | |
| struct_dists.append(distances) | |
| if debug: | |
| print("Groundtruths:") | |
| print(gts_for_key[:100]) | |
| print("Predictions") | |
| print(predictions_for_key[:100]) | |
| print("{} ME for {} objects: {}".format(key, num_objects, me)) | |
| print("{} MSE for {} objects: {}".format(key, num_objects, mse)) | |
| print("{} MEDIAN for {} objects: {}".format(key, num_objects, med)) | |
| total_mses += mse | |
| if "theta" in key: | |
| predictions_for_key = predictions_for_key.reshape(-1, 3, 3) | |
| gts_for_key = gts_for_key.reshape(-1, 3, 3) | |
| geodesic_distance = compute_geodesic_distance_from_two_matrices(predictions_for_key, gts_for_key) | |
| geodesic_distance = torch.rad2deg(geodesic_distance) | |
| mgd = torch.mean(geodesic_distance) | |
| stdgd = torch.std(geodesic_distance) | |
| megd = torch.median(geodesic_distance) | |
| print("{} Mean and std Geodesic Distance for {} objects: {} +- {}".format(key, num_objects, mgd, stdgd)) | |
| print("{} Median Geodesic Distance for {} objects: {}".format(key, num_objects, megd)) | |
| if obj_dists: | |
| euclidean_dists = torch.sqrt(obj_dists[0]**2 + obj_dists[1]**2 + obj_dists[2]**2) | |
| me = torch.mean(euclidean_dists) | |
| stde = torch.std(euclidean_dists) | |
| med = torch.median(euclidean_dists) | |
| print("Mean and std euclidean dist for {} objects: {} +- {}".format(len(euclidean_dists), me, stde)) | |
| print("Median euclidean dist for {} objects: {}".format(len(euclidean_dists), med)) | |
| if struct_dists: | |
| euclidean_dists = torch.sqrt(struct_dists[0] ** 2 + struct_dists[1] ** 2 + struct_dists[2] ** 2) | |
| me = torch.mean(euclidean_dists) | |
| stde = torch.std(euclidean_dists) | |
| med = torch.median(euclidean_dists) | |
| print("Mean euclidean dist for {} structures: {} +- {}".format(len(euclidean_dists), me, stde)) | |
| print("Median euclidean dist for {} structures: {}".format(len(euclidean_dists), med)) | |
| return -total_mses | |
| def generate_square_subsequent_mask(sz): | |
| mask = (torch.triu(torch.ones((sz, sz))) == 1).transpose(0, 1) | |
| mask = mask.float().masked_fill(mask == 0, float('-inf')).masked_fill(mask == 1, float(0.0)) | |
| return mask | |
| def visualize_occ(points, occupancies, in_num_pts=1000, out_num_pts=1000, visualize=False, threshold=0.5): | |
| rix = np.random.permutation(points.shape[0]) | |
| vis_points = points[rix] | |
| vis_occupancies = occupancies[rix] | |
| in_pc = vis_points[vis_occupancies.squeeze() > threshold, :][:in_num_pts] | |
| out_pc = vis_points[vis_occupancies.squeeze() < threshold, :][:out_num_pts] | |
| if len(in_pc) == 0: | |
| print("no in points") | |
| if len(out_pc) == 0: | |
| print("no out points") | |
| in_pc = trimesh.PointCloud(in_pc) | |
| out_pc = trimesh.PointCloud(out_pc) | |
| in_pc.colors = np.tile((255, 0, 0, 255), (in_pc.vertices.shape[0], 1)) | |
| out_pc.colors = np.tile((255, 255, 0, 120), (out_pc.vertices.shape[0], 1)) | |
| if visualize: | |
| scene = trimesh.Scene([in_pc, out_pc]) | |
| scene.show() | |
| return in_pc, out_pc | |
| def save_dict_to_h5(dict_data, filename): | |
| fh = h5py.File(filename, 'w') | |
| for k in dict_data: | |
| key_data = dict_data[k] | |
| if key_data is None: | |
| raise RuntimeError('data was not properly populated') | |
| # if type(key_data) is dict: | |
| # key_data = json.dumps(key_data, sort_keys=True) | |
| try: | |
| fh.create_dataset(k, data=key_data) | |
| except TypeError as e: | |
| print("Failure on key", k) | |
| print(key_data) | |
| print(e) | |
| raise e | |
| fh.close() | |
| def load_h5_key(h5, key): | |
| if key in h5: | |
| return h5[key][()] | |
| elif "json_" + key in h5: | |
| return json.loads(h5["json_" + key][()]) | |
| else: | |
| return None | |
| def load_dict_from_h5(filename): | |
| h5 = h5py.File(filename, "r") | |
| data_dict = {} | |
| for k in h5: | |
| data_dict[k] = h5[k][()] | |
| return data_dict | |