-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathface-stats.py
218 lines (166 loc) · 8.49 KB
/
face-stats.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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
import os
import argparse
import subprocess
import glob
import re
import pymeshlab
from decimal import Decimal, ROUND_HALF_UP
def generate_cv(displaced_samples_path):
exe_path = os.path.join(os.getcwd(), "Debug", "anisotropic_micromesh.exe")
file_list = glob.glob(os.path.join(displaced_samples_path, "*"))
displaced_meshes = [file for file in file_list if os.path.splitext(file)[1] in ['.obj', '.off']]
displaced_meshes.sort(key=os.path.getsize)
params.pop()
params.pop()
for displaced_mesh_path in displaced_meshes:
params.append(f'--base-mesh={displaced_mesh_path}')
try:
subprocess.check_call([exe_path, "compute-cv"] + params)
except subprocess.CalledProcessError as e:
print(f"Error while executing the command: {e}")
except FileNotFoundError as e:
print(f"File not found: {e}")
params.pop()
def export_scalar_inradius_circumradius_per_face(base_mesh_name, displaced_samples_path):
# Get the list of files
file_list = glob.glob(os.path.join(displaced_samples_path, "*"))
# Consider only OBJ and OFF
displaced_meshes = [file for file in file_list if os.path.splitext(file)[1] in ['.obj', '.off']]
# Sort the meshes by dimension (amount of micro-faces)
displaced_meshes.sort(key=os.path.getsize)
factor = Decimal('1.0')
with open(f"{displaced_samples_path}/scalar_per_face_circumradius_inradius.txt", "w") as distances_file:
distances_file.write("factor avg stddev variance\n")
for displaced_mesh_path in displaced_meshes:
ms = pymeshlab.MeshSet()
ms.load_new_mesh(displaced_mesh_path)
ms.compute_scalar_by_aspect_ratio_per_face()
stats = ms.get_scalar_statistics_per_face()
stats = {key: round(value, 2) for key, value in stats.items()}
distances_file.write(
f"{factor} & {stats['avg']} & {stats['stddev']} & {stats['variance']} \\\\ \n")
factor = factor + Decimal('0.1')
print(
f"Hausdorff's distances saved > {displaced_samples_path}/scalar_per_face_circumradius_inradius.txt")
distances_file.close()
def export_hausdorff(base_mesh_name, target_mesh_path, displaced_samples_path):
# Get the list of files
file_list = glob.glob(os.path.join(displaced_samples_path, "*"))
# Consider only OBJ and OFF
displaced_meshes = [file for file in file_list if os.path.splitext(file)[1] in ['.obj', '.off']]
# Sort the meshes by dimension (amount of micro-faces)
displaced_meshes.sort(key=os.path.getsize)
# Initialise the factor (will be written in the .txt)
factor = Decimal('1.0')
scheme = displaced_samples_path.split("/")[2]
with open(f"{displaced_samples_path}/hausdorff_{base_mesh_name}_{scheme}.txt", "w") as distances_file:
# Write the header
distances_file.write("microFaces factor RMS max mean RMS_scaled max_scaled mean_scaled\n")
for displaced_mesh_path in displaced_meshes:
# Load the displaced and target mesh in a MeshSet
ms = pymeshlab.MeshSet()
ms.load_new_mesh(displaced_mesh_path)
ms.load_new_mesh(target_mesh_path)
# Extract the number of micro-faces (expressed in millions, e.g. 1.3mln)
target_mesh_name = os.path.basename(displaced_mesh_path)
mfs = int(target_mesh_name.split("_")[3])
mln_mfs = Decimal(mfs) / Decimal(1000000)
mln_mfs = mln_mfs.quantize(Decimal('0.00'), rounding=ROUND_HALF_UP)
# Compute Hausdorff's distances
res = ms.get_hausdorff_distance(sampledmesh=1, targetmesh=0)
# Compute the diagonal of the BBOX for scale the absolute distances
diagonal = ms.current_mesh().bounding_box().diagonal()
# Scale the distances
scaled_RMS = (res['RMS'] * 100) / diagonal
scaled_max = (res['max'] * 100) / diagonal
scaled_mean = (res['mean'] * 100) / diagonal
# Write micro-faces, factor and distances in a row
distances_file.write(str(mln_mfs) + " ")
distances_file.write(f'{factor:.2f} ')
distances_file.write(str(res['RMS']) + " ")
distances_file.write(str(res['max']) + " ")
distances_file.write(str(res['mean']) + " ")
distances_file.write(str(scaled_RMS) + " ")
distances_file.write(str(scaled_max) + " ")
distances_file.write(str(scaled_mean) + " ")
distances_file.write("\\\\ \n")
# Increase the factor by 0.1
factor = factor + Decimal('0.1')
print(
f"Hausdorff's distances saved > {displaced_samples_path}/hausdorff_{base_mesh_name}_{scheme}.txt")
distances_file.close()
factor = Decimal('1.0')
with open(f"{displaced_samples_path}/table_data.txt", "w") as table_file:
for displaced_mesh_path in displaced_meshes:
# Load the displaced and target mesh in a MeshSet
ms = pymeshlab.MeshSet()
ms.load_new_mesh(displaced_mesh_path)
ms.load_new_mesh(target_mesh_path)
# Extract the number of micro-faces (expressed in millions, e.g. 1.3mln)
target_mesh_name = os.path.basename(displaced_mesh_path)
mfs = int(target_mesh_name.split("_")[3])
mln_mfs = Decimal(mfs) / Decimal(1000000)
mln_mfs = mln_mfs.quantize(Decimal('0.00'), rounding=ROUND_HALF_UP)
# Compute Hausdorff's distances
res = ms.get_hausdorff_distance(sampledmesh=0, targetmesh=1)
# Compute the diagonal of the BBOX for scale the absolute distances
diagonal = ms.current_mesh().bounding_box().diagonal()
# Scale the distances
scaled_RMS = (res['RMS'] * 100) / diagonal
scaled_max = (res['max'] * 100) / diagonal
scaled_mean = (res['mean'] * 100) / diagonal
# Write micro-faces, factor and distances in a row
table_file.write(str(mln_mfs) + " & ")
table_file.write(f'{factor:.2f} & ')
table_file.write("{:.2e} & ".format(res['RMS']))
table_file.write("{:.2e} & ".format(res['max']))
table_file.write("{:.2e} & ".format(res['mean']))
table_file.write("{:.2e} \\".format(scaled_mean))
table_file.write("\n")
# Increase the factor by 0.1
factor = factor + Decimal('0.1')
print(f"Table data saved > {displaced_samples_path}/table_data.txt")
table_file.close()
def generate_samples(params):
exe_path = os.path.join(os.getcwd(), "Release", "anisotropic_micromesh.exe")
MIN_MFS_FACTOR = 1.0
MAX_MFS_FACTOR = 4.1
STEP_SIZE = 0.1
for num in range(int(MIN_MFS_FACTOR * 10), int(MAX_MFS_FACTOR * 10), int(STEP_SIZE * 10)):
factor = num / 10.0
params.append(f"--factor={factor}")
try:
subprocess.check_call([exe_path, "gen-sample"] + params)
except subprocess.CalledProcessError as e:
print(f"Error while executing the command: {e}")
except FileNotFoundError as e:
print(f"File not found: {e}")
params.pop()
if __name__ == "__main__":
# Parsing command-line arguments
parser = argparse.ArgumentParser()
parser.add_argument("--base-mesh", default="pallas_1000.obj")
parser.add_argument("--target-mesh", default="original_pallas_triquad.obj")
args = parser.parse_args()
# Building command-line arguments for generating the samples
params = []
if args.base_mesh is not None:
params.append(f"--base-mesh={args.base_mesh}")
if args.target_mesh is not None:
params.append(f"--target-mesh={args.target_mesh}")
# Generating samples for both schemes (TODO: clean the directory before generating new samples again)
params.append("--scheme=micro")
generate_samples(params)
params.pop()
params.append("--scheme=aniso")
generate_samples(params)
# Exporting Hausdorff distances
base_mesh_name = args.base_mesh[:-4]
iso_samples_path = "./Evaluation/micro/" + base_mesh_name
aniso_samples_path = "./Evaluation/aniso/" + base_mesh_name
target_mesh_path = "./Models/" + args.target_mesh
# export_hausdorff(base_mesh_name, target_mesh_path, iso_samples_path)
# export_hausdorff(base_mesh_name, target_mesh_path, aniso_samples_path)
export_scalar_inradius_circumradius_per_face(base_mesh_name, iso_samples_path)
export_scalar_inradius_circumradius_per_face(base_mesh_name, aniso_samples_path)
# generate_cv(iso_samples_path)