#1 Tue 19 July 2016 12:28
- Tris
- Participant occasionnel
- Date d'inscription: 23 Jun 2016
- Messages: 14
QGIS 2.8: Problème de fusion via la console Python
Bonjour,
J'ai rasteriser 9 vecteurs qui séparément se superposent correctement mais lorsque je les fusionne via la console Python j'ai un décalage vertical de 100 m qui se produit. Les fichiers rasterisés sont tous dans le même SCR, le x et y d'origine de chacun de mes rasters sont les mêmes et ils ont tous la même taille de pixel, 1 pixel=1 mètre. J'ai relancé l'outil fusionné (raster) pour voir si cela marche donc en attendant je ne peux pas vous donner des infos précises si vous avez besoin mais dès que cela a fini de tourner je vous les donnerai.
Avez vous une idée de pourquoi se décalage s’opère.
Ci-joint le fichier .py
Pouvez vous me dire si le script est bon ou si cela provient de mes données.
Cordialement
Tristan
Hors ligne
#2 Tue 19 July 2016 13:40
- JD
- Moderateur
- Date d'inscription: 8 Aug 2013
- Messages: 726
Re: QGIS 2.8: Problème de fusion via la console Python
Bonjour,
y a t-il une raison sur le fait que vous passiez par le module gdal pour fusionner vos raster ?
Le plus simple vu que vous passez par la console python serait de passer par le module processing
et par l'algorithme 'gdalogr:merge'.
Si l'outil fusionner fonctionne je vous propose plutôt ce code :
Code:
import processing #pour avoir de l'aide sur l'algo vous tapez #dans la console processing.alghelp('gdalorg:merge') #afin de voir les options qui vous conviennent #paramètre de départ le chemin des rasters séparés par un ";" input_layers = ';'.join([layer.source() for layer in processing.getAllLayers()]) newRasterfn = '/Users/sbooob/Desktop/QGis/SIG/out.tif' processing.runalg('gdalogr:merge', input_rasters, False, False,4,newRasterfn)
Dernière modification par lejedi76 (Tue 19 July 2016 13:46)
Hors ligne
#3 Tue 19 July 2016 14:54
- Tris
- Participant occasionnel
- Date d'inscription: 23 Jun 2016
- Messages: 14
Re: QGIS 2.8: Problème de fusion via la console Python
J'ai essayé avec l'outils Raster>divers>fusionner mais ça n'a pas marché (je ne voyait que la dernière couche visible, cela provenait surement du fait que lorsque j'ai créé mes rasters il m'a remplacé tous les vides par 0 au lieu de le remplacer par Nodata) j'ai trouvé comment le faire via la console python mais ça ne tiens pas après avoir redémarrer QGIS, et la j'ai défini la nodatavalues à 0 pour tous les rasters sans fermer qgis et en relançant l'outils fusion mais via la processing tool box cette fois. Et la ça tourne!
Hors ligne
#4 Tue 19 July 2016 16:56
Re: QGIS 2.8: Problème de fusion via la console Python
Il peut être , bien entendu, utile de poser la même question sur plusieurs forums, mais la politesse voudrait qu'on le signale et qu'on assume en coordonnant les réponses.
http://gis.stackexchange.com/questions/ … ing-python
http://www.forumsig.org/showthread.php/ … post344283
Dernière modification par gene (Tue 19 July 2016 16:57)
Hors ligne
#5 Wed 20 July 2016 10:24
- Tris
- Participant occasionnel
- Date d'inscription: 23 Jun 2016
- Messages: 14
Re: QGIS 2.8: Problème de fusion via la console Python
Bonjour,
Oui j'aurais du mettre en lien mes autres messages mais en attendant le seul en endroit où j'ai eu une réponse c'est ici et malgré tous les essaies que l'on ai fait rien n'a fonctionné. J'aurais bien évidement posté un message avec la solution qui m'aurai été proposé ou bien que j'aurai trouvé si je l'avais eu.
Hors ligne
#6 Wed 20 July 2016 11:35
- dominique.lys
- Participant assidu
- Date d'inscription: 5 Oct 2006
- Messages: 473
- Site web
Re: QGIS 2.8: Problème de fusion via la console Python
Bonjour,
Pourquoi ne pas tout simplement utiliser une calculatrice raster... Je ne crois pas que gdal merge soit la solution c'est un outil dédié à la réalisation de mosaic (http://www.gdal.org/gdal_merge.html) et ce n'est clairement pas ce que vous essayez de faire.
Quelques remarques concernant votre script, il faut noté que la fonction ReadAsArray() retourne un tableau numpy et que dans un tableau numpy en 2D la première dimension représente toujours les lignes et la seconde les colonnes. On accède donc aux valeurs avec l'index y en 1er
Code:
data[row, column] == data[y, x]
Votre double itération devrait donc plutôt ressembler à ça:
Code:
ny, nx = layerData.shape for x in range(nx): for y in range(ny): dest[y][x] = layerData[y][x]
Néanmoins affecter les valeurs une à une est une assez mauvaise pratique car verbeux et lent, il est préférable de profiter des fonctionnalités de numpy avec notamment la possibilité de tout simplement additionner des tableaux. Ainsi,
Code:
dest += layerData
remplacera avantageusement votre double itération.
Quoi qu'il en soit je vous engage à explorer l'utilisation des calculatrices raster. Il y en a plusieurs : celle de QGIS accessible depuis le menu raster et celles de SAGA, GDAL et GRASS accessible depuis processing.
Dernière modification par dominique.lys (Wed 20 July 2016 11:50)
Hors ligne
#7 Wed 20 July 2016 12:45
- JD
- Moderateur
- Date d'inscription: 8 Aug 2013
- Messages: 726
Re: QGIS 2.8: Problème de fusion via la console Python
Bonjour,
effectivement le terme "fusionne" et votre fichier "merge.py" m'ont totalement induit en erreur d'où ma réponse complètement à côté de la plaque.
Avec le message de dominique.lys, j'ai enfin compris, et je suis d'accord pour la calculatrice raster.
L'outils processing et la calculatrice raster devrait répondre à votre besoin.
processing et le script 'gdalorg:rastercalculator'
On peut passer en paramètre jusqu'à 6 rasters.
Dernière modification par lejedi76 (Wed 20 July 2016 12:45)
Hors ligne
#8 Wed 20 July 2016 17:05
- Tris
- Participant occasionnel
- Date d'inscription: 23 Jun 2016
- Messages: 14
Re: QGIS 2.8: Problème de fusion via la console Python
Bonjour a vous deux!
Merci de vos réponse et pas de souci Lejedi76
Juste pour vous expliquer le contexte. Je suis en stage et je dois faire du SIG à un niveau qui me dépasse de beaucoup. Mon frère qui est développeur web et m'aide pour tout ce qui est "langage informatique" et python. Mais à nous deux on ne fait pas un très bon SIGiste, loin de la...
Mon frère viens de se lancer sur ce que tu nous a dit dominique.lys et le resultat est le même on a toujours 100m de decaalge verticale
Par contre pour la calculatrice raster c'est que je veux utiliser depuis le début mais on a pas trouvé de documentation précise sur comment s'en servir du coup on l'a un peu délaissé mais la on but et on risque de devoir s'en servir pour de bon!
En gros j'ai des 9 couches raster dont une qui sera à la base et qui va être compléter par les 8 autres. Je veux que les valeurs des pixels des couches que je vais ajouter se substituent à celle d'en dessous.
Je veux donc qu'il me remplace la valeurs du pixel de la couche de base par celle d'ajout. Si le pixel de la couche d'ajout est =0 alors il faut garder la valeur de la couche initial mais si il est différent de 0 alors il faut remplacer la valeur du pixel de la couche de base par celui de la couche d'ajout.
Donc soit je peux faire cela 8 fois et reprendre le fichier raster créer en sortie soit apparemment comme dit lejedi76 on peut le faire jusqu'à 6 paramètres ce qui pourrait nous faire gagner du temps.
Savez-vous comment le formuler pour que la calculatrice raster tourne correctement, avec l'une ou l'autre des méthodes je suis preneur!
Merci de votre contribution!
Tristan et Yo
Dernière modification par Tris (Wed 20 July 2016 17:54)
Hors ligne
#9 Wed 20 July 2016 17:56
- dominique.lys
- Participant assidu
- Date d'inscription: 5 Oct 2006
- Messages: 473
- Site web
Re: QGIS 2.8: Problème de fusion via la console Python
D'après ce que comprends une simple addition avec la calculatrice raster devrait faire l'affaire:
Code:
raster1 + raster2 + ... + raster8 + raster9
Menu Raster >> Raster Calculator >> écrire l'addition
Hors ligne
#10 Wed 20 July 2016 21:23
- Tris
- Participant occasionnel
- Date d'inscription: 23 Jun 2016
- Messages: 14
Re: QGIS 2.8: Problème de fusion via la console Python
J'ai essayé et ça ne marche pas, cela additionne les valeurs au leu de les remplacer, j'aurais aimé que ce soit aussi simple...
Prenons un exemple simplifié. raster1 est la couche inférieure, raster2 est la couche supérieure.
Je souhaite remplacer les pixels de raster1 par ceux de raster2, sauf la valeur du pixel de raster2 est égale à 0, auquel cas je veux conserver la valeur de raster 1 :
Code:
raster1 = [[ 0, 0, 1 ], [ 0, 1, 0 ], [ 1, 0, 0 ]] raster2 = [[ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ]]
Je souhaite obtenir le rasterFusionné suivant :
Code:
rasterFusionné = [[ 1, 0, 1 ], [ 0, 1, 0 ], [ 1, 0, 1 ]]
La solution que vous proposez ne produit pas le même raster :
Code:
rasterFusionné = [[ 1, 0, 1 ], [ 0, 2, 0 ], [ 1, 0, 1 ]]
C'est pour effectuer un traitement différent si la valeur du pixel est égale à 0 que je me suis tourné vers Python. Peut-être qu'une des calculatrices raster peut aussi me permettre d'y arriver mais la formule doit être un peu plus compliquée qu'une simple addition.
Je ne pense pas que cela produise l'effet recherché.
Prenons un exemple simplifié. raster1 est la couche inférieure, raster2 est la couche supérieure.
Je souhaite remplacer les pixels de raster1 par ceux de raster2, sauf la valeur du pixel de raster2 est égale à 0, auquel cas je veux conserver la valeur de raster 1 :
Code:
raster1 = [[ 0, 0, 1 ], [ 0, 1, 0 ], [ 1, 0, 0 ]] raster2 = [[ 1, 0, 0 ], [ 0, 1, 0 ], [ 0, 0, 1 ]]
Je souhaite obtenir le rasterFusionné suivant :
Code:
rasterFusionné = [[ 1, 0, 1 ], [ 0, 1, 0 ], [ 1, 0, 1 ]]
La solution que vous proposez ne produit pas le même raster :
Code:
rasterFusionné = [[ 1, 0, 1 ], [ 0, 2, 0 ], [ 1, 0, 1 ]]
C'est pour effectuer un traitement différent si la valeur du pixel est égale à 0 que je me suis tourné vers Python. Peut-être qu'une des calculatrices raster peut aussi me permettre d'y arriver mais la formule est un peu plus compliquée qu'une simple addition du coup, dommage... Mais merci quand même!
Hors ligne
#11 Thu 21 July 2016 00:06
- dominique.lys
- Participant assidu
- Date d'inscription: 5 Oct 2006
- Messages: 473
- Site web
Re: QGIS 2.8: Problème de fusion via la console Python
Dans ce cas il faut utiliser des fonctions conditionnelles. Par exemple numpy.where :
http://docs.scipy.org/doc/numpy/referen … where.html
dans le script de départ remplacer la double itération par
Code:
dest = numpy.where(layerData>0, layerData, dest)
Hors ligne
#12 Thu 21 July 2016 17:23
- Tris
- Participant occasionnel
- Date d'inscription: 23 Jun 2016
- Messages: 14
Re: QGIS 2.8: Problème de fusion via la console Python
Problème résolu.
Le code de mon premier post était correct bien que loin d'être optimisé.
Le problème venait en fait du fait que deux de mes rasters n'avaient pas la même origine que les autres (les coordonnées du point supérieur gauche étaient différentes pour ces deux rasters et pour les 7 autres).
Mon script Pyhton ne prend pas en compte les coordonnées géographiques et ne manipule que les pixels des rasters. Il est donc important que les rasters aient bien tous la même origine.
Après avoir pris soin de définir une origine commune à tous mes rasters, et optimisé le script en prenant en compte les suggestions de dominique.lys, j'ai relancé le script. Le gain de performance est impressionnant, l'opération qui prenait plus de 45 minutes s'effectue désormais en moins d'une minute !
Au cas où ça puisse aider quelqu'un, voici comment j'ai défini une origine commune à mes rasters (cela créé une copie de chaque raster) :
* Dans la liste des couches, faire un clic droit sur un raster et cliquer sur "Enregistrer sous...".
* Dans la boîte de dialogue qui s'ouvre, sélectionner où enregistrer le fichier en cliquant sur "Parcourir".
* Dans la section "emprise", entrer les coordonnées des limites géographiques de chacun des bords du raster (Nord, Sud, Est et Ouest). S'assurer de choisir des valeurs qui englobent la partie visible de tous les rasters et noter ces valeurs dans un coin.
* Valider en cliquant sur "OK".
* Répéter cette opération pour les autres rasters à traiter, en utilisant les mêmes valeurs pour l'emprise.
* Importer ces calques dans QGis pour remplacer les raster n'ayant pas une origine commune.
Et voici la nouvelle version du script. Ce script n'est pas très flexible (il a été écrit pour résoudre un problème précis, si vous souhaitez le réutiliser, des ajustements seront peut-être nécessaires). Il travaille sur tous les calques présents dans la liste des couches, qu'ils soient masqués ou non, et dans l'ordre inverse où ils apparaissent dans cette liste (Le premier raster utilisé celui en bas de la liste, puis on écrira par dessus les valeurs du deuxième en partant du bas et ainsi de suite).
Code:
import os import gdal import numpy import osr import sys def raster2array(raster): band = raster.GetRasterBand(1) return band.ReadAsArray() def getOrigin(raster): geotransform = raster.GetGeoTransform() return [geotransform[0], geotransform[3]] def getLayers(): return iface.legendInterface().layers() def array2raster(rasterfn,newRasterfn,array, bitDepth = 7): raster = gdal.Open(rasterfn) geotransform = raster.GetGeoTransform() originX = geotransform[0] originY = geotransform[3] pixelWidth = geotransform[1] pixelHeight = geotransform[5] cols = raster.RasterXSize rows = raster.RasterYSize driver = gdal.GetDriverByName('HFA') outRaster = driver.Create(newRasterfn, cols, rows, 1, bitDepth) outRaster.SetGeoTransform((originX, pixelWidth, 0, originY, 0, pixelHeight)) outband = outRaster.GetRasterBand(1) outband.WriteArray(array) outRasterSRS = osr.SpatialReference() outRasterSRS.ImportFromWkt(raster.GetProjectionRef()) outRaster.SetProjection(outRasterSRS.ExportToWkt()) outband.FlushCache() gdal.UseExceptions() # Get layers as they appear in the QGis Layers panel layers = getLayers() firstLayer = layers.pop() firstRasterPath = firstLayer.dataProvider().dataSourceUri() raster = gdal.Open(firstRasterPath) print "Using \"" + firstLayer.name() + "\" as base layer" origin = getOrigin(raster) dest = raster2array(raster) for layer in reversed(layers): print "Processing \"" + layer.name() + "\"." provider = layer.dataProvider() path = provider.dataSourceUri() raster = gdal.Open(path) layerOrigin = getOrigin(raster) layerData = raster2array(raster) dest = numpy.where(numpy.logical_and(0 < layerData, layerData <= 10000), layerData, dest) # Write output to a file newRasterfn = '/Users/sbooob/Desktop/QGis/SIG/merged.img' array2raster(firstRasterPath, newRasterfn, dest, gdal.GDT_UInt16)
En tout cas merci à tous pour votre aide et vos conseil.
Bonne fin de journée
Tristan et Yo
Hors ligne
#13 Fri 22 July 2016 08:32
- YoLecomte
- Participant assidu
- Lieu: Epinal
- Date d'inscription: 7 Jul 2015
- Messages: 266
Re: QGIS 2.8: Problème de fusion via la console Python
Salut,
Merci pour le partage!
Hors ligne