Skip to content

Commit 7875a10

Browse files
author
Dannydigr
committed
More clean up and added a requirement.txt file
1 parent 2e9b1b8 commit 7875a10

13 files changed

+136
-245
lines changed

.gitattributes

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.zip filter=lfs diff=lfs merge=lfs -text

ANN.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ def ann(query_mesh, feature_list, num_of_trees=1000, top_k=25, search_k=-1, quer
3131
is known by the parameter query: if True, the shape is new, if False, the shape is present in feature_list.
3232
"""
3333

34-
3534
all_feat = pd.read_csv(feature_list, header=0)
3635

3736
non_features = ['file_name', 'shape_number', 'Class']
@@ -137,6 +136,9 @@ def ann(query_mesh, feature_list, num_of_trees=1000, top_k=25, search_k=-1, quer
137136

138137

139138
def ann_fast(query_mesh, features, map, num_of_trees=1000, top_k=10, search_k=-1, metric='euclidean'):
139+
"""
140+
Fast because each time is called, it should not read all the features from scratch, but they are passed as input.
141+
"""
140142

141143
all_feat = features
142144
non_features = ['file_name', 'shape_number', 'Class']

Evaluation.py

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def evaluate_db(mesh_db_path="./all_features.csv", query_num=25):
2525
db_size = len(mesh_db['file_name'])
2626
class_count_dict, class_metrics = class_count(mesh_db['Class'].tolist())
2727

28-
avg_metrics = {'avg_accuracy': 0, 'avg_sensitivity': 0, 'avg_specificity': 0, 'avg_precision':0, 'avg_f1':0}
28+
avg_metrics = {'avg_accuracy': 0, 'avg_sensitivity': 0, 'avg_specificity': 0, 'avg_precision': 0, 'avg_f1': 0}
2929
class_acc = class_metrics.copy()
3030
class_sens = class_metrics.copy()
3131
class_spec = class_metrics.copy()
@@ -79,15 +79,13 @@ def evaluate_db(mesh_db_path="./all_features.csv", query_num=25):
7979
avg_metrics['avg_precision'] += precision
8080
class_prec[mesh_class] += precision
8181

82-
8382
if precision + sensitivity == 0:
8483
f1_score = 0
8584
else:
8685
f1_score = 2 * ((precision * sensitivity) / (precision + sensitivity))
8786
avg_metrics['avg_f1'] += f1_score
8887
class_f1sc[mesh_class] += f1_score
8988

90-
9189
for item in list(class_count_dict):
9290
class_acc[item] /= class_count_dict[item]
9391
class_sens[item] /= class_count_dict[item]
@@ -101,11 +99,10 @@ def evaluate_db(mesh_db_path="./all_features.csv", query_num=25):
10199
time2 = time.time()
102100
print(f"Time to evaluate: {time2-time1}")
103101

104-
105102
print("\nAverage metrics")
106103
print(avg_metrics)
107104

108-
"""print("\nClass accuracy:")
105+
print("\nClass accuracy:")
109106
print(class_acc)
110107
print("\nClass sensitivity:")
111108
print(class_sens)
@@ -114,19 +111,21 @@ def evaluate_db(mesh_db_path="./all_features.csv", query_num=25):
114111
print("\nClass precision")
115112
print(class_prec)
116113
print("\nClass F1-score")
117-
print(class_f1sc)"""
114+
print(class_f1sc)
118115

119116
results = [avg_metrics, class_acc, class_sens, class_spec, class_prec, class_f1sc, "DIST_RESULTS"]
120117

121118
return results
122119

120+
123121
def evaluate_ann(mesh_db_path="./all_features.csv", query_num=25):
122+
124123
time1 = time.time()
125124
mesh_db = pd.read_csv(mesh_db_path, header=0)
126125
db_size = len(mesh_db['file_name'])
127126
class_count_dict, class_metrics = class_count(mesh_db['Class'].tolist())
128127

129-
avg_metrics = {'avg_accuracy': 0, 'avg_sensitivity': 0, 'avg_specificity': 0, 'avg_precision': 0, 'avg_f1':0}
128+
avg_metrics = {'avg_accuracy': 0, 'avg_sensitivity': 0, 'avg_specificity': 0, 'avg_precision': 0, 'avg_f1': 0}
130129
class_acc = class_metrics.copy()
131130
class_sens = class_metrics.copy()
132131
class_spec = class_metrics.copy()
@@ -206,7 +205,7 @@ def evaluate_ann(mesh_db_path="./all_features.csv", query_num=25):
206205
print("\nAverage metrics")
207206
print(avg_metrics)
208207

209-
"""print("\nClass accuracy:")
208+
print("\nClass accuracy:")
210209
print(class_acc)
211210
print("\nClass sensitivity:")
212211
print(class_sens)
@@ -215,14 +214,15 @@ def evaluate_ann(mesh_db_path="./all_features.csv", query_num=25):
215214
print("\nClass precision")
216215
print(class_prec)
217216
print("\nClass F1-score")
218-
print(class_f1sc)"""
217+
print(class_f1sc)
219218

220219
results = [avg_metrics, class_acc, class_sens, class_spec, class_prec, class_f1sc, "ANN_RESULTS"]
221220

222221
return results
223222

224223

225224
def compute_roc_curve():
225+
226226
query_nums = [5, 10, 25, 50, 75, 100, 150, 200, 300, 400, 500, 600, 700, 800, 900, 1000]
227227

228228
tpr_dist = [0]
@@ -231,13 +231,13 @@ def compute_roc_curve():
231231
fpr_ann = [0]
232232
all_dist_results = []
233233
all_ann_results = []
234+
234235
for num in query_nums:
235236
result_dist = evaluate_db(query_num=num)
236237
all_dist_results.append((len(all_dist_results), result_dist))
237238
tpr_dist.append(result_dist[0]['avg_sensitivity'])
238239
fpr_dist.append(1-result_dist[0]['avg_specificity'])
239240

240-
241241
result_ann = evaluate_ann(query_num=num)
242242
all_ann_results.append((len(all_ann_results), result_ann))
243243
tpr_ann.append(result_ann[0]['avg_sensitivity'])
@@ -248,7 +248,6 @@ def compute_roc_curve():
248248
tpr_ann.append(1)
249249
fpr_ann.append(1)
250250

251-
252251
auc_dist = auc(fpr_dist, tpr_dist)
253252
auc_ann = auc(fpr_ann, tpr_ann)
254253

@@ -261,18 +260,7 @@ def compute_roc_curve():
261260

262261

263262

264-
265-
266-
267-
268-
269-
270-
271-
272-
273-
274-
275-
compute_roc_curve()
263+
#compute_roc_curve()
276264
#evaluate_db()
277265
#evaluate_ann()
278266
#[(closest_meshes[i][0], mesh_db['Class'].loc[mesh_db['file_name'] == closest_meshes[i][0]].item()) for i in range(len(closest_meshes))]

Mesh_Reading.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,6 @@ def view_mesh(mesh, draw_coordinates=False, show_wireframe=True, aabbox=False):
8989
"""
9090

9191
# compute the light of the mesh
92-
#mesh.vertex_normals = o3d.utility.Vector3dVector([])
93-
#mesh.triangle_normals = o3d.utility.Vector3dVector([])
9492
mesh.compute_vertex_normals()
9593
mesh.compute_triangle_normals()
9694

Mesh_refining.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ def refine_single_mesh(mesh, target_faces_number=5000):
2424

2525
actual_faces_number = len(mesh.triangles)
2626
splitpoint = int(target_faces_number * 0.4) # eg: 5000 - x = 4x - 5000
27-
# splitpoint identifies the value for which is the same refine or not refine the mesh, given the target.
28-
# In fact, not all meshes with < 5000 faces should be refined, since for every value above 2000,
29-
# if the refining will be done even only once, the number of faces obtained would be
30-
# far from 5000 compared to the case that we haven't refined the original mesh.
31-
# 2000 is the split point: 5000 - 2000 = 3000 and 2000 * 4 - 5000 = 3000.
32-
# The distance from 5000 of the refined vs not refined is the same.
27+
28+
"""splitpoint identifies the value for which is the same refine or not refine the mesh, given the target.
29+
In fact, not all meshes with < 5000 faces should be refined, since for every value above 2000,
30+
if the refining will be done even only once, the number of faces obtained would be
31+
far from 5000 compared to the case that we haven't refined the original mesh.
32+
2000 is the split point: 5000 - 2000 = 3000 and 2000 * 4 - 5000 = 3000.
33+
The distance from 5000 of the refined vs not refined is the same."""
3334

3435
if actual_faces_number < splitpoint:
3536

@@ -39,11 +40,9 @@ def refine_single_mesh(mesh, target_faces_number=5000):
3940
# for the submeshing, the algorithm would take care about the target number
4041
# of faces and we don't have to calculate a splitpoint.
4142
elif actual_faces_number > target_faces_number:
42-
4343
new_mesh = mesh.simplify_quadric_decimation(target_number_of_triangles=target_faces_number)
4444

4545
else:
46-
4746
new_mesh = mesh
4847

4948
new_mesh.remove_duplicated_triangles()

Normalization.py

Lines changed: 29 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
import open3d as o3d
44
import numpy as np
55
import os
6-
import trimesh as tm
7-
import copy
86

97

108
def get_barycenter(mesh):
@@ -221,50 +219,26 @@ def align_eigenvectors(mesh):
221219

222220
return mesh
223221

224-
"""
225222

226-
def flip_test(mesh):
227-
228-
print("Flipping the mesh....")
229-
230-
f_x = 0
231-
f_y = 0
232-
f_z = 0
233-
234-
for face in np.asarray(mesh.triangles):
235-
a = np.asarray(mesh.vertices)[face[0]]
236-
b = np.asarray(mesh.vertices)[face[1]]
237-
c = np.asarray(mesh.vertices)[face[2]]
238-
tri_center = np.asarray([(a[0]+b[0]+c[0])/3, (a[1]+b[1]+c[1])/3, (a[2]+b[2]+c[2])/3])
239-
240-
f_x += np.sign(tri_center[0])*(tri_center[0])**2
241-
f_y += np.sign(tri_center[1])*(tri_center[1])**2
242-
f_z += np.sign(tri_center[2])*(tri_center[2])**2
243-
244-
if np.sign(f_x) == -1:
245-
center = get_barycenter(mesh)
246-
R = np.asarray([[np.cos(np.pi), 0, np.sin(np.pi)],[0, 1, 0],[-np.sin(np.pi), 0, np.cos(np.pi)]])
247-
mesh.rotate(R, center=center)
223+
def eigenvectors_check(mesh):
248224

249-
if np.sign(f_y) == -1:
250-
center = get_barycenter(mesh)
251-
R = np.asarray([[1, 0, 0], [0, np.cos(np.pi), -np.sin(np.pi)], [0, np.sin(np.pi), np.cos(np.pi)]])
252-
mesh.rotate(R, center=center)
225+
eig_vec, eig_val = compute_pca(mesh)
226+
sort_eig_val = sorted(eig_val)
227+
index_maj = np.where(eig_val == sort_eig_val[2])[0][0]
228+
maj_eig_vec = eig_vec[:, index_maj]
253229

254-
if np.sign(f_z) == -1:
255-
center = get_barycenter(mesh)
256-
R = np.asarray([[np.cos(np.pi), 0, np.sin(np.pi)], [0, 1, 0], [-np.sin(np.pi), 0, np.cos(np.pi)]])
257-
mesh.rotate(R, center=center)
230+
index_med = np.where(eig_val == sort_eig_val[1])[0][0]
231+
med_eig_vec = eig_vec[:, index_med]
232+
maj_cross_med = np.cross(maj_eig_vec, med_eig_vec)
258233

259-
center = get_barycenter(mesh)
260-
R = np.asarray([[np.cos(-1/4 * np.pi), -np.sin(-1/4 * np.pi), 0], [np.sin(-1/4*np.pi), np.cos(-1/4*np.pi), 0], [0,0,1]])
261-
mesh.rotate(R, center=center)
234+
dot_x = np.absolute(np.dot(maj_eig_vec, [1, 0, 0]))
235+
dot_y = np.absolute(np.dot(med_eig_vec, [0, 1, 0]))
236+
dot_z = np.absolute(np.dot(maj_cross_med, [0, 0, 1]))
262237

263-
print("Mesh flipped.")
238+
value = (dot_x + dot_y + dot_z) / 3
264239

265-
return mesh
240+
return value
266241

267-
"""
268242

269243
def flip_test(mesh):
270244
"""
@@ -319,51 +293,23 @@ def flip_test(mesh):
319293
return mesh
320294

321295

296+
def flip_test_check(mesh):
322297

298+
f_x = 0
299+
f_y = 0
300+
f_z = 0
323301

324-
"""def testing():
325-
326-
coord_frame = o3d.geometry.TriangleMesh.create_coordinate_frame(origin=[0, 0, 0])
327-
328-
#mesh = load_mesh("./benchmark/db_refined/14/m1450/m1450.off") #random mesh
329-
330-
#mesh = load_mesh("./benchmark/db_refined/11/m1112/m1112.off") #f_x negative #very not watertight, like not at allllll
331-
#mesh = load_mesh("./benchmark/db_refined/6/m672/m672.off") #f_x negative --> needs inversion
332-
#mesh = load_mesh("./benchmark/db_refined/0/m12/m12.off") #f_y negative --> needs inversion
333-
#mesh = load_mesh("./benchmark/db_refined/17/m1777/m1777.off") #f_z negative --> needs inversion #rotate around y axis 180 degrees
334-
335-
#mesh = load_mesh("./benchmark/db_refined/14/m1450/m1450.off") #f_x and f_y negative --> no inversion
336-
#mesh = load_mesh("./benchmark/db_refined/5/m556/m556.off") #f_x and f_z negative #flip only x axis --> no inversion
337-
mesh = load_mesh("./benchmark/db_refined/0/m99/m99.off") #f_y and f_z negative #seems to work --> no inversion
338-
339-
340-
#mesh = load_mesh("./benchmark/db_refined/5/m558/m558.off") # f_x, f_y and f_z negative #rotate around the y axis 180 degrees
341-
#mesh = load_mesh("./benchmark/db_refined/18/m1800/m1800.off") #all positive
342-
343-
print(f"Mesh barycenter before normalisation:{get_barycenter(mesh)}")
344-
mesh_norm = copy.deepcopy(mesh)
345-
mesh = translate_to_origin(mesh)
346-
mesh = align_eigenvectors(mesh)
347-
mesh.translate(translation=[-1.5, 0, 0])
348-
349-
mesh_norm = translate_to_origin(mesh_norm)
350-
#view_mesh(mesh_norm, draw_coordinates=True)
351-
#R = mesh.get_rotation_matrix_from_xyz((np.pi / 2, 0, np.pi / 4))
352-
#mesh_norm.rotate(R, center=get_barycenter(mesh))
353-
print(f"Mesh barycenter before rotation:{get_barycenter(mesh_norm)}")
354-
355-
mesh_copy = copy.deepcopy(mesh_norm)
356-
357-
mesh_norm = align_eigenvectors(mesh_norm)
358-
mesh_norm = flip_test(mesh_norm)
359-
360-
mesh.compute_vertex_normals()
361-
mesh_norm.compute_vertex_normals()
362-
363-
364-
o3d.visualization.draw_geometries([mesh, mesh_norm])
365-
366-
367-
testing()"""
302+
for face in np.asarray(mesh.triangles):
303+
a = np.asarray(mesh.vertices)[face[0]]
304+
b = np.asarray(mesh.vertices)[face[1]]
305+
c = np.asarray(mesh.vertices)[face[2]]
306+
tri_center = np.asarray([(a[0]+b[0]+c[0])/3, (a[1]+b[1]+c[1])/3, (a[2]+b[2]+c[2])/3])
368307

308+
f_x += np.sign(tri_center[0])*(tri_center[0])**2
309+
f_y += np.sign(tri_center[1])*(tri_center[1])**2
310+
f_z += np.sign(tri_center[2])*(tri_center[2])**2
369311

312+
if f_x > 0 and f_y > 0 and f_z > 0:
313+
return 1
314+
else:
315+
return -1

0 commit comments

Comments
 (0)