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)"
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.
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"
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"
"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"