2 funzioni utili alla costruzione del layout delle stanze partendo da un immagine nota della mappa, dalla quale non si conosce nulla.
8 from shapely.geometry
import Polygon
9 from shapely.ops
import cascaded_union
10 from sklearn.cluster
import DBSCAN
12 import util.matrice
as mtx
13 from object
import ExtendedSegment
as ext
14 from object
import Line
as rt
15 from object
import Segment
as sg
16 from object
import Space
as sp
17 from object
import Surface
as fc
18 from util
import mean_shift
as ms
19 from util
import rototranslation
as rotot
21 from skimage
import io
23 from matplotlib
import pyplot
as plt
27 image_3 = cv2.bitwise_not(image.copy())
36 walls = cv2.HoughLinesP(image_3, param_obj.rho, param_obj.theta, param_obj.thresholdHough, param_obj.minLineLength, param_obj.maxLineGap)
38 if cv2.__version__[0] ==
'3' or cv2.__version__[0]==
'4':
39 walls = [i[0]
for i
in walls]
40 elif cv2.__version__[0] ==
'2':
43 raise EnvironmentError(
'Opencv Version Error. You should have OpenCv 2.* or 3.* or 4.*')
50 line[1] = height - line[1]
51 line[3] = height - line[3]
63 walls.append(sg.Segment(x1, y1, x2, y2))
68 if len(img_rgb.shape) == 3:
70 img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
72 img_gray = img_rgb.copy()
74 ret, thresh = cv2.threshold(img_gray.copy(), 253, 255, cv2.THRESH_BINARY_INV)
75 if cv2.__version__[0] ==
'3':
77 img_contour, contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
79 contours = list(contours)
82 img_contour = cv2.drawContours(img_contour.copy(), contours, -1, (0, 255, 0), 3, cv2.LINE_8)
84 img_contour, contours, hierarchy = cv2.findContours(img_contour, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
86 elif cv2.__version__[0] ==
'4':
88 contours, hierarchy = cv2.findContours(thresh.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
90 contours = list(contours)
93 img_contour = cv2.drawContours(thresh.copy(), contours, -1, (0, 255, 0), 3, cv2.LINE_8)
95 contours, hierarchy = cv2.findContours(img_contour, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
97 raise EnvironmentError(
'Opencv Version Error. You should have OpenCv 3.* or Opencv 4.*')
99 contours = sorted(contours, key=cv2.contourArea, reverse=
True)[:10]
100 contours_max = contours[1]
101 perimeter = cv2.arcLength(contours_max,
True)
102 approx = cv2.approxPolyDP(contours_max, 0.0002 * perimeter,
True)
111 vertices.append([float(c[0][0]), float(c[0][1])])
113 return screen_cnt, vertices
116 def cluster_ang(h, min_offset, walls, num_min=3, min_lenght=3, diagonals=True):
119 cluster_centers = ms.mean_shift(h, min_offset, walls)
123 indexes = ms.indexes_to_be_deleted(num_min, min_lenght, cluster_centers, walls, diagonals)
126 for i
in sorted(indexes, reverse=
True):
128 del cluster_centers[i]
130 united = ms.merge_similar_cluster(cluster_centers)
132 united = ms.merge_similar_cluster(cluster_centers)
134 walls = sg.assign_angular_cluster(walls, cluster_centers)
136 angular_clusters = []
138 angular_clusters.append(wall.angular_cluster)
139 return indexes, walls, angular_clusters
142 def extend_line(spatial_clusters, walls, x_min, x_max, y_min, y_max):
144 extended_lines = rt.create_extended_lines(spatial_clusters, walls, x_min, y_min)
147 extended_segments = ext.create_extended_segments(x_min, x_max, y_min, y_max, extended_lines)
148 return extended_lines, extended_segments
153 contour = Polygon(vertices)
156 contour = contour.buffer(0)
162 for index, f
in enumerate(cells):
165 points.append([float(b.x1), float(b.y1)])
166 points.append([float(b.x2), float(b.y2)])
170 x = [p[0]
for p
in points]
171 y = [p[1]
for p
in points]
173 centroid = (sum(x) / len(points), sum(y) / len(points))
174 points.sort(key=algo)
176 cell = Polygon(points)
178 if not cell.intersects(contour):
183 if cell.intersects(contour):
185 if cell.intersection(contour).area >= cell.area/threshold:
194 cells_out = list(set(cells_out)-set(cells_partial))
196 cells = list(set(cells) - set(cells_out))
197 cells = list(set(cells) - set(cells_partial))
198 return cells, cells_out, polygon_cells, indexes, cells_partial, contour, centroid, points
203 riordina i punti in senso orario
205 return (math.atan2(p[0] - centroid[0], p[1] - centroid[1]) + 2 * math.pi) % (2*math.pi)
210 return list(
uniq(sorted(l, reverse=
True)))
229 points.append([float(b.x1), float(b.y1)])
230 points.append([float(b.x2), float(b.y2)])
232 x = [p[0]
for p
in points]
233 y = [p[1]
for p
in points]
235 centroid = (sum(x) / len(points), sum(y) / len(points))
236 points.sort(key=algo)
237 cell = Polygon(points)
238 cells_polygon.append(cell)
245 points.append([float(b.x1), float(b.y1)])
246 points.append([float(b.x2), float(b.y2)])
248 x = [p[0]
for p
in points]
249 y = [p[1]
for p
in points]
250 centroid = (sum(x) / len(points), sum(y) / len(points))
251 points.sort(key=algo)
252 cell = Polygon(points)
253 polygon_out.append(cell)
257 for f
in cells_partial:
260 points.append([float(b.x1),float(b.y1)])
261 points.append([float(b.x2),float(b.y2)])
263 x = [p[0]
for p
in points]
264 y = [p[1]
for p
in points]
265 centroid = (sum(x) / len(points), sum(y) / len(points))
266 points.sort(key=algo)
267 cell = Polygon(points)
268 polygon_partial.append(cell)
270 return cells_polygon, polygon_out, polygon_partial, centroid
275 matrix_l = mtx.create_matrix_l(cells, sigma, val)
276 matrix_d = mtx.create_matrix_d(matrix_l)
277 matrix_d_inv = matrix_d.getI()
278 matrix_m = matrix_d_inv.dot(matrix_l)
279 matrix_m = mtx.symmetry(matrix_m)
281 return matrix_l, matrix_d, matrix_d_inv, X
284 def DB_scan(eps, min_points, X, celle_poligoni):
294 af = DBSCAN(eps, min_samples, metric=
"precomputed").fit(X)
299 rooms, spaces =
merge_cells(clusters_cells, cells, polygon_cells)
310 for l
in set(clusters):
313 for index, cluster
in enumerate(clusters):
314 if (l == cluster)
and not cells[index].out:
315 polygons.append(polygon_cells[index])
316 matching_cells.append(cells[index])
317 room = cascaded_union(polygons)
319 space = sp.Space(polygons, room, matching_cells, index)
326 calcola la matrice delle distanze tra tutti i segmenti
332 for segmento1
in walls:
334 for segmento2
in walls:
335 min = sg.segments_distance(segmento1.x1, segmento1.y1, segmento1.x2, segmento1.y2, segmento2.x1, segmento2.y1, segmento2.x2, segmento2.y2)
352 af = DBSCAN(eps=7, min_samples=1, metric=
"precomputed").fit(matrix)
360 ang = set(angular_clusters)
367 if wall.angular_cluster == c:
369 angular_ordered.append(row)
374 for ang
in angular_ordered:
384 walls = sg.set_segment_label2(angular_ordered, label)
388 for segment
in walls:
389 wall_cluster.append(segment.wall_cluster)
396 for cluster
in set(wall_cluster):
401 if wall.wall_cluster == cluster:
406 x = (candidate.x1+candidate.x2)/2
407 y = (candidate.y1+candidate.y2)/2
408 angle = candidate.angular_cluster * (180/math.pi)
414 (x_projected, y_projected) = sg.get_projected_points(candidate, i)
415 X.append(x_projected)
416 Y.append(y_projected)
418 my_function = rotot.transform_points(x, y, angle)
419 for px, py
in zip(X, Y):
421 distance_vector.append(my_function(px,py)[0])
424 index_representative = numpy.argsort(distance_vector)[len(distance_vector)//2-1]
426 representatives.append(lista[index_representative])
427 return representatives
435 spatial_clusters = []
437 if wall.spatial_cluster
is not None:
438 spatial_clusters.append(wall.spatial_cluster)
440 for cluster
in list(set(spatial_clusters)):
442 same_wall_cluster = []
443 for segment
in representatives_segments:
444 if segment.spatial_cluster == cluster:
445 same_wall_cluster.append(segment.wall_cluster)
447 same_wall_cluster = list(set(same_wall_cluster))
449 for segment
in walls:
450 if segment.wall_cluster
in same_wall_cluster:
451 segment.set_spatial_cluster(cluster)
459 if wall.wall_cluster == -1:
460 outliers.append(wall)
465 spatial_cluster.append(wall.spatial_cluster)
467 return spatial_cluster
474 for outlier
in outliers:
475 min_distance_to_cluster = 999999
476 representative = representatives_segments[0]
477 for segment
in representatives_segments:
478 dist = sg.lateral_separation(outlier, segment)
479 if outlier.angular_cluster == segment.angular_cluster:
480 if dist <= min_distance_to_cluster:
481 min_distance_to_cluster = dist
482 representative = segment
484 if min_distance_to_cluster <= lateral_threshold:
485 outlier.spatial_cluster = representative.spatial_cluster
486 outlier.wall_cluster = representative.wall_cluster
489 new_cluster = walls.index(outlier)
490 outlier.spatial_cluster = new_cluster
492 representatives_segments.append(outlier)
502 if fc.adjacent(c, co):
503 if fc.common_edge(c, co)[0].weight < 0.05:
507 partial_cells.append(c)
509 for border
in c.borders:
510 x_list = [border_coordinates[0], border_coordinates[2]]
511 y_list = [border_coordinates[1], border_coordinates[3]]
512 if (border.x1
or border.x2)
in x_list
or (border.y1
or border.y2)
in y_list:
516 partial_cells.append(c)
518 partial_polygons = []
519 for f
in partial_cells:
522 points.append([float(b.x1), float(b.y1)])
523 points.append([float(b.x2), float(b.y2)])
525 x = [p[0]
for p
in points]
526 y = [p[1]
for p
in points]
528 centroid = (sum(x) / len(points), sum(y) / len(points))
529 points.sort(key=algo)
530 cell = Polygon(points)
531 partial_polygons.append(cell)
532 return partial_cells, partial_polygons
541 points.append([float(b.x1), float(b.y1)])
542 points.append([float(b.x2), float(b.y2)])
544 x = [p[0]
for p
in points]
545 y = [p[1]
for p
in points]
547 centroid = (sum(x) / len(points), sum(y) / len(points))
548 points.sort(key=algo)
549 cell = Polygon(points)
550 polygons_out.append(cell)
556 for segment
in extended_segments:
557 if (segment.x1 == x_max
and segment.x2 == x_max)
or (segment.x1 == x_min
and segment.x2 == x_min)
or (segment.y1 == y_max
and segment.y2 == y_max)
or (segment.y1 == y_min
and segment.y2 == y_min):
559 border_lines.append((segment.angular_cluster, segment.spatial_cluster))
564 angular_clusters = []
569 for i, direction
in enumerate(comp):
571 minimum = abs(direction - wall.direction)
573 if minimum < absolute_min:
574 absolute_min = minimum
577 wall.set_angular_cluster(comp[index])
579 wall.set_angular_cluster(comp[index - 1])
581 angular_clusters.append(wall.angular_cluster)
582 return angular_clusters