Projet: Retrait du motion blur

Introduction

Pour le projet, j'ai choisi d'implémenter la solution de l'article From Motion Blur to Motion Flow: a Deep Learning Solution for Removing Heterogeneous Motion Blur de Dong Gong, Jie Yang, Lingqiao Liu, Yanning Zhang, Ian Reid, Chunhua Shen, Anton van den Hengel, Qinfeng Shi of School of Computer Science and Engineering, Northwestern Polytechnical University, China and the University of Adelaide, Australian Centre for Robotic Vision.

Cet article permet d'estimer le bruit de déplacement sur une image et de le soustraite à une image bruitée pour retrouver une image plus nette. Quand on prend une photo d'une image et que les acteurs sont en déplacement, on peut capturer du bruit. En effet, si leur déplacement est plus rapide que la vitesse d'obturation de l'appareil photo, alors les photos qui seront capturés laisseront voir des traînées que l'on appelle du "motion blur". Ce bruit peut être qualifié en 2 types:

  1. Motion blur unidirectionnel: Tout le motion blur de l'image est linéaire et est appliqué sur une sous-section ou la totalité de l'image. Par exemple, vous avez un trépied et un appareil photo et vous prenez une photo d'une scène fixe avec un chien qui court dans une direction perpendiculaire à la celle de l'appareil. L'image du chien sera floue, mais l'arrière-plan sera clair. Ce type de flou peut être assez facilement retirable d'une image, car il est linéaire et des algorithmes existent pour l'estimer et en atténuer l'impact.
  2. Motion blur hétérogène: Le motion blur est propre à chacun des pixels. Cela implique que les pixels voisins ne partagent pas nécessairement le même bruit de déplacement. Comme chaque pixel peut avoir son propre bruit, il n'existe pas d'algorithmes qui peuvent le calculer et le retirer de l'image. La seule manière de retirer, c'est en faisant une estimation du bruit et de sa direction. Toutefois, il s'agit d'une opération qui est impossible à paramétriser.
Comme le motion blur hétérogène peut être estimé, il est à notre avantage de faire usage de la puissance de l'intelligence artificielle, car il s'agit d'une technologie très appropriée pour faire de l'inférence. Comme ce sont des images qui seront traitées et qu'elles seront de tailles différentes, il est impératif que le réseau soit fully-convolutionnal.

Processus

La méthode de l'article se fait en 2 étapes. La première étape consiste à créer le jeu de données et à entraîner le réseau avec ce dernier. La seconde consiste à estimer le bruit dans l'image puis de le retirer avec des algorithmes linéaires.

Création du jeu de données

Pour créer le jeu de données, les images de BSD500 ont été utilisées. Il s'agit d'un ensemble de 200 images qui sont d'une taille d'environ 300 x 460 et qui représentent des animaux, des hommes ou des scènes. En prenant les 200 images et en utilisant les algorithmes dont l'article fait usage, il est possible de générer 50 motion flow par image. Cela totalise 10 000 motion flow en plus des 200 images non-bruitées et leurs motion flows associés (qui sont nuls).

Exemple de blur d'image

Image nette
Image avec motion blur hétérogène

En plus du bruit de déplacement directionnel ajouté à l'image, un bruit gaussien est ajouté ce qui rend l'image un peu plus floue et garantie que l'image ne peut être débruitée.

Développement du modèle sur Pytorch

Dans l'article, un modèle entraîné par l'équipe est donné, mais il est sur Caffe. Comme j'ai décidé de l'implémenter en Pytorch, je dois réecrire le code et déterminer les équivalences pour les différentes fonctions.

Fully-convolutionnal network (FCN)

En plus du déplacement directionnel ajouté à l'image, un bruit gaussien est appliqué ce qui rend l'image un peu plus floue et garantie que l'image ne peut être débruitée facilement.

Entraînement du réseau de neurone

L'entraînement implique plusieurs paramètres:

Comment se déroule l'entraînement

Pour l'entraînement, le réseau de neurone prend en entrée des images motion blurred et tente de prédire en sortie le motion flow map qui est associé à cette image. Comme tous les bruits ont été générés synthétiquement, les labels ont été conservés et il est possible de calculer la différence entre la prédiction et la "ground truth" (la cible) avec une perte de Cross Entropy.

Processus d'entraînement

Pour chaque image blurred, le réseau apprend à prédire le bon motion flow map. Itérativement et avec la descente de gradient, il devient meilleur et devrait prédire des motion flow maps qui sont de plus en plus en accord avec le bruit réel dans l'image.

Deblurring de l'image

Pour retirer le bruit d'une image, il faut tout d'abord prendre le motion flow map qui a été estimé par le modèle. Par après, en prenant le déplacement de chacun des pixels, un algorithme se charge de calculer linéairement le déplacement pour le pixel et ses voisins. Ce processus se fait par déconvolution. Il est à noter que la déconvolution peut occasionner des effets indésirables sur les photos. En effet, la déconvolution effectue du upsampling dans l'image. Cela implique d'aggrandir une image en lui rajoutant de l'information et ce processus peut injecter du bruit, car du padding doit être ajouté autour de l'image. Parfois, si le upsampling est trop grand, on peut appercevoir un effet de quadrillage sur le résultat final.

Résultats

