Pour le 22/12/2008 Vision et Reconstruction 3D Projet : Retimer Pol Grasland-Mongrain 1) Objectifs Prendre une séquence ordonnée de photos (si possible en mode rafale) d'un sujet animé. Retrouver des points communs à toutes les images, les mailler et générer des images intermédiaires par interpolation du maillage et des couleurs. On s'attachera plus à la robustesse de la détermination des points qu'à d'éventuels raffinements ou post-traitements qui permettraient l'obtention d'images parfaites. J'ai écrit toutes les fonctions citées ci-dessous, à l'exception de dist2.m (qui fait 1 ligne), harris.m (que j'ai légèrement modifié) et delaunay (qui est une fonction interne à Matlab) 2) Structure de l'algorithme Le fichier principal à lancer s'appelle main.m. Toutes les variables intéressantes à modifier pour l'utilisateur se trouvent dans le fichier initialisation.m. Cet algorithme : 1. Initialise certaines variables (fonctions initialisation.m) 2. Importe les images et les transforme en niveaux de gris 3. Trouve les points d'intérêts par la méthode de Harris (fonction harris.m) 4. Supprime les points d'intérêts trop proches (fonction removeNeighboor.m) 5. Trouve les descripteurs associés à chaque point d'intérêt (fonction descriptor.m) : il s'agit du patch de 9 pixels * 9 pixels autour du point d'intérêt 6. Calcule la « distance » entre tous les descripteurs, c'est à dire leur ressemblance - ce n'est pas une distance euclidienne (fonction dist2.m) 6. Met en correspondance les descripteurs et supprime toutes les correspondances douteuses : quand un point correspond à deux autres, lorsque sa direction est très différente des autres, et lorsque son déplacement est trop important, et rajoute les coins de l'image dans les descripteurs (fichier matches.m) 7. Affiche les 2 images côte-à-côte, montre les points d'intérêt dans les 2 images et leur correspondances 8. Pour les ceil(n/2) premières images : 1. Réalise une triangulation de Delaunay pour les points d'intérêt de l'image a (fonction delaunay) 2. Trouve l'appartenance de chaque pixel de l'image a à un ou plusieurs des triangles de Delaunay (fonction presenceTriangle.m) 3. Calcule les transformations affines qui permettent de passer des 3 points d'intérêt formant un triangle de l'image a à 3 autres correspondants dans l'image b, et applique ces transformations à chaque triangle de l'image, et ce pour l'image a 9. S'il y a plus de 2 images intermédiaires, réalise les étapes 8,9 et 10 pour les floor(n/2) images suivantes sur l'image b 10. Affiche les images intermédiaires 3) Qualités et défauts L'algorithme est bien approprié pour des petits déplacements. Les mouvements globaux de caméra sont très bien rendus (sauf au niveau du bord lorsque le déplacement est trop important). S'il y a plus de deux images intermédiaires, le fait de réaliser les transformations sur une image, puis sur l'autre, permet une transition plus douce et symétrise l'algorithme. L'algorithme n'est pas robuste aux déplacements importants : il présente parfois des lignes au niveau des triangles très transformés ; lorsque les objets se déplacent dans différentes directions avec un mouvement important, l'algorithme ne le voit pas forcément ; les triangles peuvent se superposer en cas de mouvement important (cf photo). Il n'est pas adapté aux changements d'angle et occlusions, du fait de sa structure. L'algorithme prend de 10 secondes à 2 minutes à tourner sur mon ordinateur (Intel Core Duo 2 Ghz), pour des images de taille inférieure à 400x400, et en gardant une taille de 3 à propos du nombre de descripteurs retournés par la fonction harris.m. 4) Résultats Exemple de triangles superposés Voici quelques exemples de résultats commentés (ils sont disponibles en meilleur résolution avec d'autres exemple non commentés en pièce jointe du mail). 4.1. Exemple 1 : chat sur sol bleu Exemple 1, Image 1 Exemple 1, Image 2 Exemple 1, image intermédiaire Dans cet exemple, le mouvement est très faible (corps du chat, la tête un peu plus), et la caméra bouge légèrement. L'algorithme trouve bien le déplacement global de la caméra, un peu le mouvement du corps, et pas du tout le mouvement de la tête. Ces résultats sont plutôt compréhensibles : l'algorithme favorise les mouvements à peu près globaux (pour une question de robustesse), mais n'est pas efficace pour trouver des mouvements intermédiaires lorsqu'il y a des occlusions (comme pour la tête du chat). Paramètres : bool_rapport=0.5; gaussian_factor=100; limit=-1; seuil=-1; limitDepl_x=-1; limitDepl_y=-1; 4.2. Exemple 2 : voiture sur une rivière Exemple 2, Image 1 Exemple 2, Image intermédiaire Exemple 2, Image 2 Exemple 2, Image 2 Dans cet exemple, les arbres sur les côtés sont bien déplacés, sauf au niveau de la bordure. Ceci est normal vu que les bords ne se déplacent pas : il en résulte donc une dilatation ou une compression peu agréable. L'arrière plan est cependant bien rendu. D'autre part, la voiture au centre est déplacée dans le mauvais sens. L'algorithme a du mal à traiter ce cas pour 3 raisons : la plupart des points d'intérêt se trouvent sur les arbres, la transformation est ici dans le sens inverse du mouvement global, et le mouvement est relativement « important ». Paramètres : bool_rapport=0.5;gaussian_factor=100; limit=50; seuil=-1;limitDepl_x=300; limitDepl_y=-1; 4.3 Exemple 3 : fête foraine Exemple 3, Image 1 Exemple 3, Image intermédiaire Exemple 3, image 2 Dans cet exemple, le déplacement de la caméra est assez important (les barrières métalliques en sont la preuve), les nuages changent, la roue tourne, un poteau en haut à droite et un individu en bas à gauche disparaissent. Il en résulte des objets déformés (la grande roue, les barrières), et l'apparition des contours de certains triangles très déformés. Ceci nous montre que l'algorithme n'est robuste que pour des petits mouvements : les prises de vue en mode rafale sont bien plus adaptées. Paramètres : bool_rapport=0.45; gaussian_factor=2; limit=5; seuil=-1; limitDepl_x=100; limitDepl_y=-1; 5) Améliorations possibles L'une des améliorations pourrait concerner les bords : au lieu de déformer les triangles des bords, on pourrait essayer de faire une translation entre l'image a et l'image b (pour un mouvement global de caméra). J'ai essayé de l'implémenter mais ça ne rendait vraiment pas bien au niveau des jointures. Comme suggéré dans votre email, on pourrait aussi utiliser à la fois des points de Harris et des SIFT pour augmenter le maillage. En cas de triangles superposés, il faudrait remailler localement, mais je ne vois pas trop comment faire... La plupart du temps, en jouant sur les paramètres, on n'arrive à supprimer ces défauts : les triangles superposés sont généralement dûs à des points d'intérêt mal matchés, et donc en affinant les valeurs, on peut les éviter. Une autre amélioration concerne le fait qu'on n'utilise qu'une des deux images pour effectuer la transformation. Si j'utilise les deux et que je fais une moyenne, le résultat est assez moyen car on voit juste deux images mal superposées... Peut-être en cherchant le maximum de corrélation, si les deux images sont suffisamment ressemblantes ? Les deux images transformées n'étaient pas assez similaires dans mon cas pour que cette idée fonctionne. Quelques jours avant la date de rendu du projet, j'ai entendu la présentation d'un cours au 2e semestre du master 2, qui s'intitule « géométrie et espace de forme », par Alain Trouvé. Dans ce cours, une méthode d'interpolation basée sur les géodésiques permettrait d'avoir des résultats vraiment efficaces sur des images intermédiaires. Je n'en sais pas plus pour l'instant...