Skip to Content

QGIS : Gérer un catalogue d'images, comment se passer de Show/Hide Image ?


Il y a quelques temps j'avais fait un article sur comment gérer un catalogue d'images à l'aide des plugins Image boundary et Show/Hide Image : Plugin QGIS - Image boundary et Show/Hide Image : Gérer un catalogue d'images. Malheureusement si Image Boundary existe encore pour QGIS 2, ce n'est pas le cas pour Show/Hide Image. Alors comment faire en se passant de ces deux plugins ?

Image Boundary permet de créer un tableau d'assemblage de rasters contenus dans un dossier, il est possible de faire la même chose à l'aide de gdaltindex, disponible également dans QGIS :

Menu Raster / Divers / Index de tuiles

Je choisis d'écrire le chemin absolu dans le shapefile, mais un chemin relatif fonctionne tout aussi bien, et permet de déplacer les rasters et le tableau d'assemblage ailleurs sans avoir à modifier le tableau d'assemblage.

Une fois le tableau d'assemblage créé, il faut l'ouvrir dans QGIS.

Nous allons utiliser les actions pour gérer l'affichage ou non de nos rasters :

Il faut ouvrir les propriétés du tableau d'assemblage (clic droit sur la couche / Propriétés) puis se rendre sur l'onglet actions. Nous allons créer deux actions de type python, l'une pour ouvrir le raster et l'autre pour le fermer :

action openRaster :

  • choisir le type python
  • donner un nom à l'action : openRaster
  • puis entrer le code suivant dans la zone Action :
import os
chemin='[% "location" %]'
nomCouche = str(os.path.splitext(os.path.split(chemin)[1])[0])
qgis.utils.iface.addRasterLayer(chemin,nomCouche)

[% "location" %] correspond au nom du champ contenant le chemin vers le raster

  • puis cliquer sur Ajouter l'action à la liste

action closeRaster :

Faire de même que pour openRaster, mais dans la zone Action, entrez le code suivant :

closeRaster.py

  1. import os
  2. chemin='[% "location" %]'
  3. nomCouche = str(os.path.splitext(os.path.split(chemin)[1])[0])
  4. instRegistry = QgsMapLayerRegistry.instance()
  5. couche = instRegistry.mapLayersByName(nomCouche)
  6. if len(couche) > 0:
  7. instRegistry.removeMapLayer(couche[0].id())

Vous devez maintenant avoir deux actions liées au tableau d'assemblage

Appliquez et fermez les propiétés en validant par OK, puis vous pourrez utiliser les boutons d'actions :

Il ne vous reste plus qu'à sélectionner le tableau d'assemblage comme couche active, choisir l'une ou l'autre des actions et cliquer sur la dalle souhaitée.

L'inconvénient majeur de cette solution, c'est que les actions sont enregistrées dans le document courant, si vous ouvrez votre tableau d'assemblage dans un autre document, elles ne seront plus présentes. Il est possible de régler ce problème en cliquant sur le bouton Sauvegarder par défaut des propriétés de la couche. Ainsi lorsque vous ouvrirez à nouveau votre tableau d'assemblage, les actions seront présentes.

Il est probablement possible de faire mieux et plus propre, mais on voit qu'en quelques minutes il est possible de faire des choses très utiles assez simplement, j'espère que cela vous sera utile.


Site officiel : PyQGIS Developper CookBook


Creative Commons License
licence Creative Commons Paternité-Pas d'Utilisation Commerciale-Pas de Modification 2.0 France

Commentaires

Raster/Divers/construire un raster virtuel

Bonjour,

J'ai trouvé dans QGIS 2.10 l'outil Raster/Divers/construire un raster virtuel, qui permet de créér à partir des fichiers raster existants dans un répertoire ou affichés, une couche qui s'affiche comme une seule dalle raster.
C'est simple et rapide, et une fois la couche créée, on peut facilement régler sa transparence sans devoir le faire individuellement pour 150 dalles.

C'était ce que je cherchais quand je suis arrivé sur ce forum, alors si ça intéresse quelqu'un...

Déplacer tableau + raster

Bonjour,

Merci pour cette astuce très utile.
Par contre, j'ai une question toute bête : comment déplacer les rasters et le tableau d'assemblage généré dans un autre répertoire (genre clé usb ou autre) pour le partage des données ?

Merci d'avance.

Bonjour Cela doit être

Bonjour

Cela doit être possible en créant un tableau d'assemblage en y inscrivant des chemins relatifs (décocher le case écrire le chemin absolu) ensuite on pourra déplacer le repertoire contenant le TA et les données, je pense que ça devrait marcher.

Bonjour, J'ai effectivement

Bonjour,

J'ai effectivement pu créer un tableau d'assemblage limité à ma zone d'étude avec les chemins relatifs, mais après, comment déplacer ?
Le tableau est un fichier .SHP, si je le déplace, les dalles ne viendront pas avec.

