jacklangerman commited on
Commit
090f8d2
2 Parent(s): 11827d2 3150ada

Merge branch 'pr/2' into pr/4

Browse files
Files changed (2) hide show
  1. hoho/wed.py +24 -21
  2. setup.py +1 -1
hoho/wed.py CHANGED
@@ -28,40 +28,43 @@ def preregister_mean_std(verts_to_transform, target_verts, single_scale=True):
28
  return transformed_verts
29
 
30
 
31
- def compute_WED(pd_vertices, pd_edges, gt_vertices, gt_edges, cv=-1, ce=1.0, normalized=True, preregister=True, single_scale=True):
 
 
 
 
 
 
 
 
 
 
32
  '''The function computes the Wireframe Edge Distance (WED) between two graphs.
33
  pd_vertices: list of predicted vertices
34
  pd_edges: list of predicted edges
35
  gt_vertices: list of ground truth vertices
36
  gt_edges: list of ground truth edges
37
- cv: vertex cost (the cost in centimeters of missing a vertex, default is -1, which means 1/4 of the diameter of the ground truth mesh)
 
38
  ce: edge cost (multiplier of the edge length for edge deletion and insertion, default is 1.0)
39
  normalized: if True, the WED is normalized by the total length of the ground truth edges
40
  preregister: if True, the predicted vertices have their mean and scale matched to the ground truth vertices
41
  '''
42
 
43
- # Vertex coordinates are in centimeters. When cv and ce are set to 100.0 and 1.0 respectively,
44
- # missing a vertex is equivanlent predicting it 1 meter away from the ground truth vertex.
45
- # This is equivalent to setting cv=1 and ce=1 when the vertex coordinates are in meters.
46
- # When a negative cv value is set (the default behavior), cv is reset to 1/4 of the diameter of the ground truth wireframe.
47
-
48
  pd_vertices = np.array(pd_vertices)
49
  gt_vertices = np.array(gt_vertices)
 
 
50
 
51
- diameter = cdist(gt_vertices, gt_vertices).max()
52
-
53
- if cv < 0:
54
- cv = diameter / 4.0
55
- # Cost of addining or deleting a vertex is set to 1/4 of the diameter of the ground truth mesh
56
 
57
  # Step 0: Prenormalize / preregister
58
  if preregister:
59
  pd_vertices = preregister_mean_std(pd_vertices, gt_vertices, single_scale=single_scale)
60
-
61
-
62
- pd_edges = np.array(pd_edges)
63
- gt_edges = np.array(gt_edges)
64
 
 
65
  # Step 1: Bipartite Matching
66
  distances = cdist(pd_vertices, gt_vertices, metric='euclidean')
67
  row_ind, col_ind = linear_sum_assignment(distances)
