3 from random
import randint
5 import matplotlib.colors
8 import matplotlib.pyplot
as plt
12 from PIL
import Image, ImageDraw
13 from skan.csr
import skeleton_to_csgraph
14 from skimage
import io, img_as_bool, img_as_uint, segmentation, img_as_ubyte
15 from skimage.morphology
import skeletonize
16 from skimage.util
import invert
18 from rose_v2_repo.parameters
import ParameterObj
19 from util.disegna
import setup_plot
21 from matplotlib.patches
import PathPatch
22 from matplotlib.path
import Path
23 from descartes
import PolygonPatch
24 from shapely.geometry.polygon
import Polygon
29 new_edges = len(graph.edges)
30 precision = old_edges - new_edges
32 for node
in graph.nodes:
33 tmp = list(graph.neighbors(node))
36 graph.remove_edge(node, tmp[0])
37 graph.remove_edge(node, tmp[1])
38 graph.add_edge(tmp[0], tmp[1])
40 new_edges = len(graph.edges)
41 precision = old_edges - new_edges
43 graph.remove_nodes_from(list(nx.isolates(graph)))
51 new_edges = len(graph.edges)
52 precision = old_edges - new_edges
54 for node
in graph.nodes:
55 tmp = list(graph.neighbors(node))
57 graph.remove_edge(node, tmp[0])
59 new_edges = len(graph.edges)
60 precision = old_edges - new_edges
62 graph.remove_nodes_from(list(nx.isolates(graph)))
67 for node
in graph.nodes:
68 tmp = list(graph.neighbors(node))
72 tmp = list(graph.neighbors(n))
75 graph.remove_edge(n, tmp[0])
76 graph.remove_edge(n, tmp[1])
77 graph.add_edge(tmp[0], tmp[1])
78 graph.remove_nodes_from(list(nx.isolates(graph)))
83 for node
in graph.nodes:
84 tmp = list(graph.neighbors(node))
88 n = list(graph.neighbors(el))
89 graph.remove_edge(el, n[0])
90 graph.remove_nodes_from(list(nx.isolates(graph)))
96 for node
in graph.nodes:
97 tmp = list(graph.neighbors(node))
101 graph.remove_edge(node, tmp[0])
102 graph.remove_edge(node, tmp[1])
103 graph.add_edge(tmp[0], tmp[1])
107 graph.remove_edge(node, tmp[0])
111 graph.remove_nodes_from(list(nx.isolates(graph)))
121 x_coordinates.extend((x1, x2))
122 y_coordinates.extend((y1, y2))
123 ax.plot(x_coordinates, y_coordinates, color=
'k', linewidth=1)
129 li = sorted(nx.connected_components(graph), key=len, reverse=
True)
131 voronoi_graph = graph.subgraph(largest_cc).copy()
134 voronoi_graph.remove_nodes_from(list(nx.isolates(voronoi_graph)))
139 def plot_voronoi(coordinates, voronoi_graph, ax, label, is_labelled, name, filepath):
140 for edge
in voronoi_graph.edges:
141 plot_line(coordinates[edge[0]], coordinates[edge[1]], ax)
142 for node
in voronoi_graph.nodes:
144 col = (label[node][0] / 255, label[node][1] / 255, label[node][2] / 255)
145 ax.scatter(coordinates[node][1], coordinates[node][0], c=matplotlib.colors.rgb2hex(col))
147 ax.scatter(coordinates[node][1], coordinates[node][0])
148 plt.savefig(filepath + name +
'.png')
152 distance = math.sqrt((node1[0] - node2[0]) ** 2 + (node1[1] - node2[1]) ** 2)
157 for node
in graph.nodes:
158 for n
in graph.nodes:
160 graph = nx.contracted_nodes(graph, node, n, self_loops=
False)
169 if label[point] == color:
174 if same_color
is True:
182 pt = [(point1[0] + point2[0]) / 2, (point1[1] + point2[1]) / 2]
183 pt_n = [(n1[0] + n2[0]) / 2, (n1[1] + n2[1]) / 2]
186 for direction
in directions:
187 m = math.tan(direction)
188 c1 = point1[1] - m * point1[0]
189 c2 = point2[1] - m * point2[0]
196 for i, line
in enumerate(lines1):
198 dist = abs(line - par_line) / math.sqrt(1 + math.tan(directions[i]) * math.tan(directions[i]))
199 if max_distance
is None or dist > max_distance:
201 direction = directions[i]
202 m_pt = math.tan(directions[i])
203 c_pt = pt_n[1] - m_pt * pt_n[0]
204 return direction, m_pt, c_pt
211 point1 = (int(x1), int(y1))
213 if y_min <= point1[1] <= y_max:
214 points.append(point1)
217 point2 = (int(x2), int(y2))
219 if y_min <= point2[1] <= y_max:
220 points.append(point2)
223 point3 = (int(x3), int(y3))
225 if x_min <= point3[0] <= x_max:
226 points.append(point3)
229 point4 = (int(x4), int(y4))
231 if x_min <= point4[0] <= x_max:
232 points.append(point4)
240 pt = [int(coordinates[p][1]), int(coordinates[p][0])]
242 if dist > distance
and pix_data[pt[0], pt[1]] == color:
243 point = (int(coordinates[p][1]), int(coordinates[p][0]))
249 new_edges = len(graph.edges)
250 precision = old_edges - new_edges
251 while precision != 0:
252 for node
in graph.nodes:
253 tmp = list(graph.neighbors(node))
254 if len(tmp) == 1
and evaluate_distance(coordinates[node], coordinates[tmp[0]]) < th:
255 graph.remove_edge(node, tmp[0])
256 old_edges = new_edges
257 new_edges = len(graph.edges)
258 precision = old_edges - new_edges
259 graph.remove_nodes_from(list(nx.isolates(graph)))
264 new_edges = len(graph.edges)
265 precision = old_edges - new_edges
266 while precision != 0:
267 for node
in graph.nodes:
268 tmp = list(graph.neighbors(node))
270 graph.remove_edge(node, tmp[0])
271 graph.remove_edge(node, tmp[1])
272 graph.add_edge(tmp[0], tmp[1])
273 old_edges = new_edges
274 new_edges = len(graph.edges)
275 precision = old_edges - new_edges
276 graph.remove_nodes_from(list(nx.isolates(graph)))
281 for node
in graph.nodes:
282 tmp = list(graph.neighbors(node))
283 if len(tmp) == 1
and evaluate_distance(coordinates[node], coordinates[tmp[0]]) < th:
286 n = list(graph.neighbors(el))
288 graph.remove_edge(el, n[0])
289 graph.remove_nodes_from(list(nx.isolates(graph)))
296 copy = cv2.imread(origin)
303 im = cv2.blur(im, (param_obj.blur, param_obj.blur))
304 im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
305 im = cv2.threshold(im, 230, 255, cv2.THRESH_BINARY)[1]
306 im = cv2.bitwise_not(im)
307 cv2.imwrite(
'tmp.png', im, [cv2.IMWRITE_PNG_COMPRESSION,1])
308 initial_map = img_as_bool(io.imread(
'tmp.png'))
312 input_skeleton = invert(initial_map)
316 skeleton = skeletonize(input_skeleton)
317 skeleton_object = skan.csr.Skeleton(skeleton)
318 pixel_graph, coordinates, degrees = skeleton_to_csgraph(skeleton)
321 graph = nx.from_scipy_sparse_array(pixel_graph, edge_attribute=
'weight')
323 rospy.loginfo(
'[rose2] edges initial: {}'.format(len(graph.edges)))
324 rospy.loginfo(
'[rose2] nodes initial: {}'.format(len(graph.nodes)))
352 if len(voronoi_graph.nodes) > 2:
353 voronoi_graph =
remove_close_nodes(voronoi_graph, coordinates, param_obj.voronoi_closeness)
357 graph.remove_nodes_from(list(nx.isolates(graph)))
359 rospy.loginfo(
'[rose2] edges final: {}'.format(len(voronoi_graph.edges)))
360 rospy.loginfo(
'[rose2] nodes final: {}'.format(len(voronoi_graph.nodes)))
365 plot_voronoi(coordinates, voronoi_graph, ax, 0,
False,
'voronoi_graph_' + name, filepath=filepath)
367 return voronoi_graph, coordinates
370 def labelling(voronoi_graph, coordinates, filepath='.'):
373 true_rooms = Image.open(filepath +
'8b_rooms_th1.png')
374 room = Image.open(filepath +
'8b_rooms_th1_on_map_post.png')
375 room_to_divide = room.copy()
377 pix_data_room_divide = room_to_divide.load()
378 pix_data_room = room.load()
379 pix_data_true_room = true_rooms.load()
381 label = [(0, 0, 0, 255)] * len(coordinates)
383 colors_to_divide = []
389 for node
in voronoi_graph.nodes:
390 coor = (int(coordinates[node][1]), int(coordinates[node][0]))
391 color = pix_data_room[coor]
392 color_room = pix_data_true_room[coor]
393 if color == (0, 0, 0, 255):
394 if color_room != (255, 255, 255, 255):
395 label[node] = color_room
396 if color
not in colors
and color != (0, 0, 0, 255):
399 node_to_remove.append(node)
401 elif color == (255, 255, 255, 255):
403 node_to_remove.append(node)
406 if color
not in colors
and color != (0, 0, 0, 255):
410 for i, node
in enumerate(node_to_remove):
411 li = list(voronoi_graph.neighbors(node))
414 if label[n] != (0, 0, 0, 255):
417 voronoi_graph = nx.contracted_nodes(voronoi_graph, ne, node, self_loops=
False)
425 for i, c
in enumerate(label):
426 if c == color
and c != (0, 0, 0, 255):
432 subg = voronoi_graph.subgraph(list_node)
433 if not nx.is_connected(subg):
434 colors_to_divide.append(color)
455 for y
in range(room_to_divide.size[1]):
456 for x
in range(room_to_divide.size[0]):
457 if pix_data_room_divide[x, y]
not in colors_to_divide:
458 pix_data_room_divide[x, y] = (0, 0, 0, 255)
459 room_to_divide.save(filepath +
'rooms_to_divide.png')
461 return colors_to_divide, label, voronoi_graph
467 for subgraph
in subgraphs:
468 x_min, x_max, y_min, y_max = size0, 0, size1, 0
470 x = int(coordinates[n][1])
471 y = int(coordinates[n][0])
480 middle_point = [int((x_max + x_min) / 2), int((y_max + y_min) / 2)]
481 centers.append(middle_point)
484 for i
in list(subgraph):
488 nd = [int(coordinates[i][1]), int(coordinates[i][0])]
489 centers_node.append(nd)
491 return centers, centers_node
496 for v, subgraph
in enumerate(subgraphs):
499 for u, g
in enumerate(subgraphs):
501 if dist < distance
and u != v:
504 list_closer.append(index)
509 x_min, x_max, y_min, y_max = tmp_room.size[0], 0, tmp_room.size[1], 0
510 for y
in range(tmp_room.size[1]):
511 for x
in range(tmp_room.size[0]):
512 if pix_data_tmp[x, y] == new_col[closer]
or pix_data_tmp[x, y] == (0, 0, 0, 255):
522 pix_data_tmp[x, y] = (255, 255, 255, 255)
523 return x_min, x_max, y_min, y_max
530 for node
in subgraph1:
531 node1 = [coordinates[node][1], coordinates[node][0]]
533 node2 = [coordinates[n][1], coordinates[n][0]]
543 side = (point[0] - a[0]) * (b[1] - a[1]) - (point[1] - a[1]) * (b[0] - a[0])
552 def voronoi_segmentation(patches, colors, size, voronoi_graph, coordinates, directions_orebro, im, ind, filepath='.'):
554 true_rooms = Image.open(filepath +
'8b_rooms_th1.png')
555 colors_to_divide, label, voronoi_graph =
labelling(voronoi_graph, coordinates, filepath=filepath)
557 voronoi_graph = voronoi_graph.copy()
558 copy = cv2.imread(im)
560 fig, ax =
setup_plot([im.shape[1], im.shape[0]])
562 plot_voronoi(coordinates, voronoi_graph, ax, label,
True,
'voronoi_graph' + str(ind), filepath=filepath)
566 for color
in colors_to_divide:
569 for i, label_color
in enumerate(label):
570 if label_color == color:
573 for node
in new_nodes:
574 for edge
in voronoi_graph.edges(node):
575 if edge[1]
in new_nodes:
576 g.add_edge(node, edge[1])
577 subgraphs = list(sorted(nx.connected_components(g), key=len, reverse=
True))
582 for li_comp
in subgraphs:
585 already_present.append(ap)
586 if tot != len(new_nodes):
587 for nod
in new_nodes:
588 if nod
not in already_present:
589 subgraphs.append([nod])
591 new_col = [color] * len(subgraphs)
595 centers, centers_node =
compute_centers(true_rooms.size[0], true_rooms.size[1], coordinates, subgraphs)
601 for v, subgraph
in enumerate(subgraphs):
603 tmp_room = Image.open(filepath +
'8b_rooms_th1.png')
604 pix_data_tmp = tmp_room.load()
605 closer = list_closer[v]
606 if not (v
in analyzed
and closer
in analyzed):
609 analyzed.append(closer)
613 seed1 =
compute_most_distant(list(subgraph), centers[closer], coordinates, pix_data_tmp, new_col[v])
615 seed2 =
compute_most_distant(list(subgraphs[closer]), centers[v], coordinates, pix_data_tmp, new_col[v])
618 if not (seed1
is None or seed2
is None):
621 x_min, x_max, y_min, y_max =
compute_room_range(tmp_room, pix_data_tmp, new_col, closer)
628 n1, n2 =
closer_nodes(subgraph, subgraphs[closer], coordinates)
641 node_err_1_closer = []
642 node_err_2_closer = []
643 for node
in subgraph:
644 side =
compute_side(points[0], points[1], [coordinates[node][1], coordinates[node][0]])
646 node_err_1.append(node)
648 node_err_2.append(node)
649 if len(node_err_1) != 0
and len(node_err_2) != 0:
653 if len(node_err_1) != 0:
657 for node
in subgraphs[closer]:
658 side =
compute_side(points[0], points[1], [coordinates[node][1], coordinates[node][0]])
660 node_err_1_closer.append(node)
662 node_err_2_closer.append(node)
663 if len(node_err_1_closer) != 0
and len(node_err_2_closer) != 0:
665 if len(node_err_2_closer) > len(node_err_1_closer)
and side_v != -1:
666 subgraphs[closer] = node_err_2_closer
668 subgraphs[closer] = node_err_1_closer
670 if len(node_err_2) > len(node_err_1):
671 subgraph = node_err_2
673 subgraph = node_err_1
680 tmp_room.save(filepath + 't_room_pre_' + str(ind) + '.png')
682 # draw line to separate the room
683 draw = ImageDraw.Draw(tmp_room)
684 draw.line((points[0], points[1]), fill=(0, 0, 0, 255), width=1)
685 tmp_room.save(filepath + 't_room.png')
688 original_room_image = Image.open(filepath +
'8b_rooms_th1.png')
691 color1 = (randint(0, 255), randint(0, 255), randint(0, 255), 255)
692 color2 = (randint(0, 255), randint(0, 255), randint(0, 255), 255)
699 for y
in range(tmp_room.size[1]):
700 for x
in range(tmp_room.size[0]):
701 pixel = original_room_image.getpixel((x, y))
704 if side == 1
or side == 0:
705 patch_pixels.append((x, y))
706 patch_1_pixels.append((x,y))
707 original_room_image.putpixel((x, y), color1)
708 if [x, y]
in centers_node:
709 index = centers_node.index([x, y])
710 new_col[index] = color1
712 patch_pixels.append((x, y))
713 patch_2_pixels.append((x,y))
714 original_room_image.putpixel((x, y), color2)
715 if [x, y]
in centers_node:
716 index = centers_node.index([x, y])
717 new_col[index] = color2
719 if len(patch_1_pixels) != 0
and len(patch_2_pixels) != 0:
721 original_patch =
find_patch(patches, patch_pixels)
722 patches.remove(original_patch)
724 partial_patch_1 =
make_patch(patch_1_pixels, color1)
725 patches.append(partial_patch_1)
726 partial_patch_2 =
make_patch(patch_2_pixels, color2)
727 patches.append(partial_patch_2)
728 for i, c
in enumerate(new_col):
730 for node
in subgraphs[i]:
731 pixel = original_room_image.getpixel((coordinates[node][1], coordinates[node][0]))
739 original_room_image.save(filepath +
'8b_rooms_th1.png')
746 vertices = (p.get_path().vertices).astype(
'int')
747 t = [
True for (x, y)
in vertices
if (x,y)
in patch_pixels
or (x-1, y-1)
in patch_pixels
or (x, y+1)
in patch_pixels
or (x+1, y+1)
in patch_pixels
or
748 (x+1, y)
in patch_pixels
or (x, y-1)
in patch_pixels
or (x-1, y)
in patch_pixels]
749 if len(t) == len(vertices):
752 return max(found, key=
lambda x : len(x[1]))[0]
757 color = [x / 255
for x
in list(color)]
758 patch = PathPatch(path, fc=color, ec=
'none')
763 if (p3[1] - p1[1]) * (p2[0] - p1[0]) >= (p2[1] - p1[1]) * (p3[0] - p1[0]):
770 L_upper = [P[0], P[1]]
772 for i
in range(2, len(P)):
774 while len(L_upper) > 2
and not RightTurn(L_upper[-1], L_upper[-2], L_upper[-3]):
776 L_lower = [P[-1], P[-2]]
778 for i
in range(len(P) - 3, -1, -1):
780 while len(L_lower) > 2
and not RightTurn(L_lower[-1], L_lower[-2], L_lower[-3]):
784 L = L_upper + L_lower
787 if __name__ ==
'__main__':
788 input_path =
'./../data/INPUT/IMGs/'
789 output_path =
'./../data/OUTPUT/voronoi_graph/'
790 if not os.path.exists(output_path):
791 os.mkdir(output_path)
792 for folder
in os.listdir(input_path):
793 if folder ==
'bormann no gt':
796 output = os.path.join(output_path, folder) +
'/'
797 input = os.path.join(input_path, folder)
798 if not os.path.exists(output):
800 if folder ==
'Bormann' or folder ==
'Bormann_furnitures':
804 for map
in os.listdir(input):
805 if map !=
'percentage_exploration.txt':
806 rospy.loginfo(output + map)
809 image = os.path.join(input, map)
810 param_obj = ParameterObj()