TP1: Coloration de l'Empire Russe

GIF-7105

Louis-Philippe Asselin

Résumé

Sergey a besoin d'aide pour restaurer ses photos. Ce rapport présente les méthodes utilisées afin d'aider Sergey à restaurer ses photos. Puisque l'album photo de Sergey compte 1902 images, les algorithmes retenus sont applicables automatiquement sur toutes les images.

La solution retenue (résultats de Approche pyramide) pour le traitement des images est composée des algorithmes suivants:

Ces techniques et d'autres techniques moins intéressantes sont commentées dans ce rapport.

Pour les étapes de recherche, la comparaison utilisée est la corrélation croisée de deux canaux de l'image.

Finalement, la solution retenue effectue le traitement sur une image haute résolution en moins de 2 secondes (sur un ordinateur portable ancien avec GPU). Cette performance est atteinte par l'utilisation de la librairie d'apprentissage machine PyTorch.

Note: Pour voir les images en taille originale, clic droit et "copy image address".

Approche à une seule échelle

La corrélation croisée est utilisée avec une fenêtre (padding) de 30 de chaque côté. On peut remarquer que plusieurs résultats sont à cette valeur maximale.

La comparaison effectuée est la corrélation croisée sur l'image initialement filtrée par un filtre de Sobel. Le centre 2/3 de l'image est utilisé pour la comparaison.

Les résultats sont acceptables pour les images de petite taille (400 pixels) mais pas très bons pour les images à haute résolution. C'est attendu puisque la recherche des translations n'est pas effectuée jusqu'à la valeur optimale.

La section suivante, par pyramide, est une solution à ce problème.

Résultats (click me)

Format: (vert_height, vert_width), (bleu_height, bleu_width)

Translation optimale Résultat
00029u.tif (16, 30), (15, 30)
00087u.tif (-4, 30), (-5, 3)
00106v.jpg (1, 5), (-1, 9)
00128u.tif (26, 30), (30, 30)
00458u.tif (9, 30), (30, 29)
00737u.tif (7, 17), (15, 30)
00757v.jpg (3, 3), (5, 5)
00822u.tif (24, 30), (30, 26)
00888v.jpg (1, 7), (0, 12)
00889v.jpg (2, 2), (3, 4)
00892u.tif (2, 17), (3, 30)
00907v.jpg (0, 3), (0, 6)
00911v.jpg (-1, 2), (-1, 13)
01031v.jpg (1, 2), (2, 4)
01043u.tif (10, -14), (16, 12)
01047u.tif (20, 26), (30, 30)
01657v.jpg (1, 6), (1, 12)
01880v.jpg (2, 7), (4, 14)

Approche à échelles multiples

La recherche des translation est effectuée sur plusieurs échelles, en débutant avec une image qui est plus petite que 128x128. Chaque échelle est deux fois plus petite que la précédente.

Une translation maximale de 5 pixels (de chaques côtés) est effectuée pour chaque image de la pyramide. Une fois la translation optimale déterminée pour une échelle, une translation deux fois plus grande est appliquée à l'image du niveau précédent (image deux fois plus grande).

La comparaison effectuée est la corrélation croisée sur l'image initialement filtrée par un filtre de Sobel. Le centre 2/3 de l'image est utilisé pour la comparaison.

Les résultats sont très bons visuellement.

Pour accélérer le processus, il aurait été intéressant d'optimiser la recherche en utilisant un algorithme d'optimisation.

Résultats (click me)

Format: (vert_height, vert_width), (bleu_height, bleu_width)

