Image analogies: transfert de styles entre images
Cadre du projet
Encadrant : Joëlle Thollot, Adrien Bousseau, Pierre BénardEtudiants : Rémi Fusade ; Orianne Siret ; Romain Ducout ; Jihene Haboubi ; Hanane Lamrani Abou El Assad
Presentation
Lors de ce projet, nous nous sommes penchés sur la conception d'images par analogie. Le principe de l'analogie est assez intuitif pour nous autres, humains, et permet à partir d'une transformation effectuée sur une image et l'image obtenue, de transformer de la même façon n'importe quelle autre image. Nous avons commencé par étudier l'article de recherche de Aaron Hertzmann, Charles E. Jacobs, Nuria Oliver, Brian Curless et David H. Salesin.Un algorithme d'analogie était ainsi déjà proposé avec quelques pistes et exemples d'application. Nous avons dès lors implémenté cet algorithme en C++ en essayant d'y apporter diverses optimisations. Puis, nous avons essayé de trouver d'autres applications, laissant dériver notre imagination débordante.
Sur cette page vous trouverez notre cheminement lors de ce projet: Tout d'abord une présentation de l'algorithme qui nous a permis d'obtenir nos résultats. Puis les résultats obtenus classés par domaines d'application. Enfin les problèmes rencontrés et suggestions par rapport à ceux ci. Finalement, les pistes de recherches futures.
Principe de l'algorithme
L'algorithme d'analogie d'images prend en entrée 3 images, une paire d'images sources, A et A', A' étant l'image A filtrée. On souhaite donc calculer une image B' à partir de l'image B tel que l'image B' se rapporte à B de la même manière que A' se rapporte à A.A chaque pixel d'une image, on associe un vecteur qui liste les informations utilisées par l'algorithme relatives au pixel, cela peut être les composantes RGB, la luminance ou la profondeur. Nous détaillerons plus loin l'utilité des informations et leurs influences sur le résultat. Par la suite, nous noterons A(p), A'(p), B(p) et B'(p) les vecteurs associés aux images, respectivement, A, A', B et B'. Il est important que les images A et A' aient la même taille et que les vecteurs soient identiques pour chaque pixel de chaque image.
Le principe de l'algorithme est simple, on parcourt un à un les pixels de l'image B et on cherche le pixel qui correspond dans l'image A. Le pixel à choisir est celui dont le voisinnage, à la fois dans A et A', est le plus près de celui de B et B'. Afin de capturer les motifs à différentes echelles, on utilise également une pyramide gaussienne et on effectue la recherche à la fois sur les voisinnages au niveau l et au niveau l-1. La synthèse des pixels de B' se faisant du dernier niveau de la pyramide (là où l'image est la plus petite) au premier niveau. Pour calculer la "distance" entre un point q de B et un point p de A, on construit 2 vecteurs, Fa(p) qui réunit les vecteurs des pixels concernés sur l'image A (le voisinage de p dans A, A' aux niveaux l et l-1) et Fb(x) qui réunit ceux de l'image B, on calcule ensuite la distance entre les deux vecteurs.
Le schéma suivant illustre les pixels utilisés lors du calcul de la distance entre les points p et q:
(p étant toujours un pixel de A et q de B)
- La recherche par force brute: Cet algorithme est utilisé pour la synthèse des pixels en bordure de l'image ainsi que pour la synthèse du dernier niveau de la pyramide de B'. Cette méthode construit le vecteur Fb(q) en fonction des limites de l'image, le voisinage pouvant être trop grand pour des pixels en bordure, et parcourt l'image A sur chaque pixel où le même espace de voisinage existe (c'est pour cela qu'il est utilisé aux bords de l'image). L'algorithme ne travaille pas au niveau infèrieur de la pyramide gaussienne et c'est pour cela qu'il permet de calculer B' au dernier niveau.
- L'algorithme de meilleure approximation: Cet algorithme recherche le meilleur pixel de A et A' dans toute l'image où le voisinage de q ne déborde pas de l'image. On utilise ici une bibliothèque nommée ANN (Approximate-nearest-neighbor) qui effectue cette recherche.
- L'algorithme de meilleure cohérence: Ce dernier algorithme est utilisé en supplément de l'algorithme de meilleure approximation, il limite la recherche du point de A aux points p correspondants aux voisins de q déjà synthétisés.
Vient alors la dernière étape de l'algorithme qui consiste à construire la valeur RGB des pixels de B' en fonctions du vecteur de pixel. Si le vecteur contient les valeurs RGB, alors il n'y a rien à faire, sinon, par exemple avec la luminance, on recalcule RGB a partir de la valeur de luminance et de la couleur d'un pixel.
Paramètres de l'algorithme
Cet algorithme peut s'adapter aux différentes applications que l'on souhaite en faire, plusieurs paramètres permettent de modifier le comportement de l'algorithme et ainsi d'obtenir des résultats différents. Voici la liste des paramètres de notre algorithme:- K : L'indice de cohérence. Plus il est élevé, plus l'image calculée B' contient d'éléments de l'image A'. Il faut le choisir assez grand (> 0.2) pour tout ce qui concerne la synthèse et le transfert de textures. Mais il doit être le plus petit possible si l'on ne souhaite pas que B' contiennent des "morceaux" de A' (par exemple dans le cas de certains transfert de styles) Figure 3: Exemples de dessin de texture. En prenant comme exemple une photo (A') et une segmentation de texture (A), l'algorithme produit une nouvelle photo texturée (B') dont les formes correspondent à une nouvelle carte de textures (B).
- L : Le nombre de niveaux des pyramides gaussiennes. La pyramide gaussienne d'une image est l'ensemble des images réduites (divisées par 2, par 4, par 8, etc...) de l'image originale. L'image de niveau 0 est l'image originale, l'image de niveau l est la réduction par 2 de l'image de niveau l. On les appelle "gaussiennes" car on applique un filtre gaussien pendant la réduction (chaque pixel de la nouvelle image est une combinaison de 9 pixels de l'image précédente). L'algorithme travaille d'abord sur les images de petite taille, puis passe aux images plus grandes. Cette méthode permet de détecter certaines formes qui sont plus grandes que le voisinnage considéré sur l'image originale, et qui deviennent plus petites si on réduit l'image.
- pk, gk : Ces paramètres correspondent à la taille du voisinage considéré, respectivement sur les images de taille l+1 et sur les images de taille l. Plus ce voisinage est grand, plus l'algorithme demande du temps à l'exécution, mais il peut détecter de plus grandes formes. L'algorithme tel qu'il est expliqué dans l'article de recherche correspond à pk=1 et gk=2, d'une manière plus générale, on utilisera souvent un rapport de 2 entre ces deux valeurs (même rapport qu'entre les tailles des images), mais nous l'avons généralisé pour n'importe quel autres paramètres (notamment: pk > gk).
- type : L'algorithme compare en permanence des pixels à d'autres pixels. Mais il existe plusieurs informations différentes sur chaque pixel, il faut donc choisir laquelle utiliser. Le plus souvent, la luminance (combinaison linéaire des RGB) suffit à donner de bons résultats. Mais parfois, la couleur devient indispensable. Le paramètre "type" offre donc plusieurs possibilités: LUM pour n'utiliser que la luminance, RGB pour n'utiliser que les canaux RGB, RGBLUM pour utiliser les deux, IQ pour n'utiliser que les composantes de couleurs (indépendament de la luminosié), DEPLUM pour utiliser la luminance et une information de profondeur, et enfin DEPRGB pour utiliser les canaux RGB et l'information de profondeur.
- Ad, Bd : Lorsque l'on veut rajouter une information sur la profondeur, il est nécessaire de rajouter des images en entrée de l'algorithme. Ad et Bd sont respectivement les cartes de profondeur de A et de B (la profondeur est le niveau de gris de l'image Ad/Bd).
- color : Il est possible de générer B' à l'aide des couleurs de B (transfert de style: l'image B' reste semblable à l'image B), ou bien à l'aide des couleurs de A' (synthèse de texture: l'image B' contient des textures de l'image A').
- remapping : Dans les cas où les images A et A' sont beaucoup plus claires ou beaucoup plus foncées que l'image B, l'algorithme n'obtiendra rien de bon, il est donc parfois nécessaire de ramener toutes les images à des luminosités semblables. L'option remapping permet d'effectuer ce pré-traitement.
- mosaic : Le résultat de notre logiciel est, par défaut, un fichier .tif contenant l'image B'. Mais il est parfois (souvent?) plus pratique de montrer les 4 images A, A', B, et B' dans un même fichier, ne serait-ce que pour les comparer, et vérifier que le résultat est bien celui attendu. L'option mosaic modifie donc ainsi le contenu du fichier de sortie.
Applications
L'algorithme d'analogie d'image fournit de très bons résultats dans des domaines d'application variés. Voici des applications que nous avons testées et qui offrent de bons rendus:- Filtres traditionnels et artistiques.
- Synthèse de textures.
- Augmentation de la résolution.
- Transfert de textures.
- Textures par nombres.
- Détection de contours.
- Profondeur de champ.
- Colorisation.
- Changements de couleurs.
Limitations
- Nous venons de voir qu'il est important et pas toujours évident de choisir pertinemment nos paramètres pour bien construire nos images. Cela prend donc du temps, il pourrait être intéressant d'automatiser ces paramètres en fonction du type de transformation que l'on donnerait en paramètre.
- Ressemblances: Afin de permettre à notre algorithme d'identifier la transformation effectuée entre A et A', celle ci doit être un minimum homogène sur l'image. On applique partout sur A la transformation pour obtenir A'. Si on transforme une image A en une image A' trop différente, on ne pourra appliquer cette transformation à B.
- Temps: Malgré les améliorations apportées à l'algorithme afin d'optimiser le temps de calcul des images
les images de grandes tailles prennent toujours beaucoup de temps à se construire.
=> on ne peut gagner sur l'ANN qui est optimal et que nous n'avons pas implémenté
=> Brute Force: Il s'agit d'une recherche brutale donc par conséquent,tous les calculs sont à faire, on ne peut faire beaucoup mieux, de plus il y a déjà quelques optimisations. Des pistes sont néanmoins possibles en optimisant l'accès aux informations ainsi que pour la construction des vecteurs.
=> BestCoherence => cette partie peut être optimisée mais il s'agit de la partie de l'algorithme dont le temps de calcul est presque négligeable comparé aux deux autres. Il ne serait donc pas forcément pertinent de chercher de ce côté. - Format des fichiers: Notre algorithme nécessite d'utiliser des images de type .tif. Il ne s'adapte en effet pas à d'autres formats. Il pourrait être intéressant de l'adapter pour les jpeg qui sont beaucoup plus utilisés.
Ouvertures
- Features: Tout d'abord, nous avons testé différentes caractéristiques pour remplir nos vecteurs: Rgb, iq, luminance, profondeur... Ajouter un nouveau type de caractéristiques est extrêmement facile dans notre code, il pourrait donc être intéressant de tester les effets d'autres caractéristiques.
- Afin d'affiner le calcul et de rendre un meilleur résultat, il serait possible de prendre plusieurs A et A' afin de donner à notre algorithme la possibilité de chercher le meilleur endroit analogue pour construire B' sur plusieurs images. Le résultat sera cependant plus long à calculer.
- Pour l'application Texture by Numbers, il existe une application permettant de modifier B et d'avoir B' en temps réel. Il pourrait être intéressant de la combiner à nos résultats, et peut être d'obtenir d'autres résultats en temps rêel.
- Il semble d'autre part naturel d'imaginer adapter cet algorithme à des synthèses d'images 3D. Et pourquoi pas de l'appliquer à des animations. Par exemple, un personnage en A statique, en A' dansant. En B un autre personnage fixe, et on serait capable de le faire danser !
- Enfin, en sortant complètement de notre support de travail, c'est à dire les images, nous pourrions imaginer travailler sur les sons et musiques et pourquoi pas créer des mélodies par analogie avec d'autres.
Téléchargements
- Image Analogies. Le code source de notre application
- La présentation PowerPoint du projet.