import numpy as np import matplotlib.pyplot as plt import imageio as io from time import time from random import choice from math import pi, cos, sin, floor from skimage.feature import peak_local_max from os import system import subprocess from modules import * # importation les fonctions permettant d'enregistrer des images from images import * ## Variables globales BLANC = 254 # définit le seuil pour la couleur blanche MAX_INT = 42e42 ## Liens des images sources # Fonctions ## Fonction de base sur l'image # Inverse l'image selon la coordonnée y def inv_img_y(img: list) -> list: return(img[::-1]) # lecture de l'image liée au lien [lien] depuis le serveur web def read_img(lien: str) -> np.array: im = io.v2.imread(lien) im = np.array(im) return(inv_img_y(im)) # affiche l'image [img]. # [cmap='gray'] premet d'afficher correctement les images en noir et blanc ainsi que les images en couleur # pour les images en niveaux de gris, le pixel le plus sombre sera noir et le pixel le plus clair sera blanc. # [rev] premet d'inverser l'image def show_image(img: list, rev: bool = False) -> None: plt.axis('off') # enlève les axes if rev : plt.imshow(img, cmap='gray',origin='lower', aspect='auto') else : plt.imshow(img, cmap='gray', aspect='auto') ## Traitement des images # color_to_grayscale [image] convertis l'image [image] en RGB en une image (np.array) en niveau de gris def color_to_grayscale(image: list) -> np.array: image = list(image) r = [[] for x in range(len(image))] #image vide for i in range (len(image)) : for j in range(len(image[i])) : valeur = 0.2126*image[i][j][0] + 0.7152*image[i][j][1] + 0.0722*image[i][j][2] #formule de conversion de noir et blanc a couleur r[i].append(valeur) return np.array(r) # grayscale_to_black_and_white img prend en entrée l'image [img] et renvoie un image en noir et blanc. les pixels # de couleur superieure à [seuil] vont être laissé dans leur couleur originale et ceux inferieur a seuil vont etre mis en noir # par default, la fonction conserve uniquement les pixels parfaitement blanc def grayscale_to_black_and_white(img: np.array, seuil:int = BLANC) -> np.array: r = [[] for x in range(len(img))] for i in range(len(img)): for j in range(len(img[i])): if img[i][j] < seuil : r[i].append(0) else : r[i].append(int(img[i][j])) return(np.array(r)) ## Matrice de Hough # retourne la taille du tableau qui represente l'espace de hough. # l'option precision change la taille du tableau selon la dimention x, c'est a dire selon les theta def taille_Hough(img: list, precision: int = 1) -> tuple: Px = len(img) Py = len(img[0]) hauteur = (Px ** 2 + Py ** 2)**0.5 # distance maximum (coin en bas à gauche) largeur = 360 return(round(hauteur), largeur*precision) # rho_f(x, y, θ) retourne la distance a l'origine de la droite passant par le point (x, y) et d'angle θ def rho_f(x: int, y: int, θ: float) -> float: return(x*cos(θ) + y*sin(θ)) #retourne la matrice de l'espace Hough de l'image img dans l'ordre m[r][theta] def espace_Hough(img: list, precision: int = 1) -> list: hauteur_H, largeur_H = taille_Hough(img, precision) hauteur_I, largeur_I = len(img), len(img[0]) #creer le tableau qui va contenir la matrice matrice_hough = [[0 for i in range (largeur_H)] for i in range(hauteur_H)] #on parcours toute l'image for y in range(hauteur_I): for x in range(largeur_I): if img[y][x] >= BLANC: for theta_deg in range(largeur_H): theta_rad = theta_deg /(180 * precision) * pi rho = round(rho_f(x, y, theta_rad)) if rho>0: #comme on fait varier θ jusqu'a 2π, on ne garde que les valeurs positives matrice_hough[rho][theta_deg] += 1 #on met l'origine du repere en bas de l'image return(matrice_hough) # retourne une liste de maximum locaux. def maximum_global(m: list, d: int = 100): return(peak_local_max(np.array(m), min_distance=d)) ## Géometrie # calcule l'équation d'une droite passant par deux points en coordonnées carthésiennes. # la valeur de retour sera un couple (a, b) représentant la droite sous forme y = ax + b def equation(point1: tuple, point2: tuple) -> tuple: (x1,y1),(x2,y2) = point1,point2 assert(x1 != x2), "les points sont alignés, la droite ne peut pas être prise en compte" a = (y1 - y2) / (x1 - x2) #si la droite n'est pas verticale b = y2 - a*x2 return(a,b) # retourne les coefficients de l'equation de la droite représentée par une distance a l'origine r et un angle theta # sous la forme d'un couple (a, b) représentant la droite sous forme y = ax + b def droite(r: float, theta: float, precision: int = 1) -> tuple: theta = theta / precision if theta == 0 or theta == 180: return (0,r) else : theta_rad = (pi/180)*theta a = -(cos(theta_rad)/sin(theta_rad)) b = r/sin(theta_rad) return(a,b) # Renvoie la distance euclidienne entre les points a: (x1, y1) et b : (x2, y2) def distance (a: tuple, b: tuple) -> int: (x1,y1),(x2,y2) = a,b distance = ( (x1-x2)**2 + (y1 - y2)**2 )**0.5 return(distance) # calcule la matrice de Hough a l'aide de d'un programme en C qui utilise du multithreading. # permet une vitesse d'execution beaucoup plus élevée : temps d'exécution divisé par 100 # l'argument bypass permet de tester d'autres partie du code plus rapidement def hough_c(image: list, precision: int = 10, bypass: bool = False) -> list: if not bypass: save_img_c(image) subprocess.run(['../c/multi.out', str(precision)]) mat = read_c() return(mat) # renvoit la matrice renvoyée par le calcul de l'espace de hough en C def read_c() -> list: f = open("../c/out.txt","r") m_read = f.readlines() f.close() return([[int (x) for x in y.split(",")] for y in m_read]) # enregistre la liste [image] dans le dossier C sous le nom in.txt, pour pouvoir partager des informations entre C et python def save_img_c(image: list) -> None: f = open(f"../c/in.txt","w") for i in image: f.write(str(list(i)).replace(" ","").replace("[","").replace("]","") + "\n") f.close() #donne les intervalles de déb fin d'un segment de droite def intervalle_une_droite(r: float, theta: float, plan: list, precision_h: int, blanc: int = BLANC) -> list: (a,b) = droite(r, theta, precision_h) largeur = len(plan) #axe des y longueur = len(plan[0]) #axe des x segments = [] x, deb, fin = 0, 0, 0 while x < longueur : y = round(a*x + b) if 0 < y < largeur : if plan[y][x] >= blanc : deb = x, y while (0 < y < largeur) and x < longueur and (plan[y][x] >= blanc) : x += 1 y = round(a*x +b) fin = x, y segments.append((deb, fin)) else : x += 1 else : x += 1 return(segments) # Donne les intervalles (début,fin) d'une liste de droites # in - listes_droites : couple (r, theta), plan: list # out - [[(deb, fin) (...) (deb,fin)] [...] [(deb, fin) (...) (deb, fin)] def intervalle(liste_droites: list, plan, precision_h:int) -> list: n = len(liste_droites) liste_intervalles =[] for i in range (n): r, theta = liste_droites[i][0], liste_droites[i][1] segments = intervalle_une_droite(r, theta, plan, precision_h) liste_intervalles.append(segments) return(liste_intervalles) # raccorde des segments qui sont peu éloignés (a une distance inferieur a distance_min) pour en faire une droite def raccordement_un_intervalle(segments: list, distance_min:int) -> list: new_segments = [] retry = False i = 0 while i < len(segments) : if (i < len(segments) -1 ) and (distance(segments[i][1], segments[i+1][0]) < distance_min) : retry = True new_segments.append((segments[i][0], segments[i+1][1])) i += 1 else : new_segments.append(segments[i]) i += 1 if retry : return(raccordement_un_intervalle(new_segments, distance_min)) return(new_segments) # raccorde des segments pour une liste d'intervalles d'une liste de droites def raccordement(liste_segments: list, distance_min:int = 50) -> list: new_segments = [] for i in liste_segments: new_segments.append(raccordement_un_intervalle(i, distance_min=distance_min)) return(new_segments) #enlève les intervalles trop petits, qui sont probablement des erreurs def enlever_petits_intervalles_une_droite(segments: list, longueur_min: int) -> list: new_segments =[] for i in range (len(segments)): if(distance(segments[i][0], segments[i][1])) > longueur_min: new_segments.append(segments[i]) return(new_segments) # applique la fonction enlever_petits_intervalles_une_droite sur chaque segement def enlever_petits_intervalles_general(liste_segments: list, longueur_min:int = 150) -> list: new_segments =[] for i in liste_segments: new_segments.append(enlever_petits_intervalles_une_droite(i, longueur_min)) return(new_segments) # Retourne l'ensemble des points d'intersection entre deux segments def intersection_deux_segments(segment1: tuple, segment2: tuple) -> tuple: ((xdeb1,ydeb1),(xfin1,yfin1)),((xdeb2,ydeb2),(xfin2,yfin2)) = segment1,segment2 (a1,b1), (a2,b2) = equation((xdeb1,ydeb1),(xfin1,yfin1)), equation((xdeb2,ydeb2),(xfin2,yfin2)) if a1 != a2: x_sol = (b2 - b1) / (a1 - a2) y_sol = a1 * x_sol + b1 if ((xdeb1 < x_sol < xfin1) or (xfin1 < x_sol < xdeb1)) and ((xdeb2 < x_sol < xfin2) or (xfin2 < x_sol < xdeb2)) and ((ydeb1 < y_sol < yfin1) or (yfin1 < y_sol < ydeb1)) and ((ydeb2 < y_sol < yfin2) or (yfin2 < y_sol < ydeb2)): return (x_sol, y_sol) # calcule toutes les intersections entre une liste de segments # type : [[droite i] [...] [droite j] ] -> ((droite i, droite j), (x, y)) # avec (x,y) : les coordonnées du point d'intersection def intersection_general(liste_segments): n = len(liste_segments) liste_intersection = [] for i in range (n): for j in range (n): if i > j: # permet d'eviter les doublons. La matrice est alors inferieur gauche. try: x,y = intersection_deux_segments(liste_segments[i],liste_segments[j]) liste_intersection.append(((liste_segments[i], liste_segments[j]), (x,y))) except Exception as e: # Il peut ne pas y avoir d'intersection entre ces deux segements, la fct intersection_deux_segments ne renvoie # rien, on a donc une erreur et c'est pour cela qu'on passe. pass return (liste_intersection) # transforme la une liste de liste en liste d'elements def flatten(liste: list) -> list: flat_list = [] for sublist in liste: for item in sublist: flat_list.append(item) return(flat_list) # calcule la matrice d'intersections # renvoie : matrice[i][j] =(x,y) <=> (x,y) est le point d'intersection entre le ième et le jème segment de [liste_segments] def matrice_intersections(liste_intersections: list, liste_segments: list): len_segments = len(liste_segments) # nombres de routes len_intersection = len(liste_intersections) # nombre d'intersections m = [[ (-1,-1) for i in range(len_segments)] for j in range(len_segments)] for z in range (len_intersection): (droite_1,droite_2), (x,y) = liste_intersections[z] index_i = liste_segments.index(droite_1) index_j = liste_segments.index(droite_2) m[index_i][index_j] = (x,y) return(m) # renvoie la matrice d'adjacence correspondant au graphe de notre ville # on definit m[i][i] comme les coordonnées du point i et m[i][j] la distance entre le sommet i et le sommet j si ils sont relié. sinon, -1 # add_str permet de modifier le nom du fichier def mat_adjacence(mat_intersections: list, liste_intersections: list, img_NB: list, img: list, add_str: str = ""): liste_pts = list(set([x[1] for x in liste_intersections])) # enlève les doublons n_r = len(liste_pts) # nb de routes n_i = len(mat_intersections[0]) # nb de sommets graphe_return = [[-1 for y in range(n_r)] for x in range(n_r)] for i in range(n_r): graphe_return[i][i] = liste_pts[i] # definition de m[i][i] for j in range(n_r): if i > j: if voisin(liste_pts[i], liste_pts[j], img_NB): d = int(distance(liste_pts[i], liste_pts[j])) graphe_return[i][j] = d graphe_return[j][i] = d plt.plot((liste_pts[i][0], liste_pts[j][0]),(liste_pts[i][1], liste_pts[j][1]) ) return(graphe_return) # renvoie si a et b sont des voisins. # pour cela, on verifie si il y a plus de [p]% de points de route entre les deux def voisin(pt1: tuple, pt2 : tuple, img : list, p: int = 60) -> tuple: a, b = equation(pt1, pt2) pts = [x for x in range(int(min(pt1[0], pt2[0])),int(max(pt1[0], pt2[0])))] # valeurs que doit prendre x sur le trajet nb_tot = len(pts) def f(x): # équation de la droite return(int(a*x+b)) c = 0 # compteur de points blanc for x in pts: # on compte le nombre de points blanc entre les deux points if f(x) < len(img): if img[f(x)][x] == BLANC : c += 1 if nb_tot == 0 : return(False) return((c/(nb_tot)*100)>p) # Applique l'algorithme de dijkstra à une matrice d'adjacence et un sommet de début donné # Renvoie la liste des distances du sommet de départ à tout les autres # la liste des sommets qui ont découvert t[i] (liste des parents) def dijkstra(mat_adj: list, sommet_deb:int, sommet_fin: int): vue = [sommet_deb] # liste des sommets déjà vu n = len(mat_adj) dist = [ -1 for i in range(n)] # liste des distances dist[sommet_deb] = 0 liste_parents = [ -1 for i in range(n)] nb = 0 for _ in range(n-1): nb += 1 mini = MAX_INT # distance minimum des voisins sommet_min = -1 a_decouvert = 0 for cur in range(n): # on parcours les sommets if cur in vue : # si le sommet a déjà été vu for vois in range(n): # on parcours ses voisins if mat_adj[cur][vois] != -1 and not (vois in vue): # si il est de distance inferieure if mat_adj[cur][vois] + dist[cur] < mini : # on le définit comme meilleur candidat et on continue mini = mat_adj[cur][vois] + dist[cur] sommet_min = vois a_decouvert = cur liste_parents[sommet_min] = a_decouvert # on conserve le meilleur candidat dist[sommet_min] = mini vue.append(sommet_min) if sommet_min == sommet_fin: break return(liste_parents,dist, nb) # Renvoie la liste des sommets à parcourir pour aller du sommet de début au sommet de fin à partir du tableau de dijkstra # est appelé avec la liste des pères renvoyé par dijkstra def chemin(liste_decouvre: list, sommet_fin:int) -> list: liste_sommet = [] i = sommet_fin while liste_decouvre[i] != -1 : # -1 est le sommet de départ liste_sommet.append(i) # on est sensé ajouter les elements au début de la liste. On les ajoutes à la fin, puis on retourne la liste i = liste_decouvre[i] liste_sommet.append(i) liste_sommet = liste_sommet[::-1] return(liste_sommet) # Renvoie la liste des sommets à parcourir à partir du graphe d'adj, # le sommet de deb, repéré par son indice dans la matrice et le sommet de fin, repéré de même def plus_court_chemin_dijkstra(mat_adj: list, sommet_deb:int, sommet_fin:int) -> list: start_dijkstra = time() liste_dec, _, nb_sommets = dijkstra(mat_adj, sommet_deb, sommet_fin) pcc = chemin(liste_dec,sommet_fin) return(pcc, nb_sommets, (time() - start_dijkstra)) # Algorithme A* # [mat_adj] : matrice d'adjacence avec t[i][i] les coordonnées du point # [h] heuristique : fonction d'estimation de la distance # [s] sommet de depart # [t] sommet d'arrivé def a_etoile(mat_adj, h, s, t): n = len(mat_adj[0]) # nb de sommets f = FP() f.push(s, 0) liste_distance = [ MAX_INT for i in range(n)] liste_distance[s] = 0 nb = 0 while not(f.is_empty()): nb +=1 v = f.pop() if v == t : # si on a atteint le sommet voulu return(reconstruire(liste_distance, mat_adj, t), nb) else : # sinon on s'applique sur chaque voisins for u in voisins_a(v, mat_adj): if liste_distance[u] > liste_distance[v] + mat_adj[v][u] : liste_distance[u] = liste_distance[v] + mat_adj[v][u] f.push(u, liste_distance[u] + h(mat_adj, u, t)) # voisins pour la fonction A* # s est le sommet que l'on considère def voisins_a(s: int, matrice_adj: list) -> list: n = len(matrice_adj) l = [] # liste des voisins for i in range(n): if i != s and matrice_adj[s][i] != -1: # si [i] et [s] sont voisin dans la matrice d'adjacence l.append(i) return(l) # reconstuit le chemin de t a s, pour la fonction A* # d est la liste des distances entre le sommet original et le sommet d[i] # t est le sommet d'arrivée def reconstruire(d: list, mat_adj: list, t: int) -> list: r = d[t] # r est la distance restante avec le sommet de depart chemin = [t] # on initialise le chemin avec le sommet d'arrivé while r!=0 : # tant qu'il reste de la distance jusqu'au sommet de de depart for u in range(len(mat_adj)): # on parcours tout les voisind de t if u!=t : # - if r == d[u] + mat_adj[u][t] : # si la distance restante est la distance entre le sommet u et le sommet de chemin.append(u) # départ + la distance entre u et le sommet actuel r = r - mat_adj[u][t] # on diminue la distance t = u # on passe par ce sommet et on recommence l'algorithme break chemin.reverse() return(chemin) # Heuristique pour A* # On utilise la distance à vol d'oiseau. # C'est bien une heuristique acceptante. def heuristique(mat_adj: list, sommet_act:int , sommet_fin:int) -> int: x1,y1 = mat_adj[sommet_act][sommet_act] x2,y2 = mat_adj[sommet_fin][sommet_fin] dist_min = distance((x1,y1), (x2,y2)) return (dist_min) # determine le nombre de points blanc d'une droite, en pouvant avancer de d points sans reset le compte # droite est donnée sous la forme d'un couple (a, b) # l'image dois être l'image en noir et blanc # [d] est la distance maximale entre deux points blancs def nombre_points_blanc(droite: tuple, img: list, d: int = MAX_INT) -> int: n = len(img) # dimension de l'image m = len(img[1]) # dimension de l'image distance = d # distance max liste_dist = [] # liste des suites de points blanc (a,b) = droite nmbre_points = 0 # nombre de points blanc for x in range (m): y = a*x+b if (y=0): # si on est bien dans l'image if distance == 0 : # si on a trop avancé dans l'image sans croiser de points blancs liste_dist.append(nmbre_points) # nmbre_points = 0 # on reset le compte de points distance = d # on reset la distance if (img[int(y)][int(x)] >= BLANC): # si le pixel est blanc nmbre_points+=1 # on incremente la valeur du nb de points distance = d # on reset la distance else : distance -= 1 # on decremente la distance liste_dist.append(nmbre_points) return(max(liste_dist)) # valeur maximale d'une suite de points blanc # fusionne les droites similaires # liste est la liste des droites parametrée selon r et theta # dico est un dictionnaire représentant les droites traitées et non traitées # nb_lim est le nombre de pixel maximum de difference permettant la fusion de deux droites # a_fact et b_fact sont les facteurs permettant de choisir les droites a prendres en comptes entre elles, en parametrage carthesien def fusion_droites (liste: list, imageNB, dico: dict, a_fact: float, b_fact: float, nb_lim: int, precision_hough: int) -> list: nouvelle_liste = [] modif = False for i in range(len(liste)): (r1,theta1) = liste[i] for j in range(1, len(liste)): (r2, theta2) = liste[j] a1, b1 = droite(r1, theta1, precision_hough) a2, b2 = droite(r2, theta2, precision_hough) if r1 == r2 and theta1==theta2: # on ne se considere pas soit même pass else : if (dico[(r1, theta1)]!=1) and (dico[(r2, theta2)]!=1): # on a déjà traiter la droite min_a = min(abs(a1), abs(a2)) moy_a = abs(a1 + a2)/2 a_lim = a_fact + a_fact * min_a**2 if (abs(a1-a2) < a_lim): # si les droites sont suffisament proche selon les a b_lim = b_fact + moy_a**2 * b_fact if abs(b1 - b2) < b_lim : # si les droites sont suffisament proche selon des b n1 = nombre_points_blanc((a1,b1), imageNB, 5) n2 = nombre_points_blanc((a2,b2), imageNB, 5) if (abs(n1-n2) < nb_lim): # on conserve la droite moyenne entre les deux ntot = n1 + n2 # -- r_moy = (r1 + r2)/2 # -- theta_moy = (theta1 + theta2)/2 # -- nouvelle_liste.append((r_moy, theta_moy)) # -- elif ( n1 > n2 ): # on conserve uniquement la droite 1 nouvelle_liste.append((r1, theta1)) # -- else : # on conserve uniquement la droite 1 nouvelle_liste.append((r2, theta2)) # -- modif = True dico[(r1, theta1)] = 1 dico[(r2, theta2)] = 1 if dico[(r1,theta1)]!=1: nouvelle_liste.append((r1, theta1)) return(list(set(nouvelle_liste)), modif, dico) # applique en boucle la fonction fusion_droites jusqu'à qu'il n'y ai plus de modifications def fusion_droites_rec(liste: list, image: list , a_fact: int, b_fact: int, nb_lim: int, precision_hough: int) -> list: dico = {} # Cas initial for (r1,theta1) in liste: dico[(r1,theta1)] = 0 nv_liste, booleen, dico = fusion_droites(liste, image, dico, a_fact, b_fact, nb_lim, precision_hough) while booleen: # Le booleen représente si une modification a été faite ou non dico = {} # si c'est le cas on recommence for (r1,theta1) in nv_liste: dico[(r1,theta1)] = 0 nv_liste, booleen, dico = fusion_droites(nv_liste, image, dico, a_fact, b_fact, nb_lim, precision_hough) return(nv_liste) # trie une liste selon la deuxieme coordonnée def sort_list_theta(liste: list) -> list: liste = [(x[1], x[0]) for x in liste] liste.sort() return([(x[1], x[0]) for x in liste]) # Permet de fusionner les intersections qui sont proches les une des autres, à partir de la matrice d'adjacence. # distance_max est la distance à partir de laquelle on arrête de fusionner les droites. def cluster(matrice_adj: list, distance_max: int) -> list: for i in range(len(matrice_adj)): # on parcours l'intégralité des sommets for j in range(i+1, len(matrice_adj)): point1 = matrice_adj[i][i] point2 = matrice_adj[j][j] x1, y1 = point1 x2, y2 = point2 if distance(point1, point2) < distance_max and (x1,y1) != (-1, -1) and (x2,y2) != (-1, -1): # on supprime la valeur j et on introduit les anciennes valeurs dans i matrice_adj[i][i] = (int((x1+x2)/2), int((y1+y2)/2)) # la coordonnée du point est la moyenne des deux matrice_adj[j][j] = (-1, -1) for k in range(len(matrice_adj)): if k!=i and k != j: if matrice_adj[j][k] != -1: if matrice_adj[i][k] != -1: matrice_adj[i][k] = (matrice_adj[i][k] + matrice_adj[j][k])/2 matrice_adj[k][i] = (matrice_adj[k][i] + matrice_adj[k][j])/2 else : matrice_adj[i][k] = matrice_adj[j][k] matrice_adj[k][i] = matrice_adj[k][j] matrice_adj[j][k] = -1 matrice_adj[k][j] = -1 return(cluster(matrice_adj, distance_max)) return(matrice_adj) def matrice_recadre(points, mat): belle_matrice = [[0 for i in range(len(points))] for i in range(len(points))] for i in range(len(points)): for j in range(len(points)): belle_matrice[i][j] = mat[points[i]][points[j]] return(belle_matrice) def main(lien: str, precision_hough:int = 1): print("Lecture de l'image.") # uniquement a partir de plan image = read_img(lien) print("Conversion en niveau de gris.") image_grayscale = color_to_grayscale(image) print("Conversion en noir et blanc.") image_NB = grayscale_to_black_and_white(image_grayscale) print("Calcul de l'espace de Hough.") espace_h = hough_c(image_NB, precision_hough) save_hough(espace_h) print("Récuperation des droites.") liste_droites1 = peak_local_max(np.array(espace_h), min_distance=70, num_peaks=500, threshold_rel=0.23) print(f"Nombre de droites : {len(liste_droites1)}.") liste_droites1 = [list(x) for x in list(liste_droites1)] save_with_droites(image, liste_droites1, precision_hough, "01. toutes les droites") liste_droites2 = fusion_droites_rec(sort_list_theta(liste_droites1), image_NB, 0.5, 50, 10, precision_hough) save_with_droites(image, liste_droites2, precision_hough, "02. premier filtrage des droites") liste_droites3 = fusion_droites_rec(sort_list_theta(liste_droites2), image_NB, 0.3, 75, 10, precision_hough) save_with_droites(image, liste_droites3, precision_hough, "03. deuxieme filtrage des droites") print("Récupération de la listes des intervalles.") liste_intervalles = intervalle(liste_droites3, image_NB, precision_hough) save_liste_inter(liste_intervalles, image, "04. intervalles") print("Raccorde les droites.") liste_segments = raccordement(liste_intervalles, 28) save_liste_inter(liste_segments, image, "05. raccordement (28)") print("enlève les petits bouts de droite") liste_segments = enlever_petits_intervalles_general(liste_segments) save_liste_inter(liste_segments, image, "06. segments (28)") liste_segments = flatten(liste_segments) liste_intersections = intersection_general(liste_segments) save_intersection(liste_intersections, image) print("transformation en matrice d'intersections") matrice_inter = matrice_intersections(liste_intersections, liste_segments) matr_adj = mat_adjacence(matrice_inter, liste_intersections, image_NB, image) print("clusterisation") matrice_adj_cluster = cluster(matr_adj, 28) save_cluster(matrice_adj_cluster, image) save_graphe(matrice_adj_cluster, image) #save_full_graphe(matrice_adj_cluster, image) sommet_depart = 63 sommet_arrivee = 61 # d'autres valeurs intéressantes sont possibles : 61->73 ; 1->24 chemin_dijksra, nb_sommets_dijkstra, duree_dijksra = plus_court_chemin_dijkstra(matr_adj, sommet_depart, sommet_arrivee) start_a_star = time() chemin_a_star, nb_sommets_a_star = a_etoile(matr_adj, heuristique, sommet_depart, sommet_arrivee) duree_a_star = (time() - start_a_star) print(f"chemin dijkra : {chemin_dijksra}, temps d'execution : {duree_dijksra}, sommets parcourus : {nb_sommets_dijkstra}") print(f"chemin A*: {chemin_a_star}, temps d'execution : {duree_a_star}, sommets parcourus : {nb_sommets_a_star}") save_chemin(chemin_dijksra, matrice_adj_cluster, image, "dijkstra", "g") save_chemin(chemin_a_star, matrice_adj_cluster, image, "a star", "k") return(matrice_adj_cluster) mat = main("https://server.ip/TIPE/paris2.png", 100) #points = [25, 41, 3, 14, 52, 53, 54] print(matrice_recadre([25, 41, 3, 14, 52, 53, 54], mat))