improved apex detection algorithm
Browse files- handcrafted_solution.py +87 -28
handcrafted_solution.py
CHANGED
@@ -11,11 +11,68 @@ from scipy.spatial.distance import cdist
|
|
11 |
from hoho.read_write_colmap import read_cameras_binary, read_images_binary, read_points3D_binary
|
12 |
from hoho.color_mappings import gestalt_color_mapping, ade20k_color_mapping
|
13 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
14 |
|
15 |
def empty_solution():
|
16 |
'''Return a minimal valid solution, i.e. 2 vertices and 1 edge.'''
|
17 |
return np.zeros((2,3)), [(0, 1)]
|
18 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
19 |
|
20 |
def convert_entry_to_human_readable(entry):
|
21 |
out = {}
|
@@ -42,34 +99,34 @@ def get_vertices_and_edges_from_segmentation(gest_seg_np, edge_th = 50.0):
|
|
42 |
vertices = []
|
43 |
connections = []
|
44 |
# Apex
|
45 |
-
|
46 |
-
|
47 |
-
|
48 |
-
|
49 |
-
|
50 |
-
|
51 |
-
|
52 |
-
|
53 |
-
|
54 |
-
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
|
|
|
|
66 |
# Connectivity
|
67 |
-
apex_pts = []
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
apex_pts_idxs.append(j)
|
72 |
-
apex_pts = np.array(apex_pts)
|
73 |
|
74 |
# Ridge connects two apex points
|
75 |
for edge_class in ['eave', 'ridge', 'rake', 'valley']:
|
@@ -106,6 +163,8 @@ def get_vertices_and_edges_from_segmentation(gest_seg_np, edge_th = 50.0):
|
|
106 |
for a_i, a in enumerate(connected_verts):
|
107 |
for b in connected_verts[a_i+1:]:
|
108 |
connections.append((a, b))
|
|
|
|
|
109 |
return vertices, connections
|
110 |
|
111 |
def get_uv_depth(vertices, depth):
|
|
|
11 |
from hoho.read_write_colmap import read_cameras_binary, read_images_binary, read_points3D_binary
|
12 |
from hoho.color_mappings import gestalt_color_mapping, ade20k_color_mapping
|
13 |
|
14 |
+
apex_color = gestalt_color_mapping["apex"]
|
15 |
+
eave_end_point = gestalt_color_mapping["eave_end_point"]
|
16 |
+
flashing_end_point = gestalt_color_mapping["flashing_end_point"]
|
17 |
+
|
18 |
+
apex_color, eave_end_point, flashing_end_point = [np.array(i) for i in [apex_color, eave_end_point, flashing_end_point]]
|
19 |
+
unclassified = np.array([(215, 62, 138)])
|
20 |
+
line_classes = ['eave', 'ridge', 'rake', 'valley']
|
21 |
|
22 |
def empty_solution():
|
23 |
'''Return a minimal valid solution, i.e. 2 vertices and 1 edge.'''
|
24 |
return np.zeros((2,3)), [(0, 1)]
|
25 |
+
|
26 |
+
|
27 |
+
|
28 |
+
def undesired_objects(image):
|
29 |
+
image = image.astype('uint8')
|
30 |
+
nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(image, connectivity=8)
|
31 |
+
sizes = stats[:, -1]
|
32 |
+
max_label = 1
|
33 |
+
max_size = sizes[1]
|
34 |
+
for i in range(2, nb_components):
|
35 |
+
if sizes[i] > max_size:
|
36 |
+
max_label = i
|
37 |
+
max_size = sizes[i]
|
38 |
+
|
39 |
+
img2 = np.zeros(output.shape)
|
40 |
+
img2[output == max_label] = 1
|
41 |
+
return img2
|
42 |
+
|
43 |
+
def clean_image(image_gestalt) -> np.ndarray:
|
44 |
+
# clears image in from of unclassified and disconected components
|
45 |
+
image_gestalt = np.array(image_gestalt)
|
46 |
+
unclassified_mask = cv2.inRange(image_gestalt, unclassified + 0.0, unclassified + 0.8)
|
47 |
+
unclassified_mask = cv2.bitwise_not(unclassified_mask)
|
48 |
+
mask = undesired_objects(unclassified_mask).astype(np.uint8)
|
49 |
+
mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, np.ones((11, 11), np.uint8), iterations=11)
|
50 |
+
|
51 |
+
image_gestalt[:, :, 0] *= mask
|
52 |
+
image_gestalt[:, :, 1] *= mask
|
53 |
+
image_gestalt[:, :, 2] *= mask
|
54 |
+
return image_gestalt
|
55 |
+
|
56 |
+
|
57 |
+
def get_vertices(image_gestalt, *, color_range=4., dialations=3, erosions=1, kernel_size=13):
|
58 |
+
|
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, flashing_end_point + color_range)
|
62 |
+
# eave_end_point_mask = cv2.bitwise_or(eave_end_point_mask, flashing_end_point_mask)
|
63 |
+
|
64 |
+
kernel = np.ones((kernel_size, kernel_size), np.uint8)
|
65 |
+
|
66 |
+
apex_mask = cv2.morphologyEx(apex_mask, cv2.MORPH_DILATE, kernel, iterations=dialations)
|
67 |
+
apex_mask = cv2.morphologyEx(apex_mask, cv2.MORPH_ERODE, kernel, iterations=erosions)
|
68 |
+
|
69 |
+
eave_end_point_mask = cv2.morphologyEx(eave_end_point_mask, cv2.MORPH_DILATE, kernel, iterations=dialations)
|
70 |
+
eave_end_point_mask = cv2.morphologyEx(eave_end_point_mask, cv2.MORPH_ERODE, kernel, iterations=erosions)
|
71 |
+
|
72 |
+
*_, apex_centroids = cv2.connectedComponentsWithStats(apex_mask, connectivity=8)
|
73 |
+
*_, other_centroids = cv2.connectedComponentsWithStats(eave_end_point_mask, connectivity=8)
|
74 |
+
|
75 |
+
return [apex_centroids[1:], other_centroids[1:]]
|
76 |
|
77 |
def convert_entry_to_human_readable(entry):
|
78 |
out = {}
|
|
|
99 |
vertices = []
|
100 |
connections = []
|
101 |
# Apex
|
102 |
+
gest_seg_np = clean_image(gest_seg_np)
|
103 |
+
apex_centroids, eave_end_point_centroids = get_vertices(gest_seg_np)
|
104 |
+
# apex_color = np.array(gestalt_color_mapping['apex'])
|
105 |
+
# apex_mask = cv2.inRange(gest_seg_np, apex_color-0.5, apex_color+0.5)
|
106 |
+
# if apex_mask.sum() > 0:
|
107 |
+
# output = cv2.connectedComponentsWithStats(apex_mask, 8, cv2.CV_32S)
|
108 |
+
# (numLabels, labels, stats, centroids) = output
|
109 |
+
# stats, centroids = stats[1:], centroids[1:]
|
110 |
+
#
|
111 |
+
# for i in range(numLabels-1):
|
112 |
+
# vert = {"xy": centroids[i], "type": "apex"}
|
113 |
+
# vertices.append(vert)
|
114 |
+
#
|
115 |
+
# eave_end_color = np.array(gestalt_color_mapping['eave_end_point'])
|
116 |
+
# eave_end_mask = cv2.inRange(gest_seg_np, eave_end_color-0.5, eave_end_color+0.5)
|
117 |
+
# if eave_end_mask.sum() > 0:
|
118 |
+
# output = cv2.connectedComponentsWithStats(eave_end_mask, 8, cv2.CV_32S)
|
119 |
+
# (numLabels, labels, stats, centroids) = output
|
120 |
+
# stats, centroids = stats[1:], centroids[1:]
|
121 |
+
#
|
122 |
+
# for i in range(numLabels-1):
|
123 |
+
# vert = {"xy": centroids[i], "type": "eave_end_point"}
|
124 |
+
# vertices.append(vert)
|
125 |
# Connectivity
|
126 |
+
# apex_pts = []
|
127 |
+
# for j, v in enumerate(vertices):
|
128 |
+
# apex_pts.append(v['xy'])
|
129 |
+
apex_pts = np.concatenate([apex_centroids, eave_end_point_centroids])
|
|
|
|
|
130 |
|
131 |
# Ridge connects two apex points
|
132 |
for edge_class in ['eave', 'ridge', 'rake', 'valley']:
|
|
|
163 |
for a_i, a in enumerate(connected_verts):
|
164 |
for b in connected_verts[a_i+1:]:
|
165 |
connections.append((a, b))
|
166 |
+
vertices = [{"xy": v, "type": "apex"} for v in apex_centroids]
|
167 |
+
vertices += [{"xy": v, "type": "eave_end_point"} for v in eave_end_point_centroids]
|
168 |
return vertices, connections
|
169 |
|
170 |
def get_uv_depth(vertices, depth):
|