Siromanec commited on
Commit
c0998c1
1 Parent(s): a59f406

half implemented missing point detection; scale_estimation_coefficient =4

Browse files
Files changed (3) hide show
  1. handcrafted_solution.py +43 -6
  2. script.py +1 -1
  3. test_solution.ipynb +0 -0
handcrafted_solution.py CHANGED
@@ -9,6 +9,7 @@ import numpy as np
9
  from PIL import Image as PImage
10
  from hoho.color_mappings import gestalt_color_mapping
11
  from hoho.read_write_colmap import read_cameras_binary, read_images_binary, read_points3D_binary
 
12
  from scipy.spatial.distance import cdist
13
 
14
  apex_color = gestalt_color_mapping["apex"]
@@ -48,6 +49,7 @@ def clean_image(image_gestalt) -> np.ndarray:
48
  unclassified_mask = cv2.bitwise_not(unclassified_mask)
49
  mask = undesired_objects(unclassified_mask).astype(np.uint8)
50
  mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, np.ones((11, 11), np.uint8), iterations=11)
 
51
 
52
  image_gestalt[:, :, 0] *= mask
53
  image_gestalt[:, :, 1] *= mask
@@ -56,6 +58,7 @@ def clean_image(image_gestalt) -> np.ndarray:
56
 
57
 
58
  def get_vertices(image_gestalt, *, color_range=4., dialations=3, erosions=1, kernel_size=13):
 
59
  apex_mask = cv2.inRange(image_gestalt, apex_color - color_range, apex_color + color_range)
60
  eave_end_point_mask = cv2.inRange(image_gestalt, eave_end_point - color_range, eave_end_point + color_range)