L'entraînement du réseau est très long, car chaque epoch prend environ 40 minutes à s'exécuter. En prenant en considération que les auteurs de l'article ont mis 65 epoch pour atteindre la convergence, cela implique 45 heures de calculs. De ce fait, j'effectue une comparaison des résultats qui sont obtenus avec leur modèle en Caffe à ceux que j'ai obtenu. Aussi, il est à prendre en considération que le modèle que j'utilise fait usage d'un modèle qui est peu entraîné (environ 16 epoch), car il s'agit de la meilleure accuracy qui a été obtenue. Les résultats ne sont donc pas parfaits.

Modèle Caffe entraîné de l'article

Avec le modèle de l'article, on constate que le motion flow map est très représentatif du bruit de l'image et que le réalignement des pixels se fait très bien. Le résultat du deblurring pour mon image avec un bruit aléatoire est très réussie.

Mon modèle (Epoch 7)

Mon modèle, bien que sous-entraîné, laisse paraître un bon présage sur son apprentissage, car tous les vecteurs estimés dans le motion flow map sont orientés dans la bonne direction. On peut le comparer avec l'image précédente et le motion flow estimé par le modèle complètement entraîné. Ce qui manque à mon modèle encore, c'est un certain facteur de gain sur les vecteurs estimés. En effet, l'orientation est bonne, mais la norme est encore beaucoup trop petite. Néanmoins, on voit que le déblurring fonctionne en partie, car l'image est un peu plus nette.

Mon modèle (Epoch 7) - Image aggrandie

Un agrandissement de l'image précédente pour 2 régions indentiques sur les images permet de bien voir l'effet du deblurring. On retrouve beaucoup d'information au niveau des bordures.

Modèle Caffe entraîné de l'article

Une fois de plus, les performances avec leur modèle entraîné sont très impressionnantes. J'ai choisi cette photo, car elle contenait un peu de bruit dans l'image originale et qu'il y avait plusieurs écritures sur des panneaux d'affichage. Le bruit généré est aléatoire. Le retrait du bruit dans l'image ne permet pas de reconnaître les écritures sur les panneaux. Toutefois, avec le retrait du flou, on retrouve beaucoup d'information au niveau des visages des gens.

Mon modèle (Epoch 7) - Image aggrandie

Les performances du réseau entraîné sont très basses encore, mais les vecteurs ont sensiblement tous la bonne orientation.

Modèle Caffe entraîné de l'article - Image personnelle

Et si je prenais une photo d'un objet en mouvement? Un objet qui aurait du motion blur naturel. Voici le résultat de ma tentative. Le problème avec une photo d'un appareil, c'est qu'elle est de très grande résolution. L'estimation du motion flow se fait bien avec le réseau, même si l'image est de plus grande taille. Toutefois, c'est beaucoup plus long. En effet, c'est aussi pourquoi elle doivent être rapetissées, car le traitement devient interminable pour le deblurring. Il faut donc faire un resizing de l'image. Malgré les effets du resize, on peut constater que les résultats sont vraiment impressionnant. J'agitais effectivement la canette de haut en bas. Par contre... rien n'explique la présence des vecteurs au bas à gauche.

Mon modèle (Epoch 7) - Image personnelle

Une fois... ça va... 2 fois, c'est pas pire. Mais 3 fois que les vecteurs quasiment dans la même orientation? Je commence à douter de mon epoch 7 ! Je retesterai avec le réseau complètement entraîné. Le résultat devrait être plus prometteur. Au moins, j'aurai tenté l'expérience!

Limitations

La première limitation au modèle courant est que le modèle ne peut pas complètement retirer le flou de l'image. En effet, le modèle peut au mieux estimer le bruit et ne peut pas le retirer complètement. Aussi, il est à prendre en considération que le bruit gaussien ne peut être retiré.

La seconde limitation au modèle est que le domaine est borné et limité dans l’axe des X. Si X < 0, alors X = - X. Cela implique que les déplacements sur l'axe des X peut seulement être positif. Cela facilite l'entraînement, mais implique que les flou dans l'autre direction seront augmentés plutôt que retirés. Aussi, le déplacement maximal des vecteurs (soit la vitesse occasionnant le bruit) est limitée à une valeur maximale. De ce fait, si du bruit de déplacement est trop élevé pour les paramètres d'entraînement, il ne pourra pas être bien atténué.

Améliorations

Premièrement, les filtres à déconvolution sont suivi d'un upsample, car la conversion entre les fonctions de Caffe et de Pytorch ne sont idéales. Le problème est qu'en rajoutant des layers de upsampling à des régions de déconvolution, c'est l'équivalent à rajouter de nouvelles couches de déconvolution. Comme chaque couche peut occasionner du bruit en forme de damier, il faut limiter les opérations de déconvolution. Il faudrait donc réussir à obtenir la même équivalence entre les fonctions de Caffe et Pytorch.

Deuxièmement, du dropout pourrait être ajouté à l'entraînement pour le régulariser. Cela pourrait rendre le réseau meilleur dans les généralisations et les cas qui sont particuliers. En éteignant des neurones aléatoirement, on vient forcer l'utilisation de tous les neurones dans le réseau plutôt que de concentrer le gradient dans des neurones particuliers.

Troisièmenent, le taux d'apprentissage devraient être réduit au cours de l'entraînement. Toutefois, le training a été lancé sur Pytorch sans l'ajout de ce paramètre. Cela pourrait nuire à la convergence, car le taux d'apprentissage pourrait être trop élevé pour atteindre les minimums locaux après un haut nombre d'epochs.

Finalement, il faudrait retravailler les valeurs de domaine pour l'entraînement, car elles limitent les valeurs maximales de motion blur ainsi que leurs directions.

Sources: