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


