TP1: Coloration de l'Empire Russe

Résumé des fonctions à utiliser

Fichier: jpg.py
Prend le nom d'un fichier JPG comme argument dans le fichier et affiche l'image RGB allignée. L'algorithme ne prend pas en compte le scaling de l'image et ne fonctionne que sur les images JPG.

Fichier: scale_jpg.py
Prend le nom d'un fichier TIF ou JPG comme argument dans le fichier et affiche l'image RGB allignée. L'algorithme prend en compte le scaling de l'image de 1/5 à 1/2.

Librairies: Numpy et Skimage
Les fonctions ont besoin de ces deux librairies pour fonctionner. Les fonctions sont importées avec "import functions as fn" et utilisée comme suit: "fn.get_rgb_image(im, 15)"

Description du projet

Le projet consistait à aligner les trois spectres d'une image (rouge, vert et bleu) en une seule. L'alignement devait se faire pour que l'image finale, une combinaison des trois couleurs, soit la plus net possible. Ceci devait se faire automatiquement selon la taille de l'image d'entrée. La méthode utilisée pour les premiers tests de cet algorithme est celle prescrite dans l'énoncée du travail, soit celui de déplacer deux spectres par rapport à un autre selon une valeure de mouvement selon l'axe des X et Y; à chaque étape il faut calculer l'erreure quadratique moyenne (EQM) et le garder en mémoire pour déterminer quand est-ce que cette erreure était la moins grande.

Il fallait ensuite tenter de faire ce calcul pour des images de grandes tailles. La difficulté étant que de calculer l'EQM selon un petit mouvement de 30 pixels par 30 pixels serait très long. Il faut donc tenter de calculer le mouvement pour des images réduites. Calculer un mouvement de 30 par 30 sur une image de 3000 pixels est long mais sur une image de 400 pixels c'est intéressant. À noter que le travail de trouver l'EQM est grandement aidé si on passe l'image dans un filtre avant le traitement. J'ai utilisé le filtre de sobel de la librairie skimage filters.

Résultats de l'algorithme à une seule échelle sur toutes les images JPG

Prenons l'image de base "./images/00106v.jpg" et passons par l'algorithme de base qui ne prend pas en compte la taille de l'image et ne la réduit pas. Le script "./jpg.py" dans mon dossier de remise prendre le nom de l'image en argument et le passe à la fonction "get_rgb_image(image_input, search_offset)" qui retournera l'image RGB avec les trois spectres superposés. Pour tester mon script sur différentes images JPG simplement changer la ligne "imname = './images/00106v.jpg'" pour le nom de l'image voulue. Voici l'image filtré par le filtre sobel pour trouver les contours les plus prominents. Ceci aide particulièrement la recherche de l'EQM et donne les meilleurs résultats pour la superposition des images. Voici l'image finale après avoir été travaillé par l'algorithme de base ainsi que toutes les autres images JPG à modifier obligatoirement pour le TP.

"00106v.jpg" "00757v.jpg" "00888v.jpg" "00889v.jpg" "00907v.jpg" "00911v.jpg" "01031v.jpg" "01657v.jpg" "01880v.jpg"

Résultats de l'algorithme à échelles multiples sur des images à haute résolution

Cette partie du travail pratique est celle qui m'a donné le plus de problème. Premièrement, j'ai souvent eu un "MemoryError" en tentant d'appliquer le filtre Sobel ainsi que la fonction dstack sur mes images quand elles sont en format TIF. Pourtant (durant mes sessions de debug), je prenais très attention à transformer mes images du format float au format uint16_t et même uint8_t pour ne pas trop bourrer la mémoire. Par contre, je pense comprendre que le filtre et la fonction dstack transforment les listes de données sous format float, ce qui pourrait causer les "MemoryError". Par contre rien à craindre, j'ai fait attention à prendre ceci en compte dans mon algorithme en ne tentant pas de faire la recherche de translation sur des images trop grandes (soit des images en haut de 2900 pixels de hauteur). Toutes les images TIF ont été traitée de cette façon et malgré que je ne fais pas la recherche sur le dernier scaling (scaling de 1 donne l'image) entière et donc une hauteur de plus de 3000 pixels), je le fais sur tous les autres scaling (de 1/2 jusqu'à 1/5).

