Generation de paysage aleatoire par collage de photographies

De Ensiwiki
Révision de 15 juin 2010 à 07:50 par Fuzierc (discussion | contributions) (Mise à niveau des luminosités)

Aller à : navigation, rechercher

Projet de spécialité 2A Image

Guillaume Bron - Christophe Fuzier

DEFINITION DU SUJET

Le sujet consiste à développer des outils permettant l'intégration réaliste d'un élément d'une image dans une autre, puis à les appliquer à la génération aléatoire de paysages par mélange d'images.

Nous avons travaillé pour un artiste, Pierre Berger, président de l'association « Les Algoristes ».

MELANGE REALISTE DE PHOTOS

Mise à niveau des luminosités

La mise à niveau de la luminosité d'une image permet d'adapter la répartition des luminosités d'un objet au fond sur lequel on le colle.

Pour réaliser cette mise à niveau, on a d'abord besoin d'égaliser l'histogramme du fond et de l'objet.

L'égalisation d'histogramme d'une image consiste à ajuster le contraste en "étalant" l'histogramme. Concrètement pour cette image (avec un histogramme relativement concentré) :

Paysage non egalise.jpg, on obtient : Paysage egalise.jpg

Pour obtenir de bons résultats, il faut travailler en HSV (et non en RGB, car on dégrade alors les couleurs). L'égalisation d'histogramme consiste ensuite à égaliser seulement la composante V (celle de la luminosité), au lieu d'égaliser les trois composantes R, G et B.



Nous allons maintenant expliquer l'utilisation que l'on fait de cette égalisation dans notre programme. Nous avons en entrée un fond (le paysage de fond), et des objets que l'on insère ensuite par collage. Le problème est que la luminosité de tous ces composants (fond et objets) est très différente. Il faut donc égaliser les luminosités entre les différents éléments pour que le collage soit réaliste. On fait donc une égalisation pour le fond et pour les différents objets. Ceci étant fait, tous les éléments ont à peu près la même luminosité, mais le fond n'a plus la même luminosité qu'avant (typiquement, si l'on insérait des objets dans le paysage non égalisé précédent, on aurait un paysage final avec un fond comme celui du paysage égalisé, alors qu'on voudrait garder le brouillard du paysage non égalisé). Il est donc nécessaire de faire, en plus du traitement précédent, une égalisation inverse conditionnellement au fond, que l'on applique à toute la scène pour redonner la luminosité du fond initial à toute la scène.

Pour réaliser cette égalisation inverse, on va stocker lors de l'égalisation du fond un tableau de conversion qui à une valeur de V dans le fond égalisé associe la valeur de V correspondante dans le fond original. Il reste encore un problème à régler : certaines valeurs de V ne sont pas présentes dans le tableau de conversion, mais seront présentes dans l'image finale avec tous les objets. Nous avons décidé d'interpoler de manière linéaire les valeurs manquantes de V. Ainsi, nous avons un tableau de conversion pour toutes les valeurs de V, et l'égalisation inverse est possible.


Voici un résultat obtenu avec notre programme :

paysage sans mise à niveau des luminosités

Paysage sans modification luminosite.jpg

paysage avec mise à niveau des luminosités

Paysage avec modification luminosite.jpg


On voit clairement que les deux voitures et les arbres sont devenus plus sombres, pour s'adapter à la luminosité faible du paysage.

Transfert de couleurs

Nous nous sommes appuyé sur un article de recherche pour effectuer cette modification de style (« Color Transfer between Images » de Erik Reinhard, Michael Ashikhmin, Bruce Gooch and Peter Shirley).

Voici un exemple de transfert de couleurs d'une image à une autre :

Etant donné en entrée cette image :

Mer.bmp

on veut lui transférer les couleurs de cette image :

Mer 2.bmp

Le résultat obtenu est alors celui-ci :

Mer modifie.jpg

Nous avons implémenté la solution proposée dans cet article. L'idée de base consiste à trouver un espace autre que celui de RGB et qui correspond mieux au système visuel humain. Cet espace est l'espace LAB. L'autre avantage de cet espace est que les trois composantes sont décorrélées, ce qui permet de les traiter séparément et donc de simplifier la méthode de correction de couleur décrite dans l'article. Les calculs effectués sur les composantes LAB sont basés sur une analyse statistique de l'image (pour plus de détails, aller consulter l'article ).


Concernant l'utilité de cette transformation d'image pour notre sujet, on peut remarquer que le fait de donner les couleurs du fond au paysage contenant le fond en question et les objets s'est souvent avéré être une bonne solution qui donnait des résultats satisfaisant (la correction de luminosité ne devenait souvent même plus nécessaire).

Traitement des contours

Un autre problème qui se présente quand on colle un objet dans un fond est celui des contours, qui sont très nets et affectés par le fond duquel l'objet a été découpé. Après une tentative infructueuse d'implémentation de l'algorithme du Poisson Image Editing, nous avons choisi d'utiliser le lissage des contours pour remédier à ce problème. Il s'agit d'appliquer à l'image obtenue par collage un flou le long des contours de l'objet. Pour cela, il faut définir ces contours à l'aide d'un masque. Ensuite, nous lissons les contours du masque, ce qui permet d'effectuer les calculs à la création du masque et d'avoir ensuite un affichage des objets sans surcoût. On pourrait penser à un flou gaussien sur le masque, mais cela ne donne pas les résultats voulus car certaines parties de l'image collée, initialement masquées, deviennent visibles à cause de ce flou. Il faut donc appliquer aux contours du masque une rampe vers l'intérieur, à l'aide de plusieurs érosions dont le nombre dépend du niveau de lissage souhaité.

