-
Notifications
You must be signed in to change notification settings - Fork 0
/
jaccard_similarity.py
94 lines (67 loc) · 3.29 KB
/
jaccard_similarity.py
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
import numpy as np
import subprocess
import argparse
import binvox_rw
import os
import shutil
import plyfile
import tempfile
def jaccard_similarity(mesh_filepath0, mesh_filepath1, grid_size=40, exact=True):
t0_handle, temp_mesh0_filepath = tempfile.mkstemp(suffix=".ply")
t1_handle, temp_mesh1_filepath = tempfile.mkstemp(suffix=".ply")
os.close(t0_handle)
os.close(t1_handle)
binvox0_filepath = temp_mesh0_filepath.replace(".ply", ".binvox")
binvox1_filepath = temp_mesh1_filepath.replace(".ply", ".binvox")
shutil.copyfile(mesh_filepath0, temp_mesh0_filepath)
shutil.copyfile(mesh_filepath1, temp_mesh1_filepath)
mesh0 = plyfile.PlyData.read(temp_mesh0_filepath)
mesh1 = plyfile.PlyData.read(temp_mesh1_filepath)
minx = mesh0['vertex']['x'].min()
miny = mesh0['vertex']['y'].min()
minz = mesh0['vertex']['z'].min()
maxx = mesh0['vertex']['x'].max()
maxy = mesh0['vertex']['y'].max()
maxz = mesh0['vertex']['z'].max()
#-d: specify voxel grid size (default 256, max 1024)(no max when using -e)
#-e: exact voxelization (any voxel with part of a triangle gets set)(does not use graphics card)
#-bb <minx> <miny> <minz> <maxx> <maxy> <maxz>: force a different input model bounding box
cmd_base = "binvox -pb "
if exact:
cmd_base += "-e "
cmd_base += "-d " + str(grid_size) + " -bb " + str(minx) + " " + str(miny) + " " + str(minz) + " " + str(maxx) + " " + str(maxy) + " " + str(maxz)
mesh0_cmd = cmd_base + " " + temp_mesh0_filepath
mesh1_cmd = cmd_base + " " + temp_mesh1_filepath
subprocess.call(mesh0_cmd.split(" "))
subprocess.call(mesh1_cmd.split(" "))
mesh0_binvox = binvox_rw.read_as_3d_array(open(binvox0_filepath,'r'))
mesh1_binvox = binvox_rw.read_as_3d_array(open(binvox1_filepath, 'r'))
intersection = np.logical_and(mesh0_binvox.data, mesh1_binvox.data)
intersection_count = np.count_nonzero(intersection)
union = np.logical_or(mesh0_binvox.data, mesh1_binvox.data)
union_count = np.count_nonzero(union)
jaccard = float(intersection_count) / float(union_count)
if os.path.exists(temp_mesh0_filepath):
os.remove(temp_mesh0_filepath)
if os.path.exists(temp_mesh1_filepath):
os.remove(temp_mesh1_filepath)
if os.path.exists(binvox0_filepath):
os.remove(binvox0_filepath)
if os.path.exists(binvox1_filepath):
os.remove(binvox1_filepath)
return jaccard
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Compute Jaccard between two meshes')
parser.add_argument('mesh_filepaths', metavar='N', type=str, nargs='+',
help='meshes to compare')
parser.add_argument('--grid_size', metavar='d', type=int, default=40,
help='grid size along single dimention')
parser.add_argument('--exact', metavar='e', type=bool, default=True,
help='exact voxelization is only voxels that intersect surface')
args = parser.parse_args()
mesh_files = args.mesh_filepaths
grid_size = args.grid_size
exact = args.exact
if len(mesh_files) != 2:
print "wrong number of mesh files: wanted 2, got: " + str(len(mesh_files))
print jaccard_similarity(mesh_files[0], mesh_files[1], grid_size, exact)