voronoi.py
Go to the documentation of this file.
1 import math
2 import os
3 from random import randint
4 
5 import matplotlib.colors
6 
7 import cv2
8 import matplotlib.pyplot as plt
9 import networkx as nx
10 import skan
11 import numpy as np
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
17 
18 from rose_v2_repo.parameters import ParameterObj
19 from util.disegna import setup_plot
20 
21 from matplotlib.patches import PathPatch
22 from matplotlib.path import Path
23 from descartes import PolygonPatch
24 from shapely.geometry.polygon import Polygon
25 import rospy
26 matplotlib.use('Agg')
27 def remove_2_neighbors(graph):
28  old_edges = 0
29  new_edges = len(graph.edges)
30  precision = old_edges - new_edges
31  while precision != 0:
32  for node in graph.nodes:
33  tmp = list(graph.neighbors(node))
34  if len(tmp) == 2:
35  # new_graph = nx.contracted_nodes(new_graph, tmp[0], node, self_loops=False)
36  graph.remove_edge(node, tmp[0])
37  graph.remove_edge(node, tmp[1])
38  graph.add_edge(tmp[0], tmp[1])
39  old_edges = new_edges
40  new_edges = len(graph.edges)
41  precision = old_edges - new_edges
42  # rospy.loginfo('edge after remove 2 neighbors:', len(graph.edges))
43  graph.remove_nodes_from(list(nx.isolates(graph)))
44 
45 
46 # rospy.loginfo('nodes after removed 2 neighbors:', len(graph.nodes))
47 
48 
49 def remove_1_neighbors(graph):
50  old_edges = 0
51  new_edges = len(graph.edges)
52  precision = old_edges - new_edges
53  while precision != 0:
54  for node in graph.nodes:
55  tmp = list(graph.neighbors(node))
56  if len(tmp) == 1:
57  graph.remove_edge(node, tmp[0])
58  old_edges = new_edges
59  new_edges = len(graph.edges)
60  precision = old_edges - new_edges
61  # rospy.loginfo('edge after remove 2 neighbors:', len(graph.edges))
62  graph.remove_nodes_from(list(nx.isolates(graph)))
63 
64 
66  li = []
67  for node in graph.nodes:
68  tmp = list(graph.neighbors(node))
69  if len(tmp) == 2:
70  li.append(node)
71  for n in li:
72  tmp = list(graph.neighbors(n))
73  if len(tmp) == 2:
74  li.append(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)))
79 
80 
82  li = []
83  for node in graph.nodes:
84  tmp = list(graph.neighbors(node))
85  if len(tmp) == 1:
86  li.append(node)
87  for el in li:
88  n = list(graph.neighbors(el))
89  graph.remove_edge(el, n[0])
90  graph.remove_nodes_from(list(nx.isolates(graph)))
91 
92 
94  tb = 0
95  tc = 0
96  for node in graph.nodes:
97  tmp = list(graph.neighbors(node))
98  if len(tmp) == 2:
99  tb += 1
100  # new_graph = nx.contracted_nodes(new_graph, tmp[0], node, self_loops=False)
101  graph.remove_edge(node, tmp[0])
102  graph.remove_edge(node, tmp[1])
103  graph.add_edge(tmp[0], tmp[1])
104  elif len(tmp) == 1:
105  tc += 1
106  # new_graph = nx.contracted_edge(new_graph, (tmp[0], node), self_loops=False)
107  graph.remove_edge(node, tmp[0])
108  # rospy.loginfo('case 2:', tb)
109  # rospy.loginfo('case 1:', tc)
110  # rospy.loginfo('edge after remove 1 and 2 neighbors:', len(graph.edges))
111  graph.remove_nodes_from(list(nx.isolates(graph)))
112 
113 
114 def plot_line(node_i, node_j, ax):
115  x_coordinates = []
116  y_coordinates = []
117  x1 = int(node_i[1])
118  x2 = int(node_j[1])
119  y1 = int(node_i[0])
120  y2 = int(node_j[0])
121  x_coordinates.extend((x1, x2))
122  y_coordinates.extend((y1, y2))
123  ax.plot(x_coordinates, y_coordinates, color='k', linewidth=1)
124  del x_coordinates[:]
125  del y_coordinates[:]
126 
127 
129  li = sorted(nx.connected_components(graph), key=len, reverse=True)
130  largest_cc = li[0]
131  voronoi_graph = graph.subgraph(largest_cc).copy()
132  # rospy.loginfo('edge after subgraph:', len(voronoi_graph.edges))
133  # rospy.loginfo('nodes after subgraph:', len(voronoi_graph.nodes))
134  voronoi_graph.remove_nodes_from(list(nx.isolates(voronoi_graph)))
135  # rospy.loginfo('nodes after removed isolated:', len(voronoi_graph.nodes))
136  return voronoi_graph
137 
138 
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:
143  if is_labelled:
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))
146  else:
147  ax.scatter(coordinates[node][1], coordinates[node][0])
148  plt.savefig(filepath + name + '.png')
149 
150 
151 def evaluate_distance(node1, node2):
152  distance = math.sqrt((node1[0] - node2[0]) ** 2 + (node1[1] - node2[1]) ** 2)
153  return distance
154 
155 
156 def remove_close_nodes(graph, coordinates, th):
157  for node in graph.nodes:
158  for n in graph.nodes:
159  if n != node and evaluate_distance(coordinates[node], coordinates[n]) < th:
160  graph = nx.contracted_nodes(graph, node, n, self_loops=False)
161  # rospy.loginfo('nodes after removed closed:', len(graph.nodes))
162  return graph
163 
164 
165 def exist_path(color, paths, label):
166  same_color = False
167  for path in paths:
168  for point in path:
169  if label[point] == color:
170  same_color = True
171  else:
172  same_color = False
173  break
174  if same_color is True:
175  break
176  return same_color
177 
178 
179 def compute_lines_direction(centers, v, u, n1, n2, directions):
180  point1 = centers[v]
181  point2 = centers[u]
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]
184  lines1 = []
185  lines2 = []
186  for direction in directions:
187  m = math.tan(direction)
188  c1 = point1[1] - m * point1[0]
189  c2 = point2[1] - m * point2[0]
190  lines1.append(c1)
191  lines2.append(c2)
192  max_distance = None
193  direction = 0
194  m_pt = None
195  c_pt = None
196  for i, line in enumerate(lines1):
197  par_line = lines2[i]
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:
200  max_distance = dist
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
205 
206 
207 def compute_intersections(x_min, x_max, y_min, y_max, m, c):
208  points = []
209  x1 = x_min
210  y1 = m * x1 + c
211  point1 = (int(x1), int(y1))
212  # rospy.loginfo('point1', point1)
213  if y_min <= point1[1] <= y_max:
214  points.append(point1)
215  x2 = x_max
216  y2 = m * x2 + c
217  point2 = (int(x2), int(y2))
218  # rospy.loginfo('point2', point2)
219  if y_min <= point2[1] <= y_max:
220  points.append(point2)
221  y3 = y_min
222  x3 = (y3 - c) / m
223  point3 = (int(x3), int(y3))
224  # rospy.loginfo('point3', point3)
225  if x_min <= point3[0] <= x_max:
226  points.append(point3)
227  y4 = y_max
228  x4 = (y4 - c) / m
229  point4 = (int(x4), int(y4))
230  # rospy.loginfo('point4', point4)
231  if x_min <= point4[0] <= x_max:
232  points.append(point4)
233  return points
234 
235 
236 def compute_most_distant(list_point, center, coordinates, pix_data, color):
237  distance = 0
238  point = None
239  for p in list_point:
240  pt = [int(coordinates[p][1]), int(coordinates[p][0])]
241  dist = evaluate_distance(pt, center)
242  if dist > distance and pix_data[pt[0], pt[1]] == color:
243  point = (int(coordinates[p][1]), int(coordinates[p][0]))
244  return point
245 
246 
247 def remove_close_nodes_1_neighbors(graph, coordinates, th):
248  old_edges = 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)))
260 
261 
262 def remove_close_node_2_neighbors(graph, coordinates, th):
263  old_edges = 0
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))
269  if len(tmp) == 2 and evaluate_distance(coordinates[node], coordinates[tmp[0]]) < th and evaluate_distance(coordinates[node], coordinates[tmp[1]]) < th:
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)))
277 
278 
279 def remove_close_nodes_1_neighbors_one_cycle(graph, coordinates, th):
280  li = []
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:
284  li.append(node)
285  for el in li:
286  n = list(graph.neighbors(el))
287  if len(n) == 1:
288  graph.remove_edge(el, n[0])
289  graph.remove_nodes_from(list(nx.isolates(graph)))
290 
291 
292 def compute_voronoi_graph(origin, param_obj, only_graph, name, bormann, filepath=''):
293  # --------------------------INITIALIZATION----------------------------------
294 
295  # load map
296  copy = cv2.imread(origin)
297  im = copy.copy()
298 
299  # setup plot
300  #fig, ax = setup_plot([im.shape[1], im.shape[0]])
301  #ax.imshow(im)
302 
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'))
309  os.remove('tmp.png')
310 
311  # Invert image
312  input_skeleton = invert(initial_map)
313 
314  # ------------------------------SKELETON-----------------------------------
315 
316  skeleton = skeletonize(input_skeleton)
317  skeleton_object = skan.csr.Skeleton(skeleton)
318  pixel_graph, coordinates, degrees = skeleton_to_csgraph(skeleton)
319  # -------------------------------GRAPH-------------------------------------
320 
321  graph = nx.from_scipy_sparse_array(pixel_graph, edge_attribute='weight')
322 
323  rospy.loginfo('[rose2] edges initial: {}'.format(len(graph.edges)))
324  rospy.loginfo('[rose2] nodes initial: {}'.format(len(graph.nodes)))
325 
326  # ---------------------------PRUNING NODES----------------------------------
327 
328  # remove isolated part of graph
329  voronoi_graph = removed_isolated_cycles(graph)
330 
331  # remove_by_weight(voronoi_graph)
332 
333  if bormann:
334  remove_close_nodes_1_neighbors_one_cycle(voronoi_graph, coordinates, 40)
335  remove_close_node_2_neighbors(voronoi_graph, coordinates, 40)
336  remove_close_nodes_1_neighbors_one_cycle(voronoi_graph, coordinates, 40)
337  else:
338  remove_close_nodes_1_neighbors_one_cycle(voronoi_graph, coordinates, 40)
339  # remove_2_neighbors_one_cycle(voronoi_graph)
340  remove_close_node_2_neighbors(voronoi_graph, coordinates, 60)
341  # remove_close_nodes_1_neighbors_one_cycle(voronoi_graph, coordinates, 50)
342  remove_close_nodes_1_neighbors(voronoi_graph, coordinates, 30)
343  # remove_2_neighbors_one_cycle(voronoi_graph)
344 
345  # remove_2_neighbors(voronoi_graph)
346 
347  # remove_2_neighbors_one_cycle(voronoi_graph)
348 
349  # if len(voronoi_graph.nodes) > 500:
350  # remove_1_and_2_neighbors(voronoi_graph)
351 
352  if len(voronoi_graph.nodes) > 2:
353  voronoi_graph = remove_close_nodes(voronoi_graph, coordinates, param_obj.voronoi_closeness)
354 
355  # remove_1_neighbors(voronoi_graph)
356 
357  graph.remove_nodes_from(list(nx.isolates(graph)))
358 
359  rospy.loginfo('[rose2] edges final: {}'.format(len(voronoi_graph.edges)))
360  rospy.loginfo('[rose2] nodes final: {}'.format(len(voronoi_graph.nodes)))
361 
362  # -------------------------------PLOT-------------------------------------
363 
364  if only_graph:
365  plot_voronoi(coordinates, voronoi_graph, ax, 0, False, 'voronoi_graph_' + name, filepath=filepath)
366 
367  return voronoi_graph, coordinates
368 
369 
370 def labelling(voronoi_graph, coordinates, filepath='.'):
371  # --------------------------INITIALIZATION--------------------------------
372 
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()
376 
377  pix_data_room_divide = room_to_divide.load()
378  pix_data_room = room.load()
379  pix_data_true_room = true_rooms.load()
380 
381  label = [(0, 0, 0, 255)] * len(coordinates)
382  colors = []
383  colors_to_divide = []
384  node_to_remove = []
385 
386  # --------------------------LABELLING NODES--------------------------------
387 
388  # compute label colors and check node to remove.
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):
397  colors.append(color)
398  else:
399  node_to_remove.append(node)
400  # rospy.loginfo('voronoi node outside rooms 1')
401  elif color == (255, 255, 255, 255):
402  # rospy.loginfo('voronoi node outside rooms 2')
403  node_to_remove.append(node)
404  else:
405  label[node] = color
406  if color not in colors and color != (0, 0, 0, 255):
407  colors.append(color)
408 
409  # remove nodes outside room segmentation
410  for i, node in enumerate(node_to_remove):
411  li = list(voronoi_graph.neighbors(node))
412  ne = li[0]
413  for n in li:
414  if label[n] != (0, 0, 0, 255):
415  ne = n
416  break
417  voronoi_graph = nx.contracted_nodes(voronoi_graph, ne, node, self_loops=False)
418 
419  # --------------------------ROOMS TO BE DIVIDED--------------------------------
420 
421  # TODO compute subgraph instead of checking each node
422  # compute rooms to be divided based on connectivity
423  for color in colors:
424  list_node = []
425  for i, c in enumerate(label):
426  if c == color and c != (0, 0, 0, 255):
427  list_node.append(i)
428  # for node in list_node:
429  # for edge in voronoi_graph.edges(node):
430  # if edge[1] in list_node:
431  # g.add_edge(node, edge[1])
432  subg = voronoi_graph.subgraph(list_node)
433  if not nx.is_connected(subg):
434  colors_to_divide.append(color)
435  # ok = True
436  # for i, node in enumerate(list_node):
437  # for j in range(i + 1, len(list_node)):
438  # n = list_node[j]
439  # paths = []
440  # i = 0
441  # for path in nx.shortest_simple_paths(voronoi_graph, node, n):
442  # i += 1
443  # paths.append(path)
444  # if i == 10:
445  # break
446  # if not exist_path(color, paths, label):
447  # ok = False
448  # colors_to_divide.append(color)
449  # break
450  # if ok is False:
451  # break
452 
453  # -----------------------------PLOT-----------------------------------
454 
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')
460 
461  return colors_to_divide, label, voronoi_graph
462 
463 
464 def compute_centers(size0, size1, coordinates, subgraphs):
465  centers = []
466  centers_node = []
467  for subgraph in subgraphs:
468  x_min, x_max, y_min, y_max = size0, 0, size1, 0
469  for n in subgraph:
470  x = int(coordinates[n][1])
471  y = int(coordinates[n][0])
472  if x <= x_min:
473  x_min = x
474  if x >= x_max:
475  x_max = x
476  if y <= y_min:
477  y_min = y
478  if y >= y_max:
479  y_max = y
480  middle_point = [int((x_max + x_min) / 2), int((y_max + y_min) / 2)]
481  centers.append(middle_point)
482  distance = 100000
483  nd = None
484  for i in list(subgraph):
485  di = evaluate_distance(middle_point, (coordinates[i][1], coordinates[i][0]))
486  if di < distance:
487  distance = di
488  nd = [int(coordinates[i][1]), int(coordinates[i][0])]
489  centers_node.append(nd)
490 
491  return centers, centers_node
492 
493 
494 def compute_closer_subgraphs(subgraphs, centers):
495  list_closer = []
496  for v, subgraph in enumerate(subgraphs):
497  distance = 10000
498  index = v
499  for u, g in enumerate(subgraphs):
500  dist = evaluate_distance(centers[v], centers[u])
501  if dist < distance and u != v:
502  index = u
503  distance = dist
504  list_closer.append(index)
505  return list_closer
506 
507 
508 def compute_room_range(tmp_room, pix_data_tmp, new_col, closer):
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):
513  if x <= x_min:
514  x_min = x
515  if x >= x_max:
516  x_max = x
517  if y <= y_min:
518  y_min = y
519  if y >= y_max:
520  y_max = y
521  else:
522  pix_data_tmp[x, y] = (255, 255, 255, 255)
523  return x_min, x_max, y_min, y_max
524 
525 
526 def closer_nodes(subgraph1, subgraph2, coordinates):
527  distance = 100000
528  n1 = None
529  n2 = None
530  for node in subgraph1:
531  node1 = [coordinates[node][1], coordinates[node][0]]
532  for n in subgraph2:
533  node2 = [coordinates[n][1], coordinates[n][0]]
534  dist = evaluate_distance(node1, node2)
535  if dist < distance:
536  distance = dist
537  n1 = node1
538  n2 = node2
539  return n1, n2
540 
541 
542 def compute_side(a, b, point):
543  side = (point[0] - a[0]) * (b[1] - a[1]) - (point[1] - a[1]) * (b[0] - a[0])
544  if side > 0:
545  return 1
546  elif side < 0:
547  return -1
548  else:
549  return 0
550 
551 
552 def voronoi_segmentation(patches, colors, size, voronoi_graph, coordinates, directions_orebro, im, ind, filepath='.'):
553  # --------------------------INITIALIZATION--------------------------------
554  true_rooms = Image.open(filepath + '8b_rooms_th1.png')
555  colors_to_divide, label, voronoi_graph = labelling(voronoi_graph, coordinates, filepath=filepath)
556 
557  voronoi_graph = voronoi_graph.copy()
558  copy = cv2.imread(im)
559  im = copy.copy()
560  fig, ax = setup_plot([im.shape[1], im.shape[0]])
561  ax.imshow(im)
562  plot_voronoi(coordinates, voronoi_graph, ax, label, True, 'voronoi_graph' + str(ind), filepath=filepath)
563 
564  # -----------------------------SEGMENTATION------------------------------------
565 
566  for color in colors_to_divide:
567  # compute new subgraph based on color of labelling
568  new_nodes = []
569  for i, label_color in enumerate(label):
570  if label_color == color:
571  new_nodes.append(i)
572  g = nx.Graph()
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))
578  tot = 0
579  already_present = []
580 
581  # exception for subgraph of one single node
582  for li_comp in subgraphs:
583  tot += len(li_comp)
584  for ap in li_comp:
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])
590 
591  new_col = [color] * len(subgraphs)
592  analyzed = []
593 
594  # compute center points of subgraphs and closer node to center
595  centers, centers_node = compute_centers(true_rooms.size[0], true_rooms.size[1], coordinates, subgraphs)
596 
597  # compute closer subgraphs list
598  list_closer = compute_closer_subgraphs(subgraphs, centers)
599 
600  ind = 0
601  for v, subgraph in enumerate(subgraphs):
602  ind += 1
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):
607 
608  # add these 2 subgraphs in analyzed
609  analyzed.append(closer)
610  analyzed.append(v)
611 
612  # compute seeds, used in flood filling
613  seed1 = compute_most_distant(list(subgraph), centers[closer], coordinates, pix_data_tmp, new_col[v])
614  # rospy.loginfo('seed1:', seed1)
615  seed2 = compute_most_distant(list(subgraphs[closer]), centers[v], coordinates, pix_data_tmp, new_col[v])
616  # rospy.loginfo('seed2:', seed2)
617 
618  if not (seed1 is None or seed2 is None):
619 
620  # compute room color range
621  x_min, x_max, y_min, y_max = compute_room_range(tmp_room, pix_data_tmp, new_col, closer)
622 
623  err = True
624  points = []
625  while err:
626  err = False
627 
628  n1, n2 = closer_nodes(subgraph, subgraphs[closer], coordinates)
629 
630  # compute direction where to cut the area based on orebro's directions
631  direction, m, c = compute_lines_direction(centers, v, closer, n1, n2, directions_orebro)
632 
633  # compute maximum intersection between range of room and line
634  points = compute_intersections(x_min, x_max, y_min, y_max, m, c)
635 
636  if len(points) == 0:
637  break
638 
639  node_err_1 = []
640  node_err_2 = []
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]])
645  if side == 1:
646  node_err_1.append(node)
647  else:
648  node_err_2.append(node)
649  if len(node_err_1) != 0 and len(node_err_2) != 0:
650  err = True
651 
652  if not err:
653  if len(node_err_1) != 0:
654  side_v = 1
655  else:
656  side_v = -1
657  for node in subgraphs[closer]:
658  side = compute_side(points[0], points[1], [coordinates[node][1], coordinates[node][0]])
659  if side == 1:
660  node_err_1_closer.append(node)
661  else:
662  node_err_2_closer.append(node)
663  if len(node_err_1_closer) != 0 and len(node_err_2_closer) != 0:
664  err = True
665  if len(node_err_2_closer) > len(node_err_1_closer) and side_v != -1:
666  subgraphs[closer] = node_err_2_closer
667  else:
668  subgraphs[closer] = node_err_1_closer
669  if err:
670  if len(node_err_2) > len(node_err_1):
671  subgraph = node_err_2
672  else:
673  subgraph = node_err_1
674 
675  if len(points) == 0:
676  break
677 
678  # draw room before cut it
679  """
680  tmp_room.save(filepath + 't_room_pre_' + str(ind) + '.png')
681 
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')
686  """
687  # load image
688  original_room_image = Image.open(filepath + '8b_rooms_th1.png')
689 
690  # setup 2 new color
691  color1 = (randint(0, 255), randint(0, 255), randint(0, 255), 255)
692  color2 = (randint(0, 255), randint(0, 255), randint(0, 255), 255)
693 
694 
695  patch_pixels = [] # [(x1,y1), ..., (xn, yn)]
696  patch_1_pixels = []
697  patch_2_pixels = []
698  # color the image in normal case
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))
702  side = compute_side(points[0], points[1], (x, y))
703  if pixel == color:
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
711  if side == -1:
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
718  # the main room (patch_pixels) has to be divided in two rooms
719  if len(patch_1_pixels) != 0 and len(patch_2_pixels) != 0:
720  # find main_room patch and remove it from the patches
721  original_patch = find_patch(patches, patch_pixels)
722  patches.remove(original_patch)
723  # make patches of the two rooms and add it to patches
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):
729  if c == color:
730  for node in subgraphs[i]:
731  pixel = original_room_image.getpixel((coordinates[node][1], coordinates[node][0]))
732  if pixel == color1:
733  new_col[i] = color1
734  break
735  if pixel == color2:
736  new_col[i] = color2
737  break
738  # save final maps
739  original_room_image.save(filepath + '8b_rooms_th1.png')
740  #original_room_image.save(filepath + '8b_rooms_th1' + str(ind) + '.png')
741 
742 
743 def find_patch(patches, patch_pixels):
744  found = []
745  for p in patches:
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):
750  return p
751  found.append((p, t))
752  return max(found, key=lambda x : len(x[1]))[0]
753 
754 def make_patch(patch_pixels, color):
755  hull = GrahamScan(patch_pixels)
756  path = Path(hull)
757  color = [x / 255 for x in list(color)]
758  patch = PathPatch(path, fc=color, ec='none')
759  return patch
760 
761 # Function to know if we have a CCW turn
762 def RightTurn(p1, p2, p3):
763  if (p3[1] - p1[1]) * (p2[0] - p1[0]) >= (p2[1] - p1[1]) * (p3[0] - p1[0]):
764  return False
765  return True
766 
767 # find convex hull of a path
768 def GrahamScan(P):
769  P.sort() # Sort the set of points
770  L_upper = [P[0], P[1]] # Initialize upper part
771  # Compute the upper part of the hull
772  for i in range(2, len(P)):
773  L_upper.append(P[i])
774  while len(L_upper) > 2 and not RightTurn(L_upper[-1], L_upper[-2], L_upper[-3]):
775  del L_upper[-2]
776  L_lower = [P[-1], P[-2]] # Initialize the lower part
777  # Compute the lower part of the hull
778  for i in range(len(P) - 3, -1, -1):
779  L_lower.append(P[i])
780  while len(L_lower) > 2 and not RightTurn(L_lower[-1], L_lower[-2], L_lower[-3]):
781  del L_lower[-2]
782  del L_lower[0]
783  del L_lower[-1]
784  L = L_upper + L_lower # Build the full hull
785  return np.array(L)
786 
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':
794  pass
795  else:
796  output = os.path.join(output_path, folder) + '/'
797  input = os.path.join(input_path, folder)
798  if not os.path.exists(output):
799  os.mkdir(output)
800  if folder == 'Bormann' or folder == 'Bormann_furnitures':
801  bormann = True
802  else:
803  bormann = False
804  for map in os.listdir(input):
805  if map != 'percentage_exploration.txt':
806  rospy.loginfo(output + map)
807  tmp = map.split('.')
808  name = tmp[0]
809  image = os.path.join(input, map)
810  param_obj = ParameterObj()
811  compute_voronoi_graph(image, param_obj, True, name, bormann, filepath=output)
voronoi.find_patch
def find_patch(patches, patch_pixels)
Definition: voronoi.py:743
voronoi.voronoi_segmentation
def voronoi_segmentation(patches, colors, size, voronoi_graph, coordinates, directions_orebro, im, ind, filepath='.')
Definition: voronoi.py:552
voronoi.remove_close_nodes
def remove_close_nodes(graph, coordinates, th)
Definition: voronoi.py:156
voronoi.exist_path
def exist_path(color, paths, label)
Definition: voronoi.py:165
voronoi.remove_2_neighbors
def remove_2_neighbors(graph)
Definition: voronoi.py:27
voronoi.remove_close_node_2_neighbors
def remove_close_node_2_neighbors(graph, coordinates, th)
Definition: voronoi.py:262
voronoi.labelling
def labelling(voronoi_graph, coordinates, filepath='.')
Definition: voronoi.py:370
voronoi.remove_1_and_2_neighbors
def remove_1_and_2_neighbors(graph)
Definition: voronoi.py:93
voronoi.remove_close_nodes_1_neighbors
def remove_close_nodes_1_neighbors(graph, coordinates, th)
Definition: voronoi.py:247
voronoi.compute_room_range
def compute_room_range(tmp_room, pix_data_tmp, new_col, closer)
Definition: voronoi.py:508
voronoi.remove_1_neighbors
def remove_1_neighbors(graph)
Definition: voronoi.py:49
voronoi.GrahamScan
def GrahamScan(P)
Definition: voronoi.py:768
voronoi.evaluate_distance
def evaluate_distance(node1, node2)
Definition: voronoi.py:151
voronoi.compute_intersections
def compute_intersections(x_min, x_max, y_min, y_max, m, c)
Definition: voronoi.py:207
voronoi.remove_2_neighbors_one_cycle
def remove_2_neighbors_one_cycle(graph)
Definition: voronoi.py:65
voronoi.remove_close_nodes_1_neighbors_one_cycle
def remove_close_nodes_1_neighbors_one_cycle(graph, coordinates, th)
Definition: voronoi.py:279
voronoi.make_patch
def make_patch(patch_pixels, color)
Definition: voronoi.py:754
voronoi.compute_closer_subgraphs
def compute_closer_subgraphs(subgraphs, centers)
Definition: voronoi.py:494
voronoi.compute_side
def compute_side(a, b, point)
Definition: voronoi.py:542
voronoi.compute_lines_direction
def compute_lines_direction(centers, v, u, n1, n2, directions)
Definition: voronoi.py:179
voronoi.plot_line
def plot_line(node_i, node_j, ax)
Definition: voronoi.py:114
disegna.setup_plot
def setup_plot(size)
Definition: disegna.py:20
voronoi.compute_centers
def compute_centers(size0, size1, coordinates, subgraphs)
Definition: voronoi.py:464
voronoi.closer_nodes
def closer_nodes(subgraph1, subgraph2, coordinates)
Definition: voronoi.py:526
voronoi.remove_1_neighbors_one_cycle
def remove_1_neighbors_one_cycle(graph)
Definition: voronoi.py:81
voronoi.compute_voronoi_graph
def compute_voronoi_graph(origin, param_obj, only_graph, name, bormann, filepath='')
Definition: voronoi.py:292
voronoi.compute_most_distant
def compute_most_distant(list_point, center, coordinates, pix_data, color)
Definition: voronoi.py:236
voronoi.plot_voronoi
def plot_voronoi(coordinates, voronoi_graph, ax, label, is_labelled, name, filepath)
Definition: voronoi.py:139
voronoi.RightTurn
def RightTurn(p1, p2, p3)
Definition: voronoi.py:762
voronoi.removed_isolated_cycles
def removed_isolated_cycles(graph)
Definition: voronoi.py:128


rose2
Author(s): Gabriele Somaschini, Matteo Luperto
autogenerated on Wed Jun 28 2023 02:21:53