TP2 - Photographie algorithmique

Partie 0

Cette section consiste simplement en l'implémentation d'un masque flou. Pour obtenir le masque, l'image filtrée avec un flou gaussien est soustraite à l'image originale. Ce masque peut ensuite être additionné à l'image originale pour accentuer ses contours.

Image originale
Masque flou de rayon 10
Masque flou de rayon 20
Masque flou de rayon 30
Originale
Flou de rayon 5
Flou de rayon 10
Flou de rayon 15

Partie 1

Cette partie consiste à combiner les hautes fréquences d'une image avec les basses fréquences d'une autre de façon à créer dont la perception diffère selon la distance à laquelle elle est observée.

Pour récupérer les basses fréquences d'une image, il suffit de la filtrer avec un flou gaussian qui agit comme passe-bas. Le rayon du filtre est obtenu à partir de la fréquence avec l'équation: $$\sigma = \frac{1}{ 2 \pi f}$$

Pour obtenir un filtre passe haut, une image floué générée comme spécifié dans le dernier paragraphe (basse-bas) est soustraite de l'image entière (passe-tout).

Plutot que de vous éloigner de votre ordinateur, passer la souris sur les photos!

Image originale des basses fréquences
Image originale des hautes fréquences
Image hybride
Originale
Originale
Hybride

Il est intéressant de regarder le résultat dans le domaine des fréquences. L'effet du passe-bas sur la fft d'une image est qu'il vient réduire l'amplitude des fréquences en s'éloignant des axes. Le passe-haut vient réduire l'amplitude en s'approchant des axes de la fft. On peut y voir que l'image finale correspond comme prévu à la somme des basses fréquences de la première image et des hautes fréquences de la deuxième.

Basses fréquences
Hautes fréquences
Résultat
Basses fréquences
Hautes fréquences
Somme

Crédits supplémentaires

Différents types d'images couleurs avec photos personnelles

Voici d'autres exemples de montage de la sorte comprenant des photos personnelles prises avec l'appareil d'un téléphone Sony Xperia Z3 Compact.

Il est possible d'implémenter l'algorithme plus haut tout en gérant les couleurs, une seule modification doit être faite. En effet, les images développent des taches très saturées après l'opération. Cela est du au fait que les images en notations à virgule flottante ont une grande plage dynamique, ainsi, en sommant les deux images, un canal sort fortement de la plage [0, 1]. Limiter la valeur de chaque pixel (avec numpy.clip) entre 0 et 1 de l'image sommé suffit à régler le problème.

Image originale des basses fréquences
Image originale des hautes fréquences
Image hybride
Originale
Originale
Hybride
Originale
Originale
Hybride
Originale
Originale
Hybride
Originale
Originale
Hybride

Chacun de ces exemples est particulier et démontre un usage de cette technique:

Ce dernier exemple est particulièrement intéressant puisqu'il fonctionne très bien et n'a pas nécessité d'avoir une image n'ayant pas de détails en fond. Remarquez que même le reflet dans la table en verre varie selon la distance d'observation. Le truc est que les arrêtes des objets doivent correspondent autant que possible, cela a été atteint en redimessionnant et en recadrant l'une des images. Un désavantage de cette technique est que le bruit provenant du grain du mur a été largement amplifié. Pour mitiger le problème, un filtre bilatéral a été appliqué sur l'image donnant les hautes fréquences. Celui-ci préserve les arrête de l'objet tout en adoussissant le mur.

Les exemples démontrent que l'information sur les couleurs est particulièrement importante dans les basses fréquences. En effet, ce sont ces fréquences qui donnent la couleur moyenne de la scène.

Partie 2

Une pile gaussienne est une succession d'image filtrées avec des flous gaussiens d'amplitude croissante. L'effet est que plus on s'avance dans la pile moins les hautes fréquences sont conservées.

L'inverse est la pile laplacienne qui ne conserve que les hautes fréquences. La laplacienne de niveau \(x\) est obtenue en soustrayant la gaussienne de niveau \(x\) à la gaussienne de niveau \(x-1\).

Pile gaussienne de niveau 1
Pile gaussienne de niveau 2
Pile gaussienne de niveau 3
Pile gaussienne de niveau 4
Pile gaussienne de niveau 5
Pile laplacienne de niveau 1
Pile laplacienne de niveau 2
Pile laplacienne de niveau 3
Pile laplacienne de niveau 4
Pile laplacienne de niveau 5
Pile gaussienne de niveau 1
Pile gaussienne de niveau 2
Pile gaussienne de niveau 3
Pile gaussienne de niveau 4
Pile gaussienne de niveau 5
Pile laplacienne de niveau 1
Pile laplacienne de niveau 2
Pile laplacienne de niveau 3
Pile laplacienne de niveau 4
Pile laplacienne de niveau 5

Pyramide

Une alternative à la pile gaussienne est la pyramide gaussienne. La seule différence est que la résolution des images est divisé par quatre (2x moins de pixels par dimension) à chaque niveau. La pyramide gaussienne est plus efficace pour deux raisons. D'abord, les images stockées sont plus petites et occupent donc moins de mémoire et nécessite moins de temps de calcul pour être traitées. Aussi, plutôt que d'appliquer un flou gaussien dont la complexitée croit de façon exponentielle, il devient possible de ne faire qu'un flou de rayon deux sur chaque niveau. Cela est simplement dû au fait qu'un flou de rayon deux sur une image de taille \(x\) correspond à un flou de rayon quatre si l'image est redimensionnée d'un facteur deux. La pyramide ne cause pas de perte d'information puisque redimenssionner d'un facteur 0.5 diminue de moitié la plage de fréquence de l'image tout comme le flou. La fréquence de Nyquist reste donc respectée.

La pyramide a été implémenté sous forme d'un décorateur pour les fonctions gaussienne et laplacienne. Ainsi, gaussienne(img) retourne le générateur d'une pile gaussienne pour image alors que pyramid_decorator(gaussienne(img)) retourne plutôt une pyramide.

Pyramide gaussienne de niveau 1
Pyramide gaussienne de niveau 2
Pyramide gaussienne de niveau 3
Pyramide gaussienne de niveau 4
Pyramide gaussienne de niveau 5
Pyramide laplacienne de niveau 1
Pyramide laplacienne de niveau 2
Pyramide laplacienne de niveau 3
Pyramide laplacienne de niveau 4
Pyramide laplacienne de niveau 5

Partie 3

Il est possible de faire un autre type de mélange multirésolution comme décrit dans un papier de Burt and Adelson en 1983. Un spline d'image est un joint lisse entre deux images. Il est obtenue en combinant séparément les différentes fréquences de deux images. La précision de la fonction peut être augmentée en faisant plus de passes de l'algorithme, c'est-à-dire en combinant séparément davantage de fréquences. La figure suivante montre la différence au fur et à mesure que le nombre de passe augmente.

1 passe
2 passes
3 passes
4 passes
5 passes
6 passes
7 passes
8 passes

Bien sure le masque n'a pas besoin d'être uniquement une séparation au millieu de l'image, voici d'autres exemples:

image 1
image 2
masque
Résultat
image 1
image 2
masque
Résultat
image 1
image 2
masque
Résultat
image 1
image 2
masque
Résultat

Les résultats ne sont pas toujours bons avec des photos personnelles car ce n'est pas suffisant d'avoir uniquement un jointure subtile entre deux images pour ne pas que le montage soit éviddent. Il faut en aussi contrôler l'orientation des objets par rapport à la scène, les différences d'illumination, le grain variant avec l'ISO de la prise, etc. Le résultat est aussi beaucoup plus subtil dans le cas de la pommange puisque l'image est initialement de mauvaise qualité.

Un autre problème de l'implémentation actuelle est qu'elle est très exigente en RAM. En effet, fusionner les images de 21 MPx avec 6 passes peut prendre à un certain moment jusqu'à prêt de 7 Go de mémoire. Cela est du entre autre à l'utilisation de piles plutôt que de pyramide, à la non-réutilisation des noyaux de flou et sans doute au garbage collector de Python qui prend un certain retard.

La figure suivante montre comment les images sont composées sur 4 passes. Chaque colonne représente une bande de fréquence. Les rangées correspondent à chacune des images et à la somme des deux.

Hautes fréquences
Hautes fréquences
Hautes fréquences
Hautes fréquences
Basses fréquences
Hautes fréquences
Hautes fréquences
Hautes fréquences
Hautes fréquences
Basses fréquences
Hautes fréquences
Hautes fréquences
Hautes fréquences
Hautes fréquences
Basses fréquences

Crédits supplémentaires

Comme démontré par les images précédentes, utiliser de la couleur n'est pas beaucoup plus compliqué, en effet, Scikit Image gère le flou gaussien de la même façon pour les images couleurs que monochrome. Un problème rencontré en lien avec les images RGB est que les celles-ci développaient des taches très saturées de plus en plus grosses au fur et à mesures que des passes étaient faites. Cela a été résolé de la même façon qu'à la partie 1, soit en limitant les valeurs de chaque canaux entre 0 et 1.