forked from PrimitiveAnything/PrimitiveAnything
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy patheval.py
More file actions
113 lines (91 loc) · 4.17 KB
/
Copy patheval.py
File metadata and controls
113 lines (91 loc) · 4.17 KB
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import argparse
from collections import defaultdict
import glob
import json
import os
import numpy as np
import trimesh
import point_cloud_utils as pcu
from tqdm import tqdm
import numpy as np
def voxelize(points, voxel_size=0.1):
"""
Converts a set of 3D points to a voxel grid representation.
Points are quantized to the nearest voxel center.
Parameters:
- points: (N, 3) numpy array of 3D points
- voxel_size: the size of each voxel (adjust this depending on your data)
Returns:
- voxels: Set of unique voxel coordinates
"""
# Quantize the points to the nearest voxel
quantized_points = np.floor(points / voxel_size).astype(int)
# Use a set to get unique voxel coordinates
voxels = set(map(tuple, quantized_points))
return voxels
def calculate_iou(model_vox, target_vox, voxel_size=0.1):
"""
Calculate the IoU (Intersection over Union) between two point clouds.
Parameters:
- model_vox: (N, 3) numpy array of the first point cloud
- target_vox: (M, 3) numpy array of the second point cloud
- voxel_size: Size of the voxels (default is 0.1)
Returns:
- iou: Intersection over Union (IoU) score
"""
# Voxelize both point clouds
model_voxels = voxelize(model_vox, voxel_size)
target_voxels = voxelize(target_vox, voxel_size)
# Calculate intersection and union
intersection = len(model_voxels.intersection(target_voxels))
union = len(model_voxels.union(target_voxels))
# Compute IoU
iou = intersection / union if union > 0 else 0.0
return iou
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--input_dir", type=str, default="./results/infer/PointClouds")
parser.add_argument("--target_dir", type=str, default="./data/test_pc")
parser.add_argument("--detail", action="store_true")
args = parser.parse_args()
if not os.path.exists(args.input_dir) or not os.path.exists(args.target_dir):
print("Invalid input!")
exit(1)
model_prefix = os.path.join(args.input_dir, "*.ply")
model_path_list = sorted(list(glob.glob(model_prefix)))
distance_json = {}
distance_list = []
emu_distance_list = []
hausdorff_distance_list = []
voxel_iou_list = []
for model_path in tqdm(model_path_list):
model_name = os.path.basename(model_path)
target_path = os.path.join(args.target_dir, model_name)
if not os.path.exists(target_path):
print(f"{target_path}: not found!")
exit(1)
model_pc = np.array(trimesh.load(model_path).vertices)
target_pc = np.array(trimesh.load(target_path).vertices)
distance = pcu.chamfer_distance(model_pc, target_pc)
model_pc_downsampled = model_pc[np.random.choice(model_pc.shape[0], 1000, replace=False)]
target_pc_downsampled = target_pc[np.random.choice(target_pc.shape[0], 1000, replace=False)]
emu_distance, _ = pcu.earth_movers_distance(model_pc_downsampled, target_pc_downsampled)
hausdorff_distance = pcu.hausdorff_distance(model_pc, target_pc)
iou = calculate_iou(model_pc, target_pc, voxel_size=1/32.)
distance_list.append(distance)
emu_distance_list.append(emu_distance)
hausdorff_distance_list.append(hausdorff_distance)
voxel_iou_list.append(iou)
model_id = os.path.splitext(model_name)[0]
distance_json[model_id] = distance
print(f"{model_id}: chamfer distance: {distance:.3f}, earth movers distance: {emu_distance:.3f}, hausdorff distance: {hausdorff_distance:.3f}, voxel IoU: {iou:.3f}")
distance_json["mean"] = np.mean(distance_list)
distance_json["mean_emu"] = np.mean(emu_distance_list)
distance_json["mean_hausdorff"] = np.mean(hausdorff_distance_list)
distance_json["mean_voxel_iou"] = np.mean(voxel_iou_list)
print(f"mean chamfer distance: {np.mean(distance_list)}")
print(f"mean earth movers distance: {np.mean(emu_distance_list)}")
print(f"mean hausdorff distance: {np.mean(hausdorff_distance_list)}")
print(f"mean voxel IoU: {np.mean(voxel_iou_list)}")
with open(os.path.join(args.input_dir, "distance.json"), "w") as json_file:
json.dump(distance_json, json_file, indent=4)