Très pratique !!! mais petit soucis de projection...

J'ai testé les différents scripts et après quelques corrections de chemin, ils fonctionnent au détail près qu'avec le script d'ouverture, les dalles ecw sont chargées avec la projection par défaut wgs 84 au lieu de Lambert 93.
Question, est ce que je peux forcer dans le script leur chargement dans cette projection ou existe t'il une option dans qgis qui puisse le faire.
D'avance merci beaucoup.

Complément...

Bravo pour ces actions qui me sont très utiles !!

Quelqu'un aurait une piste pour ajouter une action de transparence sur une valeur de pixel ?
Le top serait de combiner cette action avec celle de l'ouverture du fichier...

Bon bé si vous avez des indices, je suis preneur !

Merci

BonjourMerci, c'est bien de

Bonjour


Merci, c'est bien de voir que ça sert.


Oui je pense que cela doit pouvoir se faire


  1. import os
  2. chemin='[% "location" %]'
  3. nomCouche = str(os.path.splitext(os.path.split(chemin)[1])[0])
  4. macouche = QgsRasterLayer(chemin,nomCouche)
  5. x = QgsRasterTransparency.TransparentSingleValuePixel()
  6. x.min = 0 #bien sur ici on pourrait recuperer une valeur d un champ
  7. x.max = 2 #bien sur ici on pourrait recuperer une valeur d un champ
  8. x.percentTransparent= 100
  9. rt = macouche.renderer().rasterTransparency()
  10. rt.setTransparentSingleValuePixelList( [ x ] )
  11. QgsMapLayerRegistry.instance().addMapLayer(macouche)

Merci !!!

Bonjour, j'ai utilisé votre astuce avec succès et vous en remercie beaucoup.
Voici les différents points qu'il a fallu régler chez moi:

1) gdaltileindex ne fonctionnait pas pour des raisons de droits d'accès que
j'ignorais. Je suis donc passé par la nouvelle version de Image Boundary pour version 2.X.

2) du fait de l'utilisation de Image Boundary, le champ ne se nomme plus chemin mais est la concaténation des champs PATH et IMAGE (voir commentaires précédents très utiles)

3) j'avais une anomalie de mauvais encodage, due à la présence de simples antislashs suivis de chiffres dans mes chemins d'accès ('SIG/4-geomatique/1-referentiels').
Pour régler çà j'ai doublé les antislashs dans le champ Path de ma grille vecteur grâce à la calculatrice de champ en mettant à jour le champ Path avec l'expression regexp_replace("Path",'\\\\','\\\\').

Avec les style par défaut .qml, ç'est parfait pour les utilisateurs utilisant une version 2.x, juste une couche à charger.

Mille mercis !!!

Merci ! Mais problème à la dernière ligne

Merci beaucoup ! La commande openRaster marche très bien, mais pas la commande closeRaster :

File "", line 7
instRegistry.removeMapLayer(couche[0].id())
^
IndentationError: expected an indented block

Je ne m'y connais pas en langage python, pourriez-vous me dire où est l'erreur dans cette ligne ? j'ai copié collé votre texte du tuto... Toutes mes données sont sur mon disque d (pas en réseau) donc ça ne doit pas être dû à ça...

Merci !

IndentationError

Bonjour

Il faut que cette instruction instRegistry.removeMapLayer(couche[0].id())

soit indentée par rapport au bloc précédent : if len(couche) > 0:

c'est à dire qu'il faut une tabulation qui précède instRegistry.removeMapLayer(couche[0].id())

Et effectivement lorsqu'on fait un copier coller du script, l'indentation est supprimée, donc il faut rajouter la tabulation, au final, votre script doit ressembler à celui posté (avec les tabulations)

fabuleux !

Excellentissimement bien expliqué,
J'arrive à ouvrir des fichiers, mais pas à les fermer. Mais ce n'est pas très grave, j'ai l'essentiel !

Voici le message d'erreur qui apparaît :
Une erreur est apparue lors de l'exécution du code suivant :
import os
chemin=\\SERVEUR1\ResInt\EPG\SourcesCarto\Scan25_CG38_2012\SC25_TOUR_0840_6530_L93.ecw
nomCouche = str(os.path.splitext(os.path.split(chemin)[1])[0])
instRegistry = QgsMapLayerRegistry.instance()
couche = instRegistry.mapLayersByName(nomCouche)
if len(couche) > 0:
instRegistry.removeMapLayer(couche[0].id())
File "", line 2
chemin=\\SERVEUR1\ResInt\EPG\SourcesCarto\Scan25_CG38_2012\SC25_TOUR_0840_6530_L93.ecw
^
SyntaxError: unexpected character after line continuation character

Version de Python :
2.7.5 (default, May 15 2013, 22:44:16) [MSC v.1500 64 bit (AMD64)]

Version de QGIS :
2.2.0-Valmiera 'Valmiera', c3a2817