Un autre problème de cette partie a été la fonction "pyramid_reduce()" de la librairie "skimage transformations". Elle est très simple à utiliser, mais il semble que pour certaine images TIF de grand format, en autre "01047u.tif", "01043u.tif" et "00892u.tif", si je tente de les réduires d'un scaling plus grand que 5, les données de l'image vont parfois overflow. Au lieu d'avoir comme maximum la valeur float 1.0, la valeur maximum était de 1.000000007. Ce ne serait pas un problème si après je ne voudrais pas tenter d'afficher cette image. Mais dès que je tente de l'afficher une erreur de "skimage" me dit que les valeurs float doivent être entre 0.0 et 1.0. Je n'ai pas tenté de régler ce problème en prenant les valeurs fautives et les saturant à 1.0 car même avec un scaling de 5 les images TIF finales sont vraiment très très bien. Petit ajout de dernière minute, finalement il ne semble pas permis de prendre la fonction "pyramid_reduce()". Un petit changement dans le code pour prendre la fonction resize de la même librairie et tout fonctionne correctement. Il semble que j'utilisais la fonction avec les pyramides d'une mauvaises façon et que cela équivalait à prendre la fonctiom resize.

Sinon pour ce qui est de l'algorithme en tant que tel, il est assez simple mais fonctionnel. C'est la fonction "get_scaled_rgb_image(image_in)" qui retourne l'image RGB correctement allignée. Je commence avec la valeur de scaling de 5 à rentrer dans la fonction "pyramid_reduce()" et c'est sur l'image de sortie de cette fonction que je travail à chercher le calcul de la translation à exécuter sur le canal rouge et bleu par rapport au canal vert. Je travail ensuite l'image originale en utilisant la fonction "roll()" sur seulement les cannaux rouge et bleu. Puisque l'image originale est beaucoup plus grande (d'un ordre du paramètre scale), la fonction "roll()" est multipliée par la valeur "scale". Je repasse ensuite l'image originale par l'algorithme jusqu'à retrouver le paramètre "scale" égal à un. L'algorithme se termine ainsi.

Pour refaire mes images, simplement prendre le fichier "scale_jpg.py" et changer le nom des fichiers voulu en entrée. Prendre en compte le chemin absolu. L'image devrait s'afficher automatiquement.

"00029u.jpg" "00087u.jpg" "00128u.jpg" De loin une de mes images préférées dans la collection. J'étais particulièrement surpris à quel point les détails ressortent très bien sur la peinture. "00458u.jpg" "00737u.jpg" "00822u.jpg" C'est mon image préféré de la collection pour l'instant. J'aime m'imaginer à leur place, pionnier d'une petite forêt. "00892u.jpg" "01043u.jpg" "01047u.jpg" Voici maintenant le résultat de l'algorithme sur les 10 images TIF prises dans la collection.

"01567u.jpg" "01568u.jpg" "01569u.jpg" Il semble que cette image soit très saturée par la lumière du soleil. "01570u.jpg" "01571u.jpg" La fumée a bougée pendant la prise de photo et ça donne un effet mystique; probablement une maison de sorcière. "01572u.jpg" "01573u.jpg" "01574u.jpg" "01575u.jpg" "01576u.jpg"

Résultats de l'algorithmes sur des photos prises moi-même

"20190121151937.jpg" Voici la première image assez simple avant le traitement (c'est l'image utilisée pour le canal rouge). "stacked20190121151937.jpg" Les canaux bleu, vert et rouge de trois photos différentes sont combinés verticalement pour refaire le même genre d'image que celles utilisées dans le travail pratique. "rgbstacked20190121151937.jpg" Avec l'algorithme on retrouve les trois images combinées correctement. "rgbstacked20190122114824.jpg" Cette deuxième image est aussi bien, mais très clairement la télévision et changé plusieurs fois d'images et cause une superposition de canaux rouge, bleu et vert de différents moments de la télévision. Certaines personnes ont aussi bougé un peu mais l'effet est correct et l'image compréhensible. Les trois prochaines images sont des tests que j'ai fait avec le mouvement de personnes pendant que je prends les trois différentes images. Assez "wack"!

"rgbstacked20190122130623.jpg" "rgbstacked20190122130701.jpg" "rgbstacked20190122130732.jpg"