Pages: 1
- Sujet précédent - QGIS: Detection de classes entourees par une autre classe - Sujet suivant
#1 Wed 05 July 2023 03:09
- BorelPaul
- Juste Inscrit !
- Date d'inscription: 4 Jul 2023
- Messages: 3
QGIS: Detection de classes entourees par une autre classe
Bonjour, je poste ce message pour obtenir de l'aide sur un problème que j'ai actuellement.
J'ai un raster qui représente 4 classes d'occupation du sol (représenté par 4 valeurs) :
Classe A = 1
Classe B = 2
Classe C = 3
Classe D = 4
Mon raster est très grand (10000 x 10000 pixels)
J'aimerais changer la valeur des pixels de la classe D (=4) lorsqu'elle est entièrement entourée par des pixels de la classe C (=3).
J'ai essayé de faire des sélections classiques en vectorisant mon raster avec "sélection par localisation" avec le mode 'contient' mais cela ne fonctionne pas car la couche l'entoure et ne la contient pas.
Je me suis dit aussi qu'en récupérant les contours de mes polygones de ma classe C(=3) je pourrais reformer de nouveaux polygones "complets" ou "sans trous" qui me permettrais de sélectionner mes polygones de classe D(=4) avec la sélection par localisation mais je n'y parviens pas, les contours interne sont toujours récupérer (j'ai utilisé r.contour de GRASS)
J'ai aussi essayé en conservant le raster mais les manipulations de rasters sont souvent très longues donc cela ne peut pas être appliqué dans mon cas..
Merci beaucoup déjà de lire ce post et j'espère que vous aurez des pistes à me proposer !
Dernière modification par BorelPaul (Wed 05 July 2023 10:14)
Hors ligne
#2 Fri 07 July 2023 09:25
- BorelPaul
- Juste Inscrit !
- Date d'inscription: 4 Jul 2023
- Messages: 3
Re: QGIS: Detection de classes entourees par une autre classe
Alors je suis passé sous python pour essayer de trouver une solution et j'ai fait ça ! (au cas où si quelqu'un se pose la question)
Le code n'est surement pas parfait mais il fonctionne (pour exemple il traite un raster de 10 000px * 10 000px en environ 8 minutes, même si cela dépend beaucoup de la quantité de pixels à modifier et la complexité des données).
Si vous avez des suggestions pour des modifications futures ou des remarques je suis preneur !
Ce code crée des groupes de pixels collé les un aux autres (dans mon exemple il groupe les pixels égal à 4) et ensuite calcule le pourcentage de pixels d'une autre valeur autour de chacun des groupes, au dessus d'un certain pourcentage (dans mon exemple 60% de pixel égal à 3) il change la valeur des pixels vers une valeur prédéfinie (dans mon exemple 3).
Code:
import rasterio import numpy as np from tqdm import tqdm import os # Chemin vers le dossier contenant les fichiers raster dossier_source = r'chemin/vers/votre/dossier' # Liste des fichiers raster à traiter liste = ['chemin/vers/votre/fichier1.tif', 'chemin/vers/votre/fichier2.tif'] for fichier in liste: # Chemin vers le fichier de sortie modifié output_raster_path = fichier[:-4] + "_modifie.tif" # Passe si un fichier de sortie de même nom a déjà été généré if os.path.exists(output_raster_path): print(output_raster_path + " existe déjà !") continue # Lire le raster with rasterio.open(fichier) as src: # Lire les données raster raster_data = src.read(1) # Copier les données raster pour effectuer les modifications modified_raster_data = raster_data.copy() # Tableau pour stocker les groupes group_table = np.zeros_like(raster_data, dtype=np.int32) # Dictionnaire pour stocker les coordonnées des pixels de contour pour chaque groupe contour_pixels = {} # Valeur de groupe initial current_group = 1 # Parcourir tous les pixels du raster en utilisant un parcours en profondeur (DFS) itératif def dfs(i, j, current_group): stack = [(i, j)] while stack: i, j = stack.pop() if (0 <= i < raster_data.shape[0] and 0 <= j < raster_data.shape[1] and raster_data[i, j] == 4 and group_table[i, j] == 0): group_table[i, j] = current_group contour_pixels[current_group].append((i, j)) # Ajouter les voisins non marqués à la pile stack.extend([ (i, j-1), # Gauche (i-1, j-1), # Haut gauche (i-1, j), # Haut (i-1, j+1), # Haut droite (i, j+1), # Droite (i+1, j+1), # Bas droite (i+1, j), # Bas (i+1, j-1) # Bas gauche ]) # Parcourir tous les pixels du raster for i in tqdm(range(raster_data.shape[0]), desc='Processing'): for j in range(raster_data.shape[1]): if raster_data[i, j] == 4 and group_table[i, j] == 0: current_group += 1 contour_pixels[current_group] = [] # Initialiser la liste des pixels de contour pour ce groupe dfs(i, j, current_group) # Parcourir les groupes pour vérifier le pourcentage de pixels voisins des pixels de contour for group, pixels in tqdm(contour_pixels.items(), desc='Processing contours'): contour_array = np.array(pixels) contour_i, contour_j = contour_array[:, 0], contour_array[:, 1] # Obtenir les indices des voisins (les 8 voisins) neighbors_i = np.array([contour_i-1, contour_i-1, contour_i-1, contour_i, contour_i, contour_i+1, contour_i+1, contour_i+1]) neighbors_j = np.array([contour_j-1, contour_j, contour_j+1, contour_j-1, contour_j+1, contour_j-1, contour_j, contour_j+1]) # Filtrer les voisins valides valid_neighbors = np.logical_and( np.logical_and(neighbors_i >= 0, neighbors_i < raster_data.shape[0]), np.logical_and(neighbors_j >= 0, neighbors_j < raster_data.shape[1]) ) neighbors_i = neighbors_i[valid_neighbors] neighbors_j = neighbors_j[valid_neighbors] # Obtenir les valeurs des voisins neighbor_values = raster_data[neighbors_i, neighbors_j] # Compter les voisins ayant la valeur 3 imper_neighbors = np.count_nonzero(neighbor_values == 3) # Compter les voisins ayant une valeur différente de 4 pour obtenir le nombre total de voisins total_neighbors = np.count_nonzero(neighbor_values != 4) # Calculer le pourcentage percentage = (imper_neighbors * 100) / total_neighbors if percentage > 60: # Changer les valeurs des pixels du groupe de 4 à 3 dans raster_data group_indices = np.where(group_table == group) raster_data[group_indices] = 3 # Enregistrer le raster modifié with rasterio.open(output_raster_path, 'w', **src.meta) as dst: dst.write(raster_data, 1) print("Programme terminé")
Dernière modification par BorelPaul (Fri 07 July 2023 10:12)
Hors ligne
Pages: 1
- Sujet précédent - QGIS: Detection de classes entourees par une autre classe - Sujet suivant