Nous avons implémenté un éditeur de masque évolué qui permet de définir des contours, de choisir les parties de l'image à masquer et les parties à conserver, et de régler les paramètres de lissage. Voici quelques captures d'écran de cette application.

DefContours Arbre.bmp DefContours Arbre 2.bmp DefMasqueBin Arbre.bmp DefLissage Arbre.bmp DefLissage Arbre 2.bmp Masque Arbre.bmp

DefContours Maison2.bmp DefMasqueBin Maison2.bmp DefLissage Maison2.bmp Masque Maison2.bmp

GENERATION DE PAYSAGES ALEATOIRES PAR COLLAGE

On va s'intéresser dans cette partie à savoir comment créer des paysages aléatoires avec notre programme. Un paysage se compose de deux parties : le fond du paysage et les objets.

Définition du fond du paysage avec notre programme

L'utilisateur choisit une image (jpg, bmp, ...) qui sert à définir le fond du paysage. Ensuite, via un outil que l'on a développé, l'utilisateur doit définir les 4 composantes du paysage qui sont :

- La terre

- L'eau

- Le ciel

- Vide

Ces 4 composantes seront utiles pour le programme lorsque celui-ci aura à générer un paysage. Quand l'utilisateur définira ses objets, il devra dire où ces objets peuvent se placer (voir la section suivante pour plus de détails sur la création des objets). Sur les composantes "Vide", aucun objet ne peut être placé.

Nous avons créé une application qui permet de définir ces régions et d'enregistrer les paramètres dans un fichier qui peut ensuite être réutilisé par le générateur de paysages pour placer les objets aux endroits appropriés dans le fond.

Voici quelques captures d'écran de cette application:

DefRegions Verdure.bmp DefTypeRegions Verdure.bmp TypeRegions Verdure.bmp

Définition des objets du paysage avec notre programme

1) Les archétypes

On commence par définir des archétypes tels qu'un arbre ou une voiture. Il peut exister différents modèles pour un même archétype, tout comme il existe différents types d'arbre et différents modèles de voiture. En définissant un archétype, on lui donne un label, comme "Arbre" ou "Voiture", un nombre minimal et un nombre maximal d'exemplaires devant apparaître sur les paysages générés et une probabilité d'apparition. Cela donne un contrôle plus ou moins précis, suivant les souhaits de l'utilisateur, sur la composition des paysages produits. On indique également si les objets instances de cet archétype pourront se situer sur la terre, sur l'eau ou dans le ciel.

On pourra objecter que pour un même type d'arbre, il existe de nombreux "modèles" différents. Il n'y a pas deux platanes identiques dans la nature, par exemple. Si l'on veut en tenir compte, il suffit de pousser plus ou moins loin la définition des archétypes. Ainsi, au lieu de définir un archétype pour les arbres, on pourra définir des archétypes pour les platanes, les chênes, etc., avec plusieurs images et paramètres pour chacun d'eux.


2) Les modèles

Après avoir défini un archétype, on en définit un ou plusieurs modèles. Pour cela, il faut une image de l'objet et un masque en définissant les contours, lequel pourra être créé le plus précisément possible avec un éditeur de masque que nous avons développé. Il faut préciser à quel archétype appartient l'objet, en spécifiant son label. On répartit ensuite les probabilités d'apparition entre les différents modèles d'un même archétype. Pour chaque objet, on dispose aussi d'un facteur de remise à l'échelle, compte tenu du fait que les tailles des objets sur les différentes images utilisées ne sont pas nécessairement cohérentes entre elles. On peut aussi définir l'origine de l'objet. Pour placer un objet dans le fond, on tire un point aléatoire dans le ciel, l'eau ou la terre en fonction des endroits où peut apparaître cet objet. C'est en ce point que sera placée l'origine de l'objet. Ainsi, pour un arbre par exemple, on définit usuellement l'origine en bas du tronc, qui sera en contact avec la terre.

Résultats

Voici deux exemples de paysages obtenus à partir des mêmes images. Verdure 1.jpg

Verdure 2.jpg


Voici trois autres exemples de paysages obtenus à partir des mêmes images. Ville.jpg

Ville 2.jpg

Ville 3.jpg

Conclusion

La prise en main de Processing a été rapide et facile. Cet outil est très bien conçu pour des artistes, la documentation disponible sur le site est claire et contient de nombreux exemples d'utilisation. Cependant, nous avons rencontré des difficultés liées au fait que nous avions peu d'informations précises sur le fonctionnement technique de Processing : plusieurs méthodes (setup, draw, keyPressed, etc.) sont appelées automatiquement par Processing et l'on ne sait pas exactement à quels moments et dans quel ordre cela se passe.

De plus, ce projet nous a appris que Processing n'était pas fait pour de gros projets : par exemple, tous les fichiers de code doivent se trouver dans un même dossier portant le nom de l'un d'eux, ce qui n'est pas du tout pratique pour structurer les fichiers et pour partager du code entre plusieurs applications. Ce logiciel n'est pas fait non plus pour faire du calcul: il est lent et il y a peu de bibliothèques à disposition.

Il reste cependant agréable d'utilisation.

Une autre difficulté est venue de ce que nous avons perdu du temps au début du projet, le sujet n'étant pas défini au départ et ayant été modifié en cours de route. Nous avons donc appris à nous adapter à ces aléas. Il a également été très enrichissant pour nous de travailler avec une personne venant d'un milieu différent du nôtre, en l'occurrence avec un artiste.