@@ -70,15 +73,15 @@ def compute_WED(pd_vertices, pd_edges, gt_vertices, gt_edges, cv=-1, ce=1.0, nor
70
  # Step 2: Vertex Translation
71
  translation_costs = np.sum(distances[row_ind, col_ind])
72
 
73
- # Additional: Vertex Deletion
74
  unmatched_pd_indices = set(range(len(pd_vertices))) - set(row_ind)
75
- deletion_costs = cv * len(unmatched_pd_indices)
76
 
77
- # Step 3: Vertex Insertion
78
  unmatched_gt_indices = set(range(len(gt_vertices))) - set(col_ind)
79
- insertion_costs = cv * len(unmatched_gt_indices)
80
 
81
- # Step 4: Edge Deletion and Insertion
82
  updated_pd_edges = [(col_ind[np.where(row_ind == edge[0])[0][0]], col_ind[np.where(row_ind == edge[1])[0][0]]) for edge in pd_edges if edge[0] in row_ind and edge[1] in row_ind]
83
  pd_edges_set = set(map(tuple, [set(edge) for edge in updated_pd_edges]))
84
  gt_edges_set = set(map(tuple, [set(edge) for edge in gt_edges]))
 
28
  return transformed_verts
29
 
30
 
31
+ def update_cv(cv, gt_vertices):
32
+ if cv < 0:
33
+ diameter = cdist(gt_vertices, gt_vertices).max()
34
+ # Cost of adding or deleting a vertex is set to -cv times the diameter of the ground truth wireframe
35
+ cv = -cv * diameter
36
+ elif cv == 0:
37
+ # Cost of adding or deleting a vertex is set to the average distance of the ground truth vertices from their mean
38
+ cv = np.linalg.norm(np.mean(gt_vertices, axis=0) - gt_vertices, axis=1).mean()
39
+ return cv
40
+
41
+ def compute_WED(pd_vertices, pd_edges, gt_vertices, gt_edges, cv_ins=-1/2, cv_del=-1/4, ce=1.0, normalized=True, preregister=True, single_scale=True):
42
  '''The function computes the Wireframe Edge Distance (WED) between two graphs.
43
  pd_vertices: list of predicted vertices
44
  pd_edges: list of predicted edges
45
  gt_vertices: list of ground truth vertices
46
  gt_edges: list of ground truth edges
47
+ cv_ins: vertex insertion cost: if positive, the cost in centimeters of inserting vertex, if negative, multiplies diameter to compute cost (default is -1/2)
48
+ cv_del: vertex deletion cost: if positive, the cost in centimeters of deleting a vertex, if negative, multiplies diameter to compute cost (default is -1/2)
49
  ce: edge cost (multiplier of the edge length for edge deletion and insertion, default is 1.0)
50
  normalized: if True, the WED is normalized by the total length of the ground truth edges
51
  preregister: if True, the predicted vertices have their mean and scale matched to the ground truth vertices
52
  '''
53
 
 
 
 
 
 
54
  pd_vertices = np.array(pd_vertices)
55
  gt_vertices = np.array(gt_vertices)
56
+ pd_edges = np.array(pd_edges)
57
+ gt_edges = np.array(gt_edges)
58
 
59
+
60
+ cv_del = update_cv(cv_del, gt_vertices)
61
+ cv_ins = update_cv(cv_ins, gt_vertices)
 
 
62
 
63
  # Step 0: Prenormalize / preregister
64
  if preregister:
65
  pd_vertices = preregister_mean_std(pd_vertices, gt_vertices, single_scale=single_scale)
 
 
 
 
66
 
67
+
68
  # Step 1: Bipartite Matching
69
  distances = cdist(pd_vertices, gt_vertices, metric='euclidean')
70
  row_ind, col_ind = linear_sum_assignment(distances)
 
73
  # Step 2: Vertex Translation
74
  translation_costs = np.sum(distances[row_ind, col_ind])
75
 
76
+ # Step 3: Vertex Deletion
77
  unmatched_pd_indices = set(range(len(pd_vertices))) - set(row_ind)
78
+ deletion_costs = cv_del * len(unmatched_pd_indices)
79
 
80
+ # Step 4: Vertex Insertion
81
  unmatched_gt_indices = set(range(len(gt_vertices))) - set(col_ind)
82
+ insertion_costs = cv_ins * len(unmatched_gt_indices)
83
 
84
+ # Step 5: Edge Deletion and Insertion
85
  updated_pd_edges = [(col_ind[np.where(row_ind == edge[0])[0][0]], col_ind[np.where(row_ind == edge[1])[0][0]]) for edge in pd_edges if edge[0] in row_ind and edge[1] in row_ind]
86
  pd_edges_set = set(map(tuple, [set(edge) for edge in updated_pd_edges]))
87
  gt_edges_set = set(map(tuple, [set(edge) for edge in gt_edges]))
setup.py CHANGED
@@ -6,7 +6,7 @@ with open('requirements.txt') as f:
6
  required = f.read().splitlines()
7
 
8
  setup(name='hoho',
9
- version='0.0.3',
10
  description='Tools and utilites for the HoHo Dataset and S23DR Competition',
11
  url='usm3d.github.io',
12
  author='Jack Langerman, Dmytro Mishkin, S23DR Orgainizing Team',
 
6
  required = f.read().splitlines()
7
 
8
  setup(name='hoho',
9
+ version='0.0.4',
10
  description='Tools and utilites for the HoHo Dataset and S23DR Competition',
11
  url='usm3d.github.io',
12
  author='Jack Langerman, Dmytro Mishkin, S23DR Orgainizing Team',