Translation optimale Résultat
00029u.tif (15, 39), (32, 90) [](images/pyramid_jf/00029u.jpg#small_2
00087u.tif (38, 49), (56, 108)
00106v.jpg (1, 5), (-1, 9)
00128u.tif (26, 37), (38, 53)
00458u.tif (2, 42), (29, 85)
00737u.tif (7, 17), (14, 50)
00757v.jpg (3, 3), (5, 5)
00822u.tif (25, 58), (33, 126)
00888v.jpg (1, 7), (0, 12)
00889v.jpg (2, 2), (3, 4)
00892u.tif(2, 17), (4, 42)
00907v.jpg (0, 3), (0, 6)
00911v.jpg (-1, 2), (-1, 13)
01031v.jpg (1, 2), (2, 4)
01043u.tif (10, -14), (16, 12)
01047u.tif (20, 26), (33, 72)
01657v.jpg (1, 6), (1, 12)
01880v.jpg (2, 7), (4, 14)
00001u.tif [[2, 38], [-8, 97]]
00002u.tif [[23, 33], [24, 92]]
00003u.tif [[7, 27], [33, 67]]
00004u.tif [[13, 33], [41, 83]]
00005u.tif [[8, 28], [12, 89]]
00006u.tif [[43, 25], [51, 68]]
00007u.tif [[16, 42], [23, 91]]
00008u.tif [[0, 47], [0, 101]]
00009u.tif [[11, 36], [17, 80]]
00010u.tif [[-5, 46], [-20, 97]]
00011u.tif [[14, 18], [38, 81]]
00012u.tif [[-5, 42], [5, 95]]
00013u.tif [[8, 27], [10, 106]]
00014u.tif [[25, 99], [32, 202]]
00016u.tif [[12, 45], [15, 97]]
00017u.tif [[-17, 12], [-26, 18]]
00018u.tif [[28, 62], [43, 132]]
00019u.tif [[16, 53], [19, 106]]
00020u.tif [[-10, 49], [-32, 94]]
00021u.tif [[35, 30], [61, 72]]
00022u.tif [[11, 34], [7, 78]]
00023u.tif [[-11, 12], [4, 68]]
00024u.tif [[-4, 33], [-12, 77]]
00025u.tif [[21, 41], [27, 101]]
00026u.tif [[13, 55], [4, 126]]
00027u.tif [[23, 51], [42, 112]]
00028u.tif [[8, 44], [-2, 95]]
00029u.tif [[15, 39], [32, 90]]
00030u.tif [[25, 47], [40, 91]]
00031u.tif [[1, 49], [-7, 106]]
00032u.tif [[10, 39], [7, 89]]
00033u.tif [[11, 57], [15, 105]]
00034u.tif [[127, -155], [35, 97]]
00035u.tif [[7, 46], [4, 118]]
00036u.tif [[29, 37], [23, 81]]
00037u.tif [[8, 43], [7, 91]]
00038u.tif [[29, 59], [36, 121]]
00039u.tif [[13, 43], [20, 94]]
00040u.tif [[6, 32], [9, 81]]
00041u.tif [[-8, 34], [-30, 73]]
00042u.tif [[10, 38], [18, 90]]

Dans la peau de Prokudin-Gorskii

Résultats (click me)

Translation optimale Original Résultat
fractal_no_move.jpg ((0, 0), (0, 0))
small_translation.jpg ((10, 21), (0, 0))
le_vieux_chum.jpg ((5, 1), (-6, 0))
shia_mouvement.jpg ((-5, 0), (18, -1))
shia_slight_move.jpg ((42, -52), (48, -48))
gros_mouve.jpg ((0, 0), (0, 0))

^ Image en mouvement

Crédits supplémentaires

Recherche sur les arrêtes

Tous les résultats présentés plus haut utilisent le filtre de Sobel.

Un filtre de Sobel est utilisé comme première étape du traitement. Ce filtre est convolué à l'image originale.

Puisque la corrélation croisée est utilisée, les résultats nettement supérieurs. Les fonctions de recherche de translations et rotations reçoivent une image représentant les arrêtes de l'image originale.

Exemple:

La comparaison par la corrélation croisée bénéficie beaucoup de l'utilisation des arrêtes de l'image. Les régions où les valeurs des pixels sont hauts (par exemple région sombre dans une image) contribuent moins au score de la fonction de comparaison lorsque nous utilisons seulement les arrêtes de l'image.

Résultats (click me)

Exemples: (sans Sobel / avec Sobel)

1

2

3

Recherche des rotations

Au départ, une recherche sur les rotations a été effectuée en comparant le canal B à G et B à R. Les résultats ne sont pas excellents pour toutes les images pas très bons. Cette version de rotation est fournie.

Résultats (click me)

Format: (vert_height, vert_width), (bleu_height, bleu_width), (vert_rotation, bleu_rotation)

Translation et rotation optimale Résultat
00106v.jpg [-2, 0], [-5, 5] [-0.8, 1.7]
00757v.jpg [-1, -1], [ 1, 1] [0.6, 0.8]
00888v.jpg [-3, 1], [-5, 5] [ 0.8, -2. ]
00889v.jpg [-1, -1], [-1, -1] [-0.3, -0.7]
00907v.jpg [-2, 0], [-3, 1] [0.4, 0.6]
00911v.jpg [-1, 0], [-7, 5] [-0.4, 0.7]
01031v.jpg [-1, -1], [-2, -1] [-0.4, -0.4]
01657v.jpg [-3, 1], [-3, 5] [0.9, 1.7]
01880v.jpg [-3, 1], [-3, 5] [ 2. , -0.7]

Par la suite, j'ai remarqué qu'une rotation sur l'image originale pourrait être une solution. Pendant quelques jours, j'ai cru que la caméra de Sergey capturait les 3 images en même temps, à l'aide de 3 lentilles et 3 filtres. Aussi, il semble que la photo de la photo ne soit pas centrée. Selon ces hypothèses, la rotation par canal a été remplacée par une rotation complète de l'image originale (axe de rotation est le centre de l'image originale. Les résultats ne sont pas meilleurs que ceux de la rotation précédente.

Résultats (click me)

Améliorations des taches

Les améliorations suivantes sont appliquées après les translations.

Pas utilisé dans les résultats précédents.

La médiane des canaux de chaque pixel est calculée. Pour chaque pixel et chaque couleur, si la différence entre la valeur du pixel et la médiane à ce pixel est plus grande qu'un seuil (20% de la plage dynamique), la valeur est remplacée par la médiane.

Les résultats sont bons pour les taches mais ils ne sont pas excellents puisque les bordures des taches sont préservées. Ceci est attendu puisque le seuil n'est pas variable. Un autre inconvénient est que si on augmente le seuil pour augmenter toutes les taches, la couleur de l'image change beaucoup. L'effet est similaire à une balance des blancs.

Résultats (click me)

Exemples: (sans amélioration / avec amélioration)

Note: le crop des bordures dans les exemples suivants n'affecte pas l'algorithme.

1

6

55

56

Détection des bordures

Après avoir appliqué la translation, détection des bordures à l'aide des sommes des colonnes et rangées du gradient du gradient de l'image de saturation...

Sur la figure suivante, on peut voir que la somme des rangées et la somme des colonnes varie beaucoup aux discontinuités des bordures.

Figure: Sommes des pixels des colonnes (bleu) et sommes des pixels des rangées (rouge)

Détection des bordures:

  1. À partir des valeurs de l'image de saturation 2D, le gradient du gradient est calculé (pour les colonnes et les rangées).

  2. Ensuite, find_peaks de scipy.signal est appliqué sur ces valeurs.

  3. L'image est rognée aux valeurs des sommets les plus éloignés des bordures, ce qui représente normalement la dernière bordure de l'image

Cette méthode profite de la grande variation de saturation sur les côtés de l'image. Elle doit cependant être limitée aux régions approximatives des bordures, sinon, une ligne dans l'image pourrait être interprétée comme une bordure. Je n'ai pas eu ce problème.

Toutes les images présentées dans les résultats utilisent cette méthode.

Les images dont les bordures sont moins bien découpées sont celles où la bordure est un dégradé. Plusieurs exemples sont disponibles dans les résultats précédents. Pour régler ce problème, il aurait été intéressant d'ajouter une fonction qui utilise les trois images et applique un gradient inverse pour compenser.

Cependant il est plus utile d'appliquer un algorithme sur les taches qui affecte aussi les bordures.

White Balance

Pas utilisé dans les résultats précédents.

Deux méthodes testées:

Monde gris

Cette méthode suppose que l'appareil capture des scènes grises. Un simple ajustement par multiplication d'un coefficient pour chaque canal replace les canaux pour qu'ils aient tous la même moyenne.

Résultats (click me)

Exemples: (sans whitebalance / avec whitebalance)

Note: le crop des bordures dans les exemples suivants n'affecte pas l'algorithme.

1

2

3

4

Univers gris

Cette méthode supposait (comme pour la rotation de l'image originale) que l'appareil photo de Sergey capturait les 3 photos en même temps. La moyenne de l'univers (toutes les photos haute résolution, effectuer la moyenne du résultat monde gris) Les coefficients obtenus varient de l'ordre de +/- 2%. Nécessairement, les résultats ne sont pas beaucoup affectés par ce changement. La balance des blancs par l'univers gris n'a pas été retenu. Les résultats ne sont pas présentés puisqu'ils sont visuellement similaires.

Les deux méthodes testées sont calculées sur une fenête de la moitié de la taille de l'image, centrée, afin que les bordures n'affectent pas les valeurs obtenues.

Les deux méthodes ont aussi été testées avec un coefficient et un offset (addition ou multiplication). Ces deux sous méthodes donnent des résultats similaires.

Égalisation d'histogramme

Pas utilisé dans les résultats précédents.

L'égalisation de l'histogramme est effectué avec la fonction fournie par la librairie pillow de python.

Cette fonction augmente le contraste et effectue à la fois une balance des blancs. Malgré que quelques images sont très belles avec cette technique (13), les résultats du traitement sont généralement visuellement trop laids pour inclure cette technique au processus automatique de Sergey. Il est probablement possible de manuellement sélectionner les fractions de l'histogramme à étendre pour les trois canaux et obtenir des meilleurs résultats.

Résultats (click me)

Exemples: (sans égalisation / avec égalisation)

Note: le crop des bordures dans les exemples suivants n'affecte pas l'algorithme.

1

13

56

Merci!