def estrai_celle_supportate_da_extended_segmement(celle_confinanti, stanza, extended_segments): ''' delle celle che fanno parte della lista delle celle_confinanti, estraggo solo quelle che hanno tutti i lati che non toccano l'interno supportati da un extended segment(cioe' che l'extended segment deve toccare almeno una stanza) ''' #per tutte le celle out che confinano con il bordo candidate = [] for cella_conf in celle_confinanti: #estraggo le extended segment della cella_confinante extended_cella_out = ext.estrai_extended_segment_da_cella( cella_conf.c, extended_segments) for celle_st in stanza.cells: if fc.adiacenti(celle_st.c, cella_conf.c): if ( fc.edge_comune(celle_st.c, cella_conf.c)[0].weight < 0.2 ): #il bordo in comune non deve essere supportato da segmenti edge_comuni = fc.edge_comune( celle_st.c, cella_conf.c ) #ottengo la lista degli edge comuni alle 2 celle #seleziono le extended segment corrispondenti comuni = [] for bordo in edge_comuni: comuni.append( ext.estrai_extended_segment_da_bordo_cella( bordo, extended_segments)) extended_cella_out = list( set(extended_cella_out) - set(comuni) ) #tolgo dalle extended della cella out quelle che ha in comune con la cella interna #ora controllo che tutte le extend_segment trovate abbiano un supporto significativo tutte_ok = True for e in extended_cella_out: if e.peso < 0.05: #se non e' coperto da un po' di segmentini allora l'intera cella non va bene. tutte_ok = False if tutte_ok == True: #cella_conf.set_celletta_parziale(True) #questo sicuramente no perche' questa cella non e' parziale #cella_conf.set_celletta_out(False) candidate.append(cella_conf) return candidate
def estrai_solo_extended_visti(spazio_parz, extended_segments, cellette_out): ''' permette di estrarre tutti gli extended segments di una stanza parziale che sono stati sicuramente visti in precedenza. un extended segment risulta sicuramente visto se all'interno della stanza parziale esiste almeno una cella completa che condivide pareti con l'esterno. non necessariamente l'esterno si puo' ad esempio controllare anche confrondando la cella con celle di altre stanze. ''' celle = spazio_parz.cells cellette = [] # ci sono solo le celle della stanza parziale complete for ce in celle: if ce.parziale == False: cellette.append(ce) extended = [] edge_comuni = [] for celletta in cellette: for celletta_out in cellette_out: if fc.adiacenti(celletta.c, celletta_out.c): comuni = fc.edge_comune(celletta.c, celletta_out.c) for e in comuni: edge_comuni.append(e) edge_comuni = list(set(edge_comuni)) for edge in edge_comuni: extended.append( ext.estrai_extended_segment_da_bordo_cella(edge, extended_segments)) return list(set(extended))
def estrai_extended_da_spazio(spazio, extended_segments, cellette_out): ''' permette di estrarre le extended segment esterni di uno spazio ''' #se c'e' una cella che condivide un edge con l'esterno allora l'extended di qull'edge e' esterno extended = [] edge_comuni = [] for celletta in spazio.cells: for celletta_out in cellette_out: if fc.adiacenti(celletta.c, celletta_out.c): comuni = fc.edge_comune(celletta.c, celletta_out.c) for e in comuni: edge_comuni.append(e) #controllo che non tocchi il bordo, se si aggiungo anche quelle celle bordi_cella = celletta.c.bordi for e in bordi_cella: if e.cluster_spaziale == "bordo1" or e.cluster_spaziale == "bordo2" or e.cluster_spaziale == "bordo3" or e.cluster_spaziale == "bordo4": edge_comuni.append(e) edge_comuni = list(set(edge_comuni)) for edge in edge_comuni: extended.append( ext.estrai_extended_segment_da_bordo_cella(edge, extended_segments)) return list(set(extended))
def extend_line(cluster_spaziali, walls, xmin, xmax, ymin, ymax,filepath='.'): ''' crea le extended line ''' extended_lines = rt.crea_extended_lines(cluster_spaziali, walls, xmin, ymin) #da qui serve per disegnarle #extended_lines (credo parli delle rette) hanno un punto, un cluster_angolare ed un cluster_spaziale, per disegnarle pero' mi servono 2 punti. Creo lista di segmenti extended_segments = ext.crea_extended_segments(xmin,xmax,ymin,ymax, extended_lines) #----quinto plot --> disegno la mappa come era in partenza(con le linee) e ci aggiungo le rette. #disegno le extended_lines in rosso e la mappa in nero #dsg.disegna_extended_segments(extended_segments, walls,filepath = filepath) return (extended_lines, extended_segments)
def get_layout_parziale(metricMap, minVal, maxVal, rho, theta, thresholdHough, minLineLength, maxLineGap, eps, minPts, h, minOffset, minLateralSeparation, diagonali=True): ''' prende in input la mappa metrica, i parametri di canny, hough, mean-shift, dbscan, distanza per clustering spaziale. Genera il layout delle stanze e ritorna la lista di poligoni shapely che costituiscono le stanze, la lista di cluster corrispondenti, la lista estremi che contiene [minx,maxx,miny,maxy] e la lista di colori. ''' img_rgb = cv2.imread(metricMap) ret,thresh1 = cv2.threshold(img_rgb,127,255,cv2.THRESH_BINARY) #------------------CANNY E HOUGH PER TROVARE MURI---------------------------------- #canny cannyEdges = cv2.Canny(thresh1,minVal,maxVal,apertureSize = 5) #hough walls = cv2.HoughLinesP(cannyEdges,rho,theta,thresholdHough,minLineLength,maxLineGap) if cv2.__version__[0] == '3' : walls = [i[0]for i in walls] elif cv2.__version__[0] == '2' : walls = walls[0] else : raise EnvironmentError('Opencv Version Error. You should have OpenCv 2.* or 3.*') dsg.disegna_hough(img_rgb,walls) lines = flip_lines(walls, img_rgb.shape[0]-1) walls = crea_muri(lines) #disegno i muri sg.disegna_segmenti(walls) #------------SETTO XMIN YMIN XMAX YMAX DI walls-------------------------------------------- #tra tutti i punti dei muri trova l'ascissa e l'ordinata minima e massima. estremi = sg.trova_estremi(walls) xmin = estremi[0] xmax = estremi[1] ymin = estremi[2] ymax = estremi[3] offset = 20 xmin -= offset xmax += offset ymin -= offset ymax += offset #---------------CONTORNO ESTERNO------------------------------------------------------- #creo il contorno esterno facendo prima canny sulla mappa metrica. cannyEdges = cv2.Canny(img_rgb,minVal,maxVal,apertureSize = 5) t=1 #threshold di hough m=21 #maxLineGap di hough hough_contorni, contours = im.trova_contorno(t,m,cannyEdges, metricMap) #dsg.disegna_hough(cannyEdges, hough_contorni) contours = flip_contorni(contours, img_rgb.shape[0]-1) #disegno contorno esterno vertici = [] for c1 in contours: for c2 in c1: vertici.append([float(c2[0][0]),float(c2[0][1])]) dsg.disegna_contorno(vertici,xmin,ymin,xmax,ymax) #-------------------MEAN SHIFT PER TROVARE CLUSTER ANGOLARI--------------------------------------- #creo i cluster centers tramite mean shift cluster_centers = ms.mean_shift(h, minOffset, walls) #ci sono dei cluster angolari che sono causati da pochi e piccoli line_segments, che sono solamente rumore. Questi cluster li elimino dalla lista cluster_centers ed elimino anche i rispettivi segmenti dalla walls. num_min = 3 lunghezza_min = 3 indici = ms.indici_da_eliminare(num_min, lunghezza_min, cluster_centers, walls, diagonali) #ora che ho gli indici di clusters angolari e di muri da eliminare, elimino da walls e cluster_centers, partendo dagli indici piu alti for i in sorted(indici, reverse=True): del walls[i] del cluster_centers[i] #ci son dei cluster che si somigliano ma non combaciano per una differenza infinitesima, e non ho trovato parametri del mean shift che rendano il clustering piu' accurato di cosi', quindi faccio una media normalissima, tanto la differenza e' insignificante. unito = ms.unisci_cluster_simili(cluster_centers) while(unito): unito = ms.unisci_cluster_simili(cluster_centers) #assegno i cluster ai muri di walls walls = sg.assegna_cluster_angolare(walls, cluster_centers) #creo lista di cluster_angolari cluster_angolari = [] for muro in walls: cluster_angolari.append(muro.cluster_angolare) #---------------CLUSTER SPAZIALI-------------------------------------------------------------------- #setto i cluster spaziali a tutti i muri di walls walls = sg.spatialClustering(minLateralSeparation, walls) #disegno i cluster angolari #sg.disegna_cluster_angolari(cluster_centers, walls, cluster_angolari) #creo lista di cluster spaziali cluster_spaziali = [] for muro in walls: cluster_spaziali.append(muro.cluster_spaziale) #disegno cluster spaziali sg.disegna_cluster_spaziali(cluster_spaziali, walls) #-------------------CREO EXTENDED_LINES--------------------------------------------------------- extended_lines = rt.crea_extended_lines(cluster_spaziali, walls, xmin, ymin) #extended_lines hanno punto, cluster_angolare e cluster_spaziale, per disegnarle pero' mi servono 2 punti. Creo lista di segmenti extended_segments = ext.crea_extended_segments(xmin,xmax,ymin,ymax, extended_lines) #disegno le extended_lines in rosso e la mappa in nero ext.disegna_extended_segments(extended_segments, walls) #-------------CREO GLI EDGES TRAMITE INTERSEZIONI TRA EXTENDED_LINES------------------------------- edges = sg.crea_edges(extended_segments) #sg.disegna_segmenti(edges) #----------------------SETTO PESI DEGLI EDGES------------------------------------------------------ edges = sg.setPeso(edges, walls) #sg.disegna_pesanti(edges, peso_min) #----------------CREO LE CELLE DAGLI EDGES---------------------------------------------------------- print("creando le celle") celle = fc.crea_celle(edges) print("celle create") #fc.disegna_celle(celle) #----------------CLASSIFICO CELLE---------------------------------------------- #creo poligono del contorno contorno = Polygon(vertici) celle_poligoni = [] indici = [] celle_out = [] celle_parziali = [] for index,f in enumerate(celle): punti = [] for b in f.bordi: punti.append([float(b.x1),float(b.y1)]) punti.append([float(b.x2),float(b.y2)]) #ottengo i vertici della cella senza ripetizioni punti = sort_and_deduplicate(punti) #ora li ordino in senso orario x = [p[0] for p in punti] y = [p[1] for p in punti] global centroid centroid = (sum(x) / len(punti), sum(y) / len(punti)) punti.sort(key=algo) #dopo averli ordinati in senso orario, creo il poligono della cella. cella = Polygon(punti) #se il poligono della cella non interseca quello del contorno esterno della mappa, la cella e' fuori. if cella.intersects(contorno)==False: #indici.append(index) f.set_out(True) f.set_parziale(False) celle_out.append(f) #se il poligono della cella interseca il contorno esterno della mappa if (cella.intersects(contorno)): #se l'intersezione e' piu' grande di una soglia la cella e' interna if(cella.intersection(contorno).area >= cella.area/2): f.set_out(False) #altrimenti e' esterna else: f.set_out(True) f.set_parziale(False) celle_out.append(f) #le celle che non sono state messe come out, ma che sono adiacenti al bordo dell'immagine (hanno celle adiacenti < len(bordi)) sono per forza parziali a=0 for f in celle: for f2 in celle: if (f!=f2) and (fc.adiacenti(f,f2)): a += 1 if (a<len(f.bordi)): #print("ciao") if not (f.out): f.set_out(True) f.set_parziale(True) celle_parziali.append(f) a = 0 #le celle adiacenti ad una cella out tramite un edge che pesa poco, sono parziali. a = 1 while(a!=0): a = 0 for f in celle: for f2 in celle: if (f!=f2) and (f.out==False) and (f2.out==True) and (fc.adiacenti(f,f2)): if(fc.edge_comune(f,f2)[0].weight < 0.1): #qua nella funzione normale c'e' 0.2 f.set_out(True) f.set_parziale(True) celle_parziali.append(f) a = 1 #tolgo dalle celle out le parziali celle_out = list(set(celle_out)-set(celle_parziali)) #tolgo dalle celle quelle out e parziali celle = list(set(celle)-set(celle_out)) celle = list(set(celle)-set(celle_parziali)) #--------------------------POLIGONI CELLE------------------------------------------------- #adesso creo i poligoni delle celle (celle = celle interne) e delle celle esterne e parziali #poligoni celle interne celle_poligoni = [] for f in celle: punti = [] for b in f.bordi: punti.append([float(b.x1),float(b.y1)]) punti.append([float(b.x2),float(b.y2)]) punti = sort_and_deduplicate(punti) x = [p[0] for p in punti] y = [p[1] for p in punti] centroid = (sum(x) / len(punti), sum(y) / len(punti)) punti.sort(key=algo) cella = Polygon(punti) celle_poligoni.append(cella) #poligoni celle esterne out_poligoni = [] for f in celle_out: punti = [] for b in f.bordi: punti.append([float(b.x1),float(b.y1)]) punti.append([float(b.x2),float(b.y2)]) punti = sort_and_deduplicate(punti) x = [p[0] for p in punti] y = [p[1] for p in punti] centroid = (sum(x) / len(punti), sum(y) / len(punti)) punti.sort(key=algo) cella = Polygon(punti) out_poligoni.append(cella) #poligoni celle parziali parz_poligoni = [] for f in celle_parziali: punti = [] for b in f.bordi: punti.append([float(b.x1),float(b.y1)]) punti.append([float(b.x2),float(b.y2)]) punti = sort_and_deduplicate(punti) x = [p[0] for p in punti] y = [p[1] for p in punti] centroid = (sum(x) / len(punti), sum(y) / len(punti)) punti.sort(key=algo) cella = Polygon(punti) parz_poligoni.append(cella) #------------------CREO LE MATRICI L, D, D^-1, ED M = D^-1 * L--------------------------------------- sigma = 0.1 val = 0 matrice_l = mtx.crea_matrice_l(celle, sigma, val) matrice_d = mtx.crea_matrice_d(matrice_l) matrice_d_inv = matrice_d.getI() matrice_m = matrice_d_inv.dot(matrice_l) matrice_m = mtx.simmetrizza(matrice_m) X = 1-matrice_m #----------------DBSCAN PER TROVARE CELLE NELLA STESSA STANZA----------------------------------------- clustersCelle = [] clustersCelle = clustering_dbscan_celle(eps, minPts, X) colori, fig, ax = dsg.disegna_dbscan(clustersCelle, celle, celle_poligoni, xmin, ymin, xmax, ymax, edges, contours) ''' #plotto le celle esterne for f_poly in out_poligoni: f_patch = PolygonPatch(f_poly,fc='#ffffff',ec='BLACK') ax.add_patch(f_patch) ax.set_xlim(xmin,xmax) ax.set_ylim(ymin,ymax) ax.text(f_poly.representative_point().x,f_poly.representative_point().y,str("out"),fontsize=8) ''' #plotto le celle parziali for f_poly in parz_poligoni: f_patch = PolygonPatch(f_poly,fc='#d3d3d3',ec='BLACK') ax.add_patch(f_patch) ax.set_xlim(xmin,xmax) ax.set_ylim(ymin,ymax) ax.text(f_poly.representative_point().x,f_poly.representative_point().y,str("parz"),fontsize=8) plt.show() #------------------POLIGONI STANZE------------------------------------------------------------------- #creo i poligoni delle stanze (unione dei poligoni delle celle con stesso cluster). stanze = [] stanze = unisciCelle(clustersCelle, celle, celle_poligoni, False) #disegno layout stanze. fig, ax = dsg.disegna_stanze(stanze, colori, xmin, ymin, xmax, ymax) #plotto le celle parziali, questo per funzionare ha bisogno che si commenti riga 127 di disegna.py (#plt.show()). for f_poly in parz_poligoni: f_patch = PolygonPatch(f_poly,fc='#d3d3d3',ec='BLACK') ax.add_patch(f_patch) ax.set_xlim(xmin,xmax) ax.set_ylim(ymin,ymax) plt.show() return (stanze, clustersCelle, estremi, colori)