61
  flashing_end_point_mask = cv2.inRange(image_gestalt, flashing_end_point - color_range,
@@ -76,6 +79,35 @@ def get_vertices(image_gestalt, *, color_range=4., dialations=3, erosions=1, ker
76
  return apex_centroids[1:], other_centroids[1:], apex_mask, eave_end_point_mask
77
 
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  def convert_entry_to_human_readable(entry):
80
  out = {}
81
  already_good = {'__key__', 'wf_vertices', 'wf_edges', 'edge_semantics', 'mesh_vertices', 'mesh_faces',
@@ -98,7 +130,8 @@ def convert_entry_to_human_readable(entry):
98
  return out
99
 
100
 
101
- def get_vertices_and_edges_from_segmentation(gest_seg_np, *, color_range=4., point_radius=30, max_angle=5., extend = 35, **kwargs):
 
102
  '''Get the vertices and edges from the gestalt segmentation mask of the house'''
103
  # Apex
104
  connections = []
@@ -107,6 +140,9 @@ def get_vertices_and_edges_from_segmentation(gest_seg_np, *, color_range=4., poi
107
  apex_centroids, eave_end_point_centroids, apex_mask, eave_end_point_mask = get_vertices(gest_seg_np)
108
 
109
  vertices = np.concatenate([apex_centroids, eave_end_point_centroids])
 
 
 
110
 
111
  scale = 1
112
  vertex_size = np.zeros(vertices.shape[0])
@@ -239,6 +275,7 @@ def get_vertices_and_edges_from_segmentation(gest_seg_np, *, color_range=4., poi
239
  connections.append(possible_connections[:, fitted_line_idx])
240
 
241
  vertices = [{"xy": v, "type": "apex"} for v in apex_centroids]
 
242
  vertices += [{"xy": v, "type": "eave_end_point"} for v in eave_end_point_centroids]
243
  return vertices, connections
244
 
@@ -257,7 +294,7 @@ def get_uv_depth(vertices, depth):
257
  return uv, vertex_depth
258
 
259
 
260
- def merge_vertices_3d(vert_edge_per_image, th=0.1):
261
  '''Merge vertices that are close to each other in 3D space and are of same types'''
262
  all_3d_vertices = []
263
  connections_3d = []
@@ -274,7 +311,7 @@ def merge_vertices_3d(vert_edge_per_image, th=0.1):
274
  distmat = cdist(all_3d_vertices, all_3d_vertices)
275
  types = np.array(types).reshape(-1, 1)
276
  same_types = cdist(types, types)
277
- mask_to_merge = (distmat <= th) & (same_types == 0)
278
  new_vertices = []
279
  new_connections = []
280
  to_merge = sorted(list(set([tuple(a.nonzero()[0].tolist()) for a in mask_to_merge])))
@@ -335,7 +372,7 @@ def prune_not_connected(all_3d_vertices, connections_3d):
335
  return np.array(new_verts), connected_out
336
 
337
 
338
- def predict(entry, visualize=False, **kwargs) -> Tuple[np.ndarray, List[int]]:
339
  good_entry = convert_entry_to_human_readable(entry)
340
  if 'gestalt' not in good_entry or 'depthcm' not in good_entry or 'K' not in good_entry or 'R' not in good_entry or 't' not in good_entry:
341
  print('Missing required fields in the entry')
@@ -350,7 +387,7 @@ def predict(entry, visualize=False, **kwargs) -> Tuple[np.ndarray, List[int]]:
350
  gest_seg = gest.resize(depth.size)
351
  gest_seg_np = np.array(gest_seg).astype(np.uint8)
352
  # Metric3D
353
- depth_np = np.array(depth) / 2.5 # 2.5 is the scale estimation coefficient
354
  vertices, connections = get_vertices_and_edges_from_segmentation(gest_seg_np, **kwargs)
355
  if (len(vertices) < 2) or (len(connections) < 1):
356
  print(f'Not enough vertices or connections in image {i}')
@@ -370,7 +407,7 @@ def predict(entry, visualize=False, **kwargs) -> Tuple[np.ndarray, List[int]]:
370
  vertices_3d = cv2.transform(cv2.convertPointsToHomogeneous(vertices_3d_local), cam_to_world)
371
  vertices_3d = cv2.convertPointsFromHomogeneous(vertices_3d).reshape(-1, 3)
372
  vert_edge_per_image[i] = vertices, connections, vertices_3d
373
- all_3d_vertices, connections_3d = merge_vertices_3d(vert_edge_per_image, 3.0)
374
  all_3d_vertices_clean, connections_3d_clean = prune_not_connected(all_3d_vertices, connections_3d)
375
  if (len(all_3d_vertices_clean) < 2) or len(connections_3d_clean) < 1:
376
  print(f'Not enough vertices or connections in the 3D vertices')
 
9
  from PIL import Image as PImage
10
  from hoho.color_mappings import gestalt_color_mapping
11
  from hoho.read_write_colmap import read_cameras_binary, read_images_binary, read_points3D_binary
12
+ from scipy.spatial import KDTree
13
  from scipy.spatial.distance import cdist
14
 
15
  apex_color = gestalt_color_mapping["apex"]
 
49
  unclassified_mask = cv2.bitwise_not(unclassified_mask)
50
  mask = undesired_objects(unclassified_mask).astype(np.uint8)
51
  mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, np.ones((11, 11), np.uint8), iterations=11)
52
+ mask = cv2.morphologyEx(mask, cv2.MORPH_DILATE, np.ones((11, 11), np.uint8), iterations=2)
53
 
54
  image_gestalt[:, :, 0] *= mask
55
  image_gestalt[:, :, 1] *= mask
 
58
 
59
 
60
  def get_vertices(image_gestalt, *, color_range=4., dialations=3, erosions=1, kernel_size=13):
61
+ ### detects the apex and eave end and flashing end points
62
  apex_mask = cv2.inRange(image_gestalt, apex_color - color_range, apex_color + color_range)
63
  eave_end_point_mask = cv2.inRange(image_gestalt, eave_end_point - color_range, eave_end_point + color_range)
64
  flashing_end_point_mask = cv2.inRange(image_gestalt, flashing_end_point - color_range,
 
79
  return apex_centroids[1:], other_centroids[1:], apex_mask, eave_end_point_mask
80
 
81
 
82
+ def infer_vertices(image_gestalt, *, color_range=4.):
83
+ ridge_color = np.array(gestalt_color_mapping["ridge"])
84
+ rake_color = np.array(gestalt_color_mapping["rake"])
85
+ ridge_mask = cv2.inRange(image_gestalt,
86
+ ridge_color - color_range,
87
+ ridge_color + color_range)
88
+ ridge_mask = cv2.morphologyEx(ridge_mask,
89
+ cv2.MORPH_DILATE, np.ones((3, 3)), iterations=4)
90
+ rake_mask = cv2.inRange(image_gestalt,
91
+ rake_color - color_range,
92
+ rake_color + color_range)
93
+ rake_mask = cv2.morphologyEx(rake_mask,
94
+ cv2.MORPH_DILATE, np.ones((3, 3)), iterations=4)
95
+
96
+ intersection_mask = cv2.bitwise_and(ridge_mask, rake_mask)
97
+ intersection_mask = cv2.morphologyEx(intersection_mask, cv2.MORPH_DILATE, np.ones((11, 11)), iterations=3)
98
+
99
+ *_, inferred_centroids = cv2.connectedComponentsWithStats(intersection_mask, connectivity=8, stats=cv2.CV_32S)
100
+
101
+ return inferred_centroids[1:], intersection_mask
102
+
103
+
104
+ def get_missed_vertices(vertices, inferred_centroids, *, min_missing_distance=200.0, **kwargs):
105
+ vertices = KDTree(vertices)
106
+ closest = vertices.query(inferred_centroids, k=1, distance_upper_bound=min_missing_distance)
107
+ missed_points = inferred_centroids[closest[1] == len(vertices.data)]
108
+ return missed_points
109
+
110
+
111
  def convert_entry_to_human_readable(entry):
112
  out = {}
113
  already_good = {'__key__', 'wf_vertices', 'wf_edges', 'edge_semantics', 'mesh_vertices', 'mesh_faces',
 
130
  return out
131
 
132
 
133
+ def get_vertices_and_edges_from_segmentation(gest_seg_np, *, color_range=4., point_radius=30, max_angle=5., extend=35,
134
+ **kwargs):
135
  '''Get the vertices and edges from the gestalt segmentation mask of the house'''
136
  # Apex
137
  connections = []
 
140
  apex_centroids, eave_end_point_centroids, apex_mask, eave_end_point_mask = get_vertices(gest_seg_np)
141
 
142
  vertices = np.concatenate([apex_centroids, eave_end_point_centroids])
143
+ # inferred_vertices, inferred_mask = infer_vertices(gest_seg_np)
144
+ # missed_vertices = get_missed_vertices(vertices, inferred_vertices, **kwargs)
145
+ # vertices = np.concatenate([vertices, missed_vertices])
146
 
147
  scale = 1
148
  vertex_size = np.zeros(vertices.shape[0])
 
275
  connections.append(possible_connections[:, fitted_line_idx])
276
 
277
  vertices = [{"xy": v, "type": "apex"} for v in apex_centroids]
278
+ # vertices += [{"xy": v, "type": "apex"} for v in missed_vertices]
279
  vertices += [{"xy": v, "type": "eave_end_point"} for v in eave_end_point_centroids]
280
  return vertices, connections
281
 
 
294
  return uv, vertex_depth
295
 
296
 
297
+ def merge_vertices_3d(vert_edge_per_image, merge_th=0.1, **kwargs):
298
  '''Merge vertices that are close to each other in 3D space and are of same types'''
299
  all_3d_vertices = []
300
  connections_3d = []
 
311
  distmat = cdist(all_3d_vertices, all_3d_vertices)
312
  types = np.array(types).reshape(-1, 1)
313
  same_types = cdist(types, types)
314
+ mask_to_merge = (distmat <= merge_th) & (same_types == 0)
315
  new_vertices = []
316
  new_connections = []
317
  to_merge = sorted(list(set([tuple(a.nonzero()[0].tolist()) for a in mask_to_merge])))
 
372
  return np.array(new_verts), connected_out
373
 
374
 
375
+ def predict(entry, visualize=False, scale_estimation_coefficient=2.5, **kwargs) -> Tuple[np.ndarray, List[int]]:
376
  good_entry = convert_entry_to_human_readable(entry)
377
  if 'gestalt' not in good_entry or 'depthcm' not in good_entry or 'K' not in good_entry or 'R' not in good_entry or 't' not in good_entry:
378
  print('Missing required fields in the entry')
 
387
  gest_seg = gest.resize(depth.size)
388
  gest_seg_np = np.array(gest_seg).astype(np.uint8)
389
  # Metric3D
390
+ depth_np = np.array(depth) / scale_estimation_coefficient # 2.5 is the scale estimation coefficient
391
  vertices, connections = get_vertices_and_edges_from_segmentation(gest_seg_np, **kwargs)
392
  if (len(vertices) < 2) or (len(connections) < 1):
393
  print(f'Not enough vertices or connections in image {i}')
 
407
  vertices_3d = cv2.transform(cv2.convertPointsToHomogeneous(vertices_3d_local), cam_to_world)
408
  vertices_3d = cv2.convertPointsFromHomogeneous(vertices_3d).reshape(-1, 3)
409
  vert_edge_per_image[i] = vertices, connections, vertices_3d
410
+ all_3d_vertices, connections_3d = merge_vertices_3d(vert_edge_per_image, **kwargs)
411
  all_3d_vertices_clean, connections_3d_clean = prune_not_connected(all_3d_vertices, connections_3d)
412
  if (len(all_3d_vertices_clean) < 2) or len(connections_3d_clean) < 1:
413
  print(f'Not enough vertices or connections in the 3D vertices')
script.py CHANGED
@@ -127,7 +127,7 @@ if __name__ == "__main__":
127
  with ProcessPoolExecutor(max_workers=8) as pool:
128
  results = []
129
  for i, sample in enumerate(tqdm(dataset)):
130
- results.append(pool.submit(predict, sample, visualize=False, point_radius=25, max_angle=15, extend=30))
131
 
132
  for i, result in enumerate(tqdm(results)):
133
  key, pred_vertices, pred_edges = result.result()
 
127
  with ProcessPoolExecutor(max_workers=8) as pool:
128
  results = []
129
  for i, sample in enumerate(tqdm(dataset)):
130
+ results.append(pool.submit(predict, sample, visualize=False, point_radius=25, max_angle=15, extend=30, merge_th=3.0, min_missing_distance=1000000.0, scale_estimation_coefficient=4))
131
 
132
  for i, result in enumerate(tqdm(results)):
133
  key, pred_vertices, pred_edges = result.result()
test_solution.ipynb CHANGED
The diff for this file is too large to render. See raw diff