File size: 3,020 Bytes
bd27f44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# 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
                    ))