dmytromishkin jacklangerman commited on
Commit
de91949
1 Parent(s): 11827d2

separate-cv (#5)

Browse files

- separate cv_ins and cv_del + bump to 0.4 (5f7484847a971a72cf4c160f4a4bb00f7db7a077)
- fix docs (default for cv_del was stated incorrectly) (60d33017b34aa90e6e7b8625fe2dbab202461780)
- remove mean distance option for cv (bb60056dc5c76eca8e8277a8fec3a82550fb2c25)


Co-authored-by: Jack Langerman <jacklangerman@users.noreply.huggingface.co>

Files changed (2) hide show
  1. hoho/wed.py +21 -21
  2. setup.py +1 -1
hoho/wed.py CHANGED
@@ -28,40 +28,40 @@ 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 +70,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
+ return cv
37
+
38
+ 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):
39
  '''The function computes the Wireframe Edge Distance (WED) between two graphs.
40
  pd_vertices: list of predicted vertices
41
  pd_edges: list of predicted edges
42
  gt_vertices: list of ground truth vertices
43
  gt_edges: list of ground truth edges
44
+ 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)
45
+ 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/4)
46
  ce: edge cost (multiplier of the edge length for edge deletion and insertion, default is 1.0)
47
  normalized: if True, the WED is normalized by the total length of the ground truth edges
48
  preregister: if True, the predicted vertices have their mean and scale matched to the ground truth vertices
49
  '''
50
 
 
 
 
 
 
51
  pd_vertices = np.array(pd_vertices)
52
  gt_vertices = np.array(gt_vertices)
53
+ pd_edges = np.array(pd_edges)
54
+ gt_edges = np.array(gt_edges)
55
 
56
+
57
+ cv_del = update_cv(cv_del, gt_vertices)
58
+ cv_ins = update_cv(cv_ins, gt_vertices)
 
 
59
 
60
  # Step 0: Prenormalize / preregister
61
  if preregister:
62
  pd_vertices = preregister_mean_std(pd_vertices, gt_vertices, single_scale=single_scale)
 
 
 
 
63
 
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
  # Step 2: Vertex Translation
71
  translation_costs = np.sum(distances[row_ind, col_ind])
72
 
73
+ # Step 3: Vertex Deletion
74
  unmatched_pd_indices = set(range(len(pd_vertices))) - set(row_ind)
75
+ deletion_costs = cv_del * len(unmatched_pd_indices)
76
 
77
+ # Step 4: Vertex Insertion
78
  unmatched_gt_indices = set(range(len(gt_vertices))) - set(col_ind)
79
+ insertion_costs = cv_ins * len(unmatched_gt_indices)
80
 
81
+ # Step 5: 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]))
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',