Ressources
Nous utiliserons pour les RASTER la même installation de PostGIS documentée dans un module précédent ainsi que la même base de données formation .
Sous Windows, il est recommandé de modifier la variable système nommée
Pour le configurer, ouvrir le menu démarrer et chercher « propriétés système » puis l’ouvrir. Dans l’onglet « Paramètres systèmes avancés », cliquer sur « Variables d’environnement... ». Puis trouver la variable
Il faut alors ajouter dans la valeur le chemin vers les binaires exécutables de PostgreSQL en séparant par un point virgule. Mais comment connaître le chemin ? Les captures ci-dessous font état de « C:\Program Files\PostgreSQL\9.3\bin » mais la version peut être différente et il n’est pas exclus que l’installation soit dans un autre répertoire.
L’astuce consiste à chercher pgAdmin via la recherche du menu démarrer pour identifier son emplacement, qui est normalement le même que les autres utilitaires comme raster2pgsql.exe et psql.exe dont nous avons besoin.
Quand pgAdmin est trouvé, cliquer avec le bouton droit de la souris puis Propriétés . Il faut alors copier le répertoire indiqué par « Démarrer dans ».
Puis coller le répertoire dans la valeur de la variable Path après un point-virgule pour séparer des chemins pré-existants. Attention à bien enlever les guillemets.
Créons à présent notre répertoire de travail pour l’importation des rasters. Dans les captures suivantes, il s’agit de C:\Rasterwork , mais tout autre emplacement convient également. Une fois le dossier créé, il faut copier le raster des données sources QGIS\BCD_ALTI\MNT\MNT_25M_asc.asc en le renommant en mnt_25m.asc (avec l’explorateur Windows, faire un copié-collé ou bien un glissé-déplacé avec le bouton du milieu, pour copie et non déplacement).
Raster2pgsql est l’utilitaire fourni avec PostGIS pour importer un jeu de données raster dans la base PostgreSQL.
À l’instar de shp2pgsql, raster2pgsql ne se connecte pas directement à la base, mais produit les requêtes SQL qui créent le(s) raster(s) selon les options paramétrées. Ces requêtes SQL peuvent être enregistrées dans un fichier .sql qui sera ensuite exécuté par un client tel que psql ou pgadmin.
Pour commencer, ouvrir l’interpréteur de commandes (shell). Sous Windows, il s’agit d’un programme nommé cmd.exe qu’on peut lancer en utilisant le menu démarrer puis exécuter et taper cmd .
Dans l’invite de commande, faire « cd C:\Rasterwork » (ou autre chemin) pour se placer dans le répertoire de travail, puis exécuter dir pour lister les fichier et vérifier qu’on a bien notre fichier raster mnt_25m.asc .
Il faut ensuite appeler le programme raster2pgsql.exe qui a été installé avec PostGIS. Si la variable Path n’a pas été modifiée (comme indiqué plus précédemment), il faudra l’appeler par son chemin complet, qu’on obtiendra en faisant une recherche dans « C:\Program Files ».
Depuis l’invite de commande, on lance tout d’abord raster2pgsql sans argument pour vérifier que la commande est bien trouvée, et obtenir de l’aide sur son utilisation.
À présent, nous allons utiliser raster2pgsql pour importer le modèle numérique de terrain de la commune de la flèche nommé mnt_25m.asc du répertoire de travail. Pour générer le fichier SQL, exécuter : « raster2pgsql mnt_25m.asc >mnt_25m.sql ».
Pour effectuer l’importation proprement dite dans la base PostGIS, il faut ensuite exécuter le SQL dans la base concernée. On peut théoriquement utiliser pgadmin et ouvrir le fichier SQL dans la fenêtre SQL (fichier → ouvrir ), mais cette approche se révèlera limitée pour des fichiers SQL trop lourds, ce qui sera souvent le cas : pour un fichier raster donné, le fichier SQL pèse en général 2 à 3 fois plus lourd, soit 100 Mo ou 200 Mo pour un raster de 50 Mo telle que l’orthophoto 0468_6739-2040.tif . Pour cette raison, on utilisera le client psql.exe en ligne de commande.
Il faut donc appeler le client psql pour la base de données formation en indiquant le fichier mnt_25m.sql , comme ceci :
psql.exe -h localhost -U postgres -W -d formation -f mnt_25m.sqlUn mot de passe est demandé : c’est toujours celui de l’utilisateur postgres , c’est-à-dire postgres s’il n’a pas été changé.
La commande ne doit retourner aucune erreur. On peut alors vérifier avec pgAdmin que la table mnt_25m a bien été créée dans la base.
Se rendre dans pgAdmin et afficher le contenu
de la vue raster_columns
qui doit contenir une seule ligne, représentant le raster importé.
Cette vue est l’équivalent de la vue geometry_columns pour les rasters.
Pour l’instant, la plupart des colonnes sont vides concernant le raster importé, ce qui empêche son exploitation avec des outils externes tels que gdalinfo ou QGIS. De plus, l’identifiant de référence spatiale (SRID) n’a pas été précisé lors de l’import et n’est donc pas renseigné, ni dans les contraintes, ni dans le raster lui-même (colonne rast de la table mnt_25m ).
Nous allons utiliser la fonction UpdateRasterSRID pour mettre à jour le SRID. Le système de projection du MNT est le Lambert93, qui porte le numéro 2154 d’après la table spatial_ref_sys .
Dans la fenêtre SQL de pgAdmin, nous exécutons donc :
SELECT UpdateRasterSRID(’mnt_25m’, ’rast’, 2154)
À présent, nous allons ajouter toutes les contraintes pour rendre le raster exploitable par les outils externes. La fonction AddRasterConstraints fait cela automatiquement. Nous devons l’appeler comme ceci :
SELECT AddRasterConstraints(’mnt_25m’, ’rast’)
Retournons alors dans la vue raster_columns et rafraîchissons-la (F5). On obtient les valeurs suivantes :
Contrairement aux données vecteurs qui sont unitaires (un vecteur est un objet en soi et chaque enregistrement d’une table vecteur a son vecteur spécifique, même s’il peut s’agir d’un MULTI-vecteur), la donnée raster peut se répartir en dalles pour des traitements plus efficaces. Le raster est ce qu’on appelle un « raster coverage », en Français « couverture raster », qui peut éventuellement comporter des trous.
C’est pourquoi, pour un raster d’une certaine taille, comme ceux qu’on manipule dans ce chapitre, un importera le raster sous forme de dalles qui font chaun l’objet d’un enregistrement spécifique dans la table. C’est la table toute entière qui représente le raster.
Grâce à la fonction ST_Tile (fournie à partir de PostGIS version 2.1), il est possible de générer une couverture raster avec tuilage régulier à partir d’un raster non-tuilé. Ceci n’est pas couvert par ce module d’introduction : on utilisera à la place l’option -t de l’utilitaire d’importation raster2pgsql pour générer un raster tuilé directement à l’import.
Un raster est une grille de points régulièrement alignés dans une étendue géographique donnée. La résolution représente le nombre de points par unité géographique. Plus la résolution est grande, plus les calculs sont détaillés et plus l’affichage pourra être fin
(non pixellisé).
Or la résolution a un coût : un grand nombre de points signifie un poids important de données pour l’échange, ce qui peut être inutile lorsqu’on manipule le raster à petite échelle.
Pour cette raison, il est d’usage pour les rasters en général, d’utiliser des miniatures conjointement au raster d’origine. Le logiciel SIG saura sélectionner la miniature la plus adaptée pour ses traitements, ou le raster d’origine si nécessaire.
On parlera alors de structure pyramidale, où le raster donné est accompagné de ses miniature ½, ¼, 1/8, etc. Cette façon de faire est habituelle pour le format TIFF qui peut contenir ses miniature à l’intérieur du même fichier. D’autres stratégies offertes par les SIG consiste à générer des miniatures externes
: un .png
par exemple sera décliné en plusieurs fichiers.png
dans le même répertoire, représentant chacun une miniature donnée.
PostGIS RASTER permet de gérer des miniatures à l’intérieur de la base de données. La convention est la suivante : pour une table raster donnée, on maintient une table nommée o_N_raster , où raster est le nom de la table raster source et N le facture de miniature (2 pour ½, 4 pour ¼, etc.).
La vue raster_overviews liste pour chaque raster les miniatures disponibles. Ceci est possible car chaque miniature de raster (qui est elle-même un raster) définit une contrainte nommée enforce_overview_rast qui indique de quel raster source il est une miniature.
C’est grâce à cette vue raster_overviews que les outils externes savent comment exploiter les miniatures pour un raster donné.
À partir de la version 2.2 de PostGIS, la fonction ST_CreateOverview permet de générer des miniatures automatiquement (avec les bonnes contraintes) pour un raster existant. Nous n’allons pas l’utiliser ici. À la place, nous allons utiliser l’option -l de l’utilitaire raster2pgsql pour générer les miniatures directement à l’import.
Nous allons ré-importer notre modèle numérique de terrain en tenant compte des remarques précédentes :
De plus, il nous faut supprimer le raster existant pour le ré-importer : nous pourrons le faire manuellement dans pgAdmin, mais l’option -d le fera pour nous.
Dans l’invite de commande de Windows (cmd.exe), nous allons donc exécuter :
raster2pgsql -d -s 2154 -C -t auto -l 2,4 mnt_25m.asc >mnt_25m.sqlLe fichier SQL ainsi généré est prêt à être exécuté dans la base formation , comme précédemment :
psql -h localhost -U postgres -W -d formation -f mnt_25m.sql
Renommer un raster dans la base se fait de la même façon que pour les vecteurs : en renommant la table SQL :
ALTER TABLE table_name RENAME TO new_table_name
Supprimer un raster se fait de la même façon, comme pour toute table PostgreSQL :
DROP TABLE table_name
La table peut être visualisée dans pgAdmin comme tout autre table : clic droit sur la table puis « Afficher les données » → « Visualiser toutes les lignes » (ou en utilisant l’icône de la barre d’outils).
Attention : avec cette méthode, pgAdmin récupère et affiche dans le tableau la totalité du raster sous forme binaire, ce qui est particulièrement lourd, et pour la récupération des données (de la base par pgAdmin), et pour l’affichage de la fenêtre. Ceci peut paralyser pgAdmin pendant un certain temps et c’est pourquoi cette méthode n’est pas recommandée.
À la place, on inspectera la table par des requêtes SQL en utilisant des fonctions PostGIS ST_* pour inspecter les propriétés souhaitées du raster.
Les fonctions ST_Width et ST_Height permettent respectivement de calculer la taille d’un raster. Pour connaître la hauteur et la largeur totale de notre converture raster, nous exécutons la requête suivante :
SELECT
ST_Width
(
ST_Union
(rast)),
ST_height
(
ST_Union
(rast)) FROM mnt_25m
La fonction ST_Summary retourne quant à elle un résumé textuel sur le raster (dimensions, nombre de canaux et étendue géographique) ainsi que le détail pour chaque canal (nous aborderons ultérieurement le sujet des canaux).
SELECT
ST_Summary
(
ST_Union
( rast ) ) FROM mnt_25m
Contrairement aux géométries, les rasters sont des grilles de points et n’ont pas de coordonnées géographiques explicites pour chacun des points : c’est l’ordonnancement régulier des points qui permet de faire l’équivalence entre un point du raster et son emplcement géographique, grâce aux informations de géoréférencement.
Le géoréférencement définit les coordonnées géographiques de l’origine des pixels ainsi que la dimension géographique du pixel (identique pour tous les pixels). Un paramètre de transvection X et Y est également possible (skewX et skewY en Anglais), mais nous ne l’aborderons pas ici.
La fonction ST_GeoReference permet de récupérer les informations de géoréférencement du raster, au format World File [http://fr.wikipedia.org/wiki/World_file] selon 2 variantes : GDAL ou ESRI.
Essayons :
SELECT
ST_GeoReference
(
ST_Union
( rast ), ’GDAL’ ) FROM mnt_25m
Le format de géoréférencement GDAL se structure en 6 lignes, ainsi :
Pour davantage d’informations, nous nous référerons à la documentation : http://postgis.net/docs/RT_ST_GeoReference.html
Les fonctions ST_PixelWidth et ST_PixelHeight calculent respectivement la hauteur et la largeur du pixel en coordonnées géographiques (selon le référentiel spatial – SRID – du raster).
Exemples :
SELECT
ST_PixelWidth
(
ST_Union
( rast ) ) FROM mnt_25m
SELECT
ST_PixelHeight
(
ST_Union
( rast ) ) FROM mnt_25m
À l’instar des vecteurs, on utilise la fonction ST_Envelope pour obtenir l’étendue géographique d’un raster sous forme de géométrie (WKB). Pour l’obtenir en tant que BBOX lisible, on l’imbriquera dans la fonction box2d comme ceci :
SELECT box2d(
ST_Envelope
(
ST_Union
( rast ) ) ) FROM mnt_25m
Un raster est une grille régulière de valeurs, il est possible de calculer des statistiques sur les valeurs.
La fonction ST_ValueCount fait l’inventaire des valeurs présentes dans le raster et compte le nombre de leur occurrence respective.
SELECT
ST_ValueCount
(
ST_Union
( rast ) ) FROM mnt_25m
Le résultat précédent comporte 79 enregistrements (79 lignes sont indiquées dans la barre de statut), ce qui signifie 79 valeurs différentes dans le raster. Le résultat nous montre que :
etc. En défilant vers le bas (non visible dans la capture ci-dessus), on atteint la dernière valeur qui vaut 103, au nombre de 27 : 27 pixels portent la valeur 103.
La fonction ST_ValueCount accepte un argument optionnel de type ARRAY pour ne compter que certaines valeurs, comme ceci :
SELECT {fnrt ST_ValueCount}( {fnrt ST_Union}( rast ), ARRAY[24,25,103,104] )
FROM mnt_25m
Le résultat précédent indique entre autres qu’aucun pixel ne porte la valeur 24, ce qui est cohérent avant le résultat global de ST_ValueCount qui indiquait 25 comme la plus petite valeur du raster.
La fonction ST_ValueCount peut aussi être appelée pour compter le nombre de pixels dont la valeur s’approche d’une valeur donnée (comme un arrondi) :
SELECT
ST_ValueCount
(
ST_Union
( rast ), 1, 30 ) FROM mnt_25m
Il existe d’autres arguments à cette fonction, comme l’arrondi. Se référer à la documentation [http://postgis.net/docs/RT_ST_ValueCount.html] pour plus de détails.
La fonction ST_SummaryStats retourne un résumé statistique des valeurs d’un raster, qui sont dans l’ordre :
Pour connaître notre raster mnt_25m , exécutons :
SELECT
ST_SummaryStats
(
ST_Union
( rast ) ) FROM mnt_25m
Nous retrouvons les valeurs minimale de 25 et maximale de 103 que ST_ValueCount avait retournées. Il y a 160 801 valeurs différentes, la somme est de 9 648 253, la moyenne de 60,0012 environ et l’écart-type de 25,7133 environ.
Enfin, la fonction ST_Histogram calcule un histograme des valeurs en autant de classes que donné en argument. Elle retourne un enregistrement pour chaque classe avec la valeur minimale, la valeur maximale, le nombre de valeurs dans la classe et le pourcentage par rapport à la population totale des valeurs.
SELECT (stats).*
FROM (SELECT {fnrt ST_Histogram}( {fnrt ST_Union}( rast ), 1, 5 ) as stats
FROM mnt_25m) AS q
L’argument 1 indique le canal à traiter. mnt_25m est un raster à 1 seul canal, alors la question ne se pose pas. Les rasters multi-canal seront traités plus loin dans le module.
La requête comporte une sous-requête car la fonction
ST_Histogram
retourne des enregistrements complets. L’expression (stats).*
permet d’extraire ces sous-colonnes
pour en faire des colonnes normales
(c’est-à-dire : de « premier niveau »).
À l’instar de l’index spatial des vecteurs, on utilisera des index spatiaux sur l’étendue géographique de chaque tuile de raster, afin d’optimiser dans les requêtes des fonctions comme ST_Intersects ou l’opérateur &&.
Pour ce faire :
CREATE INDEX mnt_25m_rast_gist_idx ON mnt_25m
USING GIST ({fnrt ST_ConvexHull}(rast))
QGIS est capable d’accéder aux rasters de PostGIS, implicitement à travers GDAL. Pour ajouter une table comme couche raster, on se servira du gestionnaire de bases de données (DB Manager), une extension standard, activée par défaut, et disponible sous le menu « Base de données » de QGIS.
Attention : sous Linux, un bug empêche les rasters de s’afficher correctement. Pour l’éviter, il faut lancer QGIS dans la locale
de base plutôt qu’en Français :
$ LC_ALL=C LANG=C LANGUAGE=C qgis
Ouvrir le gestionnaire de bases de données puis dans l’arbre, sélectionner PostGIS puis la base formation : les tables sont listées et celles qui propose un raster ont une icône qui les distingue :
Cliquer sur mnt_25m pour connaître les détails : on apprend qu’il y a 25 enregistrements, que le référentiel spatial est « RGF93 / Lambert-93 (2154) »… Faire défiler pour connaître les champs, les contraintes et les indexes.
Pour ajouter la table en tant que couche raster au projet QGIS, faire un glissé-déposé de la table, depuis le gestionnaire de base de données vers la liste des couches QGIS, nous menant au résultat suivant :
On notera que l’affichage est d’autant plus rapide que les miniatures o_2_mnt_25m (facteur ½) et o_4_mnt_25m (facteur ¼) sont automatiquement exploitées par QGIS, notamment à petite échelle.
On trouvera dans les propriétés de la couche, différentes informations :
adressede la couche du point de vue de GDAL, une chaîne de texte du type « PG : dbname=formation host=localhost user=postgres password=postgres [...] ». C’est l’argument à copier-coller pour l’exploitation du raster avec les outils GDAL, tel que gdalinfo , gdal_translate , etc.
Jusqu’ici, nous avons travaillé avec un modèle numérique de terrain (MNT) qui ne comporte qu’un seul canal – on dit aussi « bande unique » –, c’est-à-dire que chaque pixel comporte une unique valeur.
Il est pourtant courant, avec les formats raster, de manipuler plusieurs valeurs par pixel. Il peut s’agir de valeurs dérivées ou de composantes d’imagerie. Pour une photo couleur, on utilise généralement 3 canaux qui encodent la luminosité des 3 couleurs de base du système additif : rouge, vert et bleu respectivement. Zéro représente « aucune luminosité » et 255 la valeur maximale « pleine luminosité ». Le blanc s’obtient par addition des 3 couleurs (255 ; 255 : 255), le jaune par addition de rouge et de vert (255 ; 255 ; 0), etc.
C’est ainsi qu’une photo est traitée en tant que raster, et c’est par ce mode de rendu que le raster est restitué en photo dans le rendu visuel. On notera à ce titre que le concept de couleur n’existe pas dans la donnée raster : on ne manipule pas des couleurs mais des canaux associés à chaque pixel, même c’est cela qui produit, in fine, les couleurs à travers le mode de rendu.
La fonction ST_NumBands retourne, pour un raster donné, le nombre de canaux disponibles :
SELECT
ST_NumBands
(
ST_Union
( rast ) ) FROM mnt_25m
Beaucoup de fonctions, dont ST_ValueCount et ST_Histogram , acceptent un argument nband de type nombre entier, optionel ou non selon l’ambiguité possible avec les arguments suivants. Cet argument indique le canal à utiliser par la fonction : il s’agit de son numéro, qui commence par 1 (premier canal = 1, second canal = 2, etc.).
Par ailleurs, la fonction ST_Band permet d’extraire un canal donné en tant que raster à canal unique. Ainsi les deux expressions suivantes sont équivalentes :
ST_ValueCount
( rast, 2, 42 )
Et :
ST_ValueCount
(
ST_Band
(rast , 2), 1, 42 )
Dans la première expression, ST_ValueCount est appelée pour chercher le nombre de pixels portants la valeur 42 dans le canal 2 du raster rast . Dans la seconde, ST_Band n’extrait que le canal 2 du raster rast , qui devient le canal 1 (unique) du raster retourné qui est alors passé à ST_ValueCount .
Importer dans PostGIS l’orthophoto QGIS/ORTHO_HR/0468_6739-2040.tif dans la table ortho avec les paramètres suivants :
Indice : le nom de la table peut être spécifié en second argument de raster2pgsql , après le nom du fichier.
Requête :
SELECT
ST_Width
(
ST_Union
(rast)),
ST_height
(
ST_Union
(rast)) FROM ortho
Requête :
SELECT box2d(
ST_Envelope
(
ST_Union
( rast ) ) ) FROM ortho
Requête :
SELECT {fnrt ST_PixelWidth}({fnrt ST_Union}(rast)),
{fnrt ST_PixelHeight}({fnrt ST_Union}(rast))
FROM mnt_ortho
SELECT sum(
ST_ValueCount
( rast, 3, 100 )) FROM ortho