Chemin vers Python :
[... je vous ne fait grâce...]

Il faudrait peut être doubler

Il faudrait peut être doubler les antislash, car l'antislash est un caractère d'échappement qui permet de ne pas prendre en compte le caractère suivant, donc là python doit l'interpréter ainsi, donc il faudrait tenter avec \\

Et merci pour le commentaire, ça fait toujours plaisir !

Un petit peu plus à peu de frais

Bonjour,

J'ai essayé de faire cela pour un client et j'ai eu quelques problèmes de chemin relatifs sous Windows et de fichiers très nombreux.

Pour les fichiers nombreux, la commande écrite par l'outil de QGIS n'est pas optimale. Il vaut mieux appelé l'outil gdaltindex ( disponible dans le répertoire bin du rep d'installation de QGIs) sous une forme "c:/...gdaltindex.exe" toto.shp ./repDalles/*.tif. En faisant cela, l'attibut location est en position relative par rapport au SHP

J'ai aussi un peu amélioré le script pour l'ouverture lors que l'on a des fichiers relatifs. J'ai ajouté la fonctionnalité qui fait que le script revient sur la couche du tableau d'assemblage après chaque ouverture.

Le voici :

import os
from qgis.utils import iface
p=os.path.dirname(iface.activeLayer().source())
chemin=os.path.join(p,'[% "location" %]')
nomCouche = str(os.path.splitext(os.path.split(chemin)[1])[0])
qgis.utils.iface.addRasterLayer(chemin,nomCouche)
nbLayer=(qgis.utils.iface.mapCanvas().layerCount())
calqueaActiver=qgis.utils.iface.mapCanvas().layer(nbLayer-1)
qgis.utils.iface.setActiveLayer(calqueaActiver)

Merci pour cette piste

Merci Ludovic pour cette piste. Ca fait un moment que je me demandais comment contourner le fait de devoir noter sur papier l'emprise de mon périmètre pour n'aller récupérer que les bonnes dalles et là, tu m'apportes cette astuce. Merci beaucoup.
Par contre, je l'ai un peu modifié, dans un premier temps, comme l'a fait le précédent commentateur car j'utilise aussi la grille issue de Image Boundary mais aussi pour avoir un comportement proche de Show/Hide Image (c'est-à-dire pouvoir importer plusieurs dalles à la suite sans devoir sélectionner la couche catalogue après chaque import et les rendre visibles par défaut).
Je précise que je n'y connais pas grand chose en python, si ce n'est (pour l'instant) que modifier des variables ici et là; mon code n'est peut-être pas optimisé mais il fait ce que je veux.

import os
macouche = qgis.utils.iface.activeLayer()
chemin='[% "Path" ||'/'||"IMAGE" %]'
nomCouche = str(os.path.splitext(os.path.split(chemin)[1])[0])
qgis.utils.iface.addRasterLayer(chemin,nomCouche)
monraster=qgis.utils.iface.legendInterface().currentLayer()
qgis.utils.iface.legendInterface().setLayerVisible(monraster, True)
qgis.utils.iface.legendInterface().setCurrentLayer(macouche)

Ce que j'aurais souhaité en plus, c'est :
- conserver le surlignage bleu sur la couche catalogue
- toujours comme avec Show/Hide Image, pouvoir rendre invisible la dalle si elle est déjà présente dans la couche lorsqu'on clique dans son emprise.
Mais bon, mes premières tentatives de code ayant échoué, je me contente pour l'heure de ce fonctionnement qui nous facilite ÉNORMÉMENT la tâche. Et en espérant que ces compléments puissent aider d'autres lecteurs.
Encore une fois, MERCI!

Bravo!

Alors là, je dis bravo et surtout un grand merci!
Ca marche et même très bien, l'ergonomie est également impeccable.
Merci d'avoir fait un tuto aussi détaillé et facile à suivre/appliquer.
C'est donc officiel, je n'ouvre plus QGis 1.8!
J'imagine que ça risque d'en dépanner plus d'un.

Juste un petit détail, je n'ai pas réussi à utiliser l'index de tuiles. J'ai une erreur: "Unable to find field `location' in DBF file `C:/DATA QGIS/Catalogues/Cat_Ortho_80.shp'". Je ne comprends pas comment QGIS ne peut pas trouver un champs dans un fichier dbf qu'il est justement supposé créer. Je sèche.
J'ai contourné ce problème en utilisant Image boudary: j'ai ouvert la table attributaire de la grille crée et utilisé la calculatrice afin de créer un nouveau champs contenant les champs 'PATH' et 'IMAGE' concaténés( "PATH" ||'/'||"IMAGE"). Ce champs contient donc le chemin complet des dalles Ortho. Champs que j'ai appelé "CHEMIN" et qui remplace "location" dans [% "location" %]

Encore merci !

Poster un nouveau commentaire

Le contenu de ce champ sera maintenu privé et ne sera pas affiché publiquement.