Navigation dans des images très haute résolution

De Ensiwiki
Aller à : navigation, rechercher


Navigation dans des images très haute résolution
Projet Projet de spécialité 2A
Sous-projet Image
Étudiants Amaury BALLIET (MMIS-IRVM), Lucas BERTHOU (MMIS-IRVM), Wojciech KEDZIERSKI (ERASMUS)
Promo 2011
Encadrant François BERARD francois.berard@grenoble-inp.fr

Introduction

Les images très haute résolution sont particulièrement intéressantes car elles permettent de représenter une grande quantité d'information. Lorsque l'on souhaite accéder à une partie de cette information il est alors important que la navigation dans cette image soit aisée. Par exemple, si l'on possède une carte on peut vouloir n'en consulter qu'une partie, et si l'on souhaite prévoir un itinéraire il peut être intéressant de se déplacer dans la carte. Il en va de même si l'on souhaite naviguer au sein d'image satellite ou simplement d'images possédant beaucoup de détails.

Sujet

Image très haute résolution de l'Isère affichée sur quatre écrans 30"

L'objectif de ce projet de spécialité était de concevoir une application permettant une navigation fluide dans des images très haute définition. Nous souhaitions avoir à chaque instant le maximum de résolution c'est-à-dire que nous avons évité les affichages progressifs (utilisation d'une image de moindre résolution étirée). Enfin nous voulions utiliser une grande surface pour afficher cette image, à avoir quatre écrans 30".

L'intitulé de notre projet se trouve ici : http://brouet.imag.fr/fberard/ProjetImage/VeryHighDef

Contexte du travail

Ce projet à été réalisé au sein du LIG dans l'équipe IIH et nous avons été encadrés par François Bérard. Notre équipe était constituée de Amaury Balliet, Lucas Berthou et Wojciech Kedzierski.

Implémentation

Lors de l'élaboration de ce projet nous avons été amenés à faire différents choix d'implémentation dont les principaux sont détaillés ici.


Preprocessing

Découpage en petites images de 256 par 256 pixels

Les images très haute résolution sont composées plusieurs milliards de pixels, il serait donc assez naïf de penser charger toute l'image en mémoire vive pour n'en rendre qu'une partie. Notre stratégie a été de découper cette image en plusieurs images images appelées tiles. Seuls les tiles qui nous intéressent seront chargés en mémoire et affichés dans l'image.

Construction d'une pyramide de résolution

Pour accéder rapidement à différentes résolutions de l'image nous construisons, par subsampling gaussien, une pyramide de résolutions de l'image. À chaque niveau de cette pyramide nous sous-échantillonnons l'image de moitié c'est-à-dire que nous regroupons quatre tiles pour en obtenir un nouveau de moins bonne résolution. Nous itérons cette opération sur les tiles ainsi obtenus jusqu'à n'en avoir plus qu'un.

Grille dynamique servant au texturing

Pour afficher une partie de l'image nous construisons une grille initialement composée de carrés de 256 pixels de côté. Nous texturons ensuite cette grille avec les tiles correspondant à la résolution voulue. Pour se déplacer dans l'image nous appliquons une transformation affine à cette grille, ainsi lorsque nous dézoomons et que les carrés constituant la grille mesurent 128 pixels de coté nous changeons de niveau de résolution dans la pyramide : la grille est à nouveau formée de carrés de 256 pixels de côté que l'on texture avec la nouvelle résolution. Inversement lorsque nous zoomons nous changons de niveau de résolution dans la pyramide dès que les textures sont en taille réelle (256 pixels de coté). On s'assure ainsi d'être toujours au maximum de résolution.

Bandes Passantes

Nous avons effectué des benchmarks pour mesurer les diverses bandes passantes au sein de l'ordinateur et déterminer où se trouvaient les goulots d'étranglement : sans réelle surprise le transfert le plus coûteux en temps était celui du disque dur vers la mémoire vive. Pour accélérer ce transfert nous avons compressé les images en utilisant la zlib qui effectue une compression sans perte, ce qui était important au vu de la résolution des images que nous souhaitions à tout prix préserver. La décompression se faisait alors directement en RAM. Ce processus nous a permis d'avoir des textures décompressées directement en mémoire vive deux fois plus vite que si nous les avions chargées directement dans un format décompressé depuis le disque dur.

Architecture

Schéma de l'architecture client-serveur de notre programme

Notre programme se devait d'être multi-plateformes mais devait également tirer le meilleur parti de l'architecture sur laquelle il était exécuté. Nous avons donc opté pour une architecture basée sur le modèle client-serveur. Les clients seraient spécifiques à la plateforme sur laquelle ils seraient exécutés et pourraient bénéficier d'API spécifiques tandis que le serveur serait indépendant de la plateforme.

Dans le carde de notre projet nous avons implémenté deux client : l'un basé sur Glut (Windows, Linux, Mac OS) et l'autre en Cocoa (Mac OS) ayant l'avantage de gérer plusieurs écrans. Chacun de ces clients peut demander au serveur de se préparer à l'affichage de l'image ayant subit une transformation affine puis demande, pour chacun des écrans, d'afficher une sous-partie de cette image. En retour il obtient une ensemble de commande OpenGL qui résultent en l'affichage de la portion d'image voulue.

La partie "serveur" est composée de deux entité distinctes. L'une permet de créer et manipuler une grille sur laquelle nous plaquons des textures et l'autre gère efficacement l'utilisation de la mémoire (garbage collector, préchargement automatique de tiles, etc).

Gestion de la mémoire

Spirale

On veut accéder aussi rapidement que possible à la meilleure résolution possible. On veut absolument éviter d'avoir de la pixelisation ou de l'aliasing on doit donc être capable d'accéder très rapidement au images qui nous intéressent. La ressource étant limitée on ne peut pas charger toutes les images en mémoire vidéo ou même en mémoire vive. Il faut donc mettre dans un cache seulement une partie des tiles : ceux qui entourent l'écran et qui sont susceptible d'être affichés lors d'un déplacement. On prend également les tiles de résolution juste meilleure et juste inférieure afin de pouvoir les afficher si l'utilisateur zoom. Ce chargement de tiles se fait bien sur de façon asynchrone de sorte que l'utilisateur n'est pas ralenti dans sa navigation au sein de l'image.

Afin de ne pas faire exploser la mémoire nous avons également du implémenter un ramasse miettes. Mais contrairement aux ramasse miettes usuels, nous nous intéressons ici à la position du tile que l'on veut libérer par rapport à l'écran : on libère ainsi dans un premier temps la mémoire occupée par des tiles qui sont loin de l'écran et donc peu susceptibles de servir prochainement.

Afin d'avoir en premier lieu le centre de l'écran qui correspond à ce que l'utilisateur est en train de regarder on charge le cache en spirale : on par du centre et on charge toute les textures que l'on n'a pas en s'éloignant de plus en plus du centre.

Résultats Obtenus

Notre implémentation met en évidence l'impossibilité d'avoir à chaque instant la meilleure résolution possible, cependant on a une interaction fluide et une navigation rapide au sein d'une image très haute résolution. Notre implémentation est également extrêmement portable et flexible. En effet elle peut s'adapter à un nombre d'écran variable à une taille d'image différente la bordure des écran peut être intégrée ou non, et l'application est compatible Mac OS Linux et Windows. Nous avons de plus deux interfaces utilisateur : le clavier et la sourie d'une part mais également la DiamondTouch, surface tactile MultiPoint.

Pour aller plus loin il serait encore possible de paralléliser le chargement des textures en mémoire vidéo, d'utiliser des extensions d'OpenGL tel que les PBO ou de gérer d'autres moyens d'interactions, tel que la wii-mote ou l'optitrack.

Pour un aperçu des résultats obtenus voir la vidéo en annexe.

Compétences Utilisées

Lors de ce projet nous avons eu recours à des compétences techniques telles que nos connaissances en OpenGL, en algorithmique en traitement d'image, en parallélisation de taches (threads) ou encore en interaction homme machine mais aussi des compétences humaines pour la gestion de projet et la gestion d'équipe.

Annexe