# Copyright (c) Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. import copy import torch import numpy as np import math import glob, os import argparse import open3d as o3d def make_open3d_point_cloud(xyz, color=None, voxel_size=None): if np.isnan(xyz).any(): return None xyz = xyz[:,:3] pcd = o3d.geometry.PointCloud() pcd.points = o3d.utility.Vector3dVector(xyz) if color is not None: pcd.colors = o3d.utility.Vector3dVector(color) if voxel_size is not None: pcd = pcd.voxel_down_sample(voxel_size) return pcd def compute_overlap_ratio(pcd0, pcd1, voxel_size): pcd0_down = pcd0.voxel_down_sample(voxel_size) pcd1_down = pcd1.voxel_down_sample(voxel_size) matching01 = get_matching_indices(pcd0_down, pcd1_down, voxel_size * 1.5, 1) matching10 = get_matching_indices(pcd1_down, pcd0_down, voxel_size * 1.5, 1) overlap0 = float(len(matching01)) / float(len(pcd0_down.points)) overlap1 = float(len(matching10)) / float(len(pcd1_down.points)) return max(overlap0, overlap1) def get_matching_indices(source, pcd_tree, search_voxel_size, K=None): match_inds = [] for i, point in enumerate(source.points): [_, idx, _] = pcd_tree.search_radius_vector_3d(point, search_voxel_size) if K is not None: idx = idx[:K] for j in idx: match_inds.append((i, j)) return match_inds def compute_full_overlapping(data_root, scene_id, voxel_size=0.05): _points = [ (pcd_name, make_open3d_point_cloud(torch.load(pcd_name)['coord'], voxel_size=voxel_size)) for pcd_name in glob.glob(os.path.join(data_root, scene_id, "pcd", "*.pth")) ] points = [(pcd_name, pcd) for (pcd_name, pcd) in _points if pcd is not None] print('load {} point clouds ({} invalid has been filtered), computing matching/overlapping'.format( len(points), len(_points) - len(points))) matching_matrix = np.zeros((len(points), len(points))) for i, (pcd0_name, pcd0) in enumerate(points): print('matching to...{}'.format(pcd0_name)) pcd0_tree = o3d.geometry.KDTreeFlann(copy.deepcopy(pcd0)) for j, (pcd1_name, pcd1) in enumerate(points): if i == j: continue matching_matrix[i, j] = float(len(get_matching_indices(pcd1, pcd0_tree, 1.5 * voxel_size, 1))) / float( len(pcd1.points)) # write to file with open(os.path.join(data_root, scene_id, "pcd", "overlap.txt"), 'w') as f: for i, (pcd0_name, pcd0) in enumerate(points): for j, (pcd1_name, pcd1) in enumerate(points): if i < j: overlap = max(matching_matrix[i, j], matching_matrix[j, i]) f.write("{} {} {}\n".format( pcd0_name.replace(data_root, ""), pcd1_name.replace(data_root, ""), overlap ))