# VPOA - Alexandre GIRARD - Titouan LE FALHER - Martin SACONNEY # TP1 ## Vision Monoculaire ### Calibration 1- On a disposition une mire quadrillée, une mire à points symétriques et une à points assymétriques. TODO (On a disposition une mire en damier dont la détection se fait en détectant des intersections entre les carrés.) 3- ``imgPoints`` correspond à la position de chaque coins dans la frame (dans l'espace image). ``objectpoints`` correspond à la position réel de chaque coins sur la checkboard (dans l'espace monde). 5- La fonction prend en paramètres les `objectPoints`, `imgPoints` et `imgSize`. Les valeurs sont obtenues en utilisant l'algorithme d'optimisation de Levenberg-Marquardt pour minimiser l'erreur la **RMS** 6- RMS : 1.76 Coefficients de distorsion : [ 0.04273489 -0.04655174 -0.0299877 0.022758720.02076316] Intrisic values : [[3.95907204e+01] [4.70289529e+01] [3.48579114e+01] [8.30977658e+01] [7.02127413e-02] [6.71683141e-02][1.69206364e-02] [5.63539157e-03] [2.79156992e-02][0.00000000e+00] [0.00000000e+00] [0.00000000e+00][0.00000000e+00] [0.00000000e+00] [0.00000000e+00] [0.00000000e+00] [0.00000000e+00] [0.00000000e+00] La **RMS** correspond à l'erreur quadratique moyenne entre les valeurs de références et les valeurs obtenues après optimisation des valeurs intrinsèques, extrinsèques et de distortion. Si la **RMS** est élévée, la camera nécessite une correction plus importante. 7- ![](https://i.imgur.com/RkDiOWa.png) La figure représente la position dans l'espace 3D des mires acquises dans les photos ainsi que la position de la caméra. 8- ![](https://i.imgur.com/ptj5LJ1.png) La figure représente l'ensemble des RMS pour chaque photo. On se rend compte que certaines photos ne sont pas pertinentes ce qui peut s'expliquer par des conditions de photos non-optimales. 9- Pour améliorer les résultats on pourraient supprimer les photos présentant une RMS trop importante qui faussent nos résultats. Il faudrait aussi faire attention à la capture des différentes photos et bien respecter les étapes pour prendre les photos. 10- En appliquant ces étapes on obtient les résultats suivants. RMS : 0.66 Coefficients de distorsion : [-2.09309376e+00 8.81474179e+01 2.41468786e-01 6.02433961e-02 -8.58966506e+02] Intrisic values : [[3.82733067e+02] [1.90173199e+02] [8.03813213e+01] [5.63760069e+01] [7.48608767e-01] [1.85255845e+01] [4.48457764e-02] [3.87583738e-02] [2.85975075e+02] [0.00000000e+00] [0.00000000e+00] [0.00000000e+00] [0.00000000e+00] [0.00000000e+00] [0.00000000e+00] [0.00000000e+00] [0.00000000e+00] [0.00000000e+00]] ![](https://i.imgur.com/cMNpDym.png) ### Rectification 11- `getOptimalNewCameraMatrix` va raffiner la matrice de la camera et `initunDistortRectifyMap` va créer les transformation de rectification et de non-distorsion pour pouvoir les appliquer sur une image distordue 13- Le paramètre **alpha** est un paramètre qui modifie l'échelle de l'image rectifiée. Les paramètres xRatio et yRatio permettent un étirement de l'image en longueur et hauteur respectivement. 14- On peut observer une distorsion radiale positive avec un effet "bombé" au centre de l'image. 15- La plupart des caméras ont des défauts de distorsion, qui sont facilement recalibrables avec une mire lors d'une capture correcte des images. ## Stéreovision ### Calibration 16- Comme pour `calibrateCameraExtended`, on a les `objPoints` et les `imgPoints` excepté qu'étant donné que l'on travaille sur 2 caméras on a cette fois-ci 2 `imgPoints`, un pour chaque caméra. La fonction va essayer d'optimiser les paramètres intrinsèques et extrinsèques des 2 caméras. On aura ainsi en retour de fonction 2 `cameraMatrix` et `distCoeffs`. 17- On obtient ces valeurs là à la toute première calibration. Nous nous sommes rendus compte que nous devions faire quelques ajustements sur certaines images qui posaient problèmes RMS: 224.77055467026935 Left distortion coefficients: [-0.04390567 0.00033051 -0.0119769 -0.00343517 0. ] Right distortion coefficients: [ 0.20487761 -0.01197686 0.40007974 -0.02255972 0. ] Après suppression des images aberrantes nous obtenons ces résultats : RMS: 0.18 Left distortion coefficients: [-0.26239183 0.13485141 0.00045677 0.000344-0.04091748] Right distortion coefficients: [-0.26061958 0.13072332 0.00043855 0.00067861-0.03674215] 18- ![](https://i.imgur.com/5UpqJxY.png) ### Rectification 18- L'intérêt de la stéréo-rectification est d'appliquer des rectifications à des caméras en stéréos mais aussi de pouvoir faire de la reconstruction 3D. Avec OpenCV il faut utiliser la fonction `stereoRectify`. Elle prend en paramètres la matrice caméra, les coefficients de distorsion pour chaque caméra, ainsi que la matrice de rotation et de translation de la caméra 1 à la caméra 2. 19- On observe des déformations importantes dûes à la correction sur les bordures des images. Les images d'origine possèdent une très forte distorsion radiale. 20- Avec les droites épipolaires, on cherche à savoir si les droites passent par les mêmes points dans les deux images. Avec nos résultats, nous pouvons voir que les droites passent à peu près par les mêmes points (on peut cependant noter un léger décalage). On peut en conclure que la calibration a été plutôt efficace. ### Reconstruction 3D 21- 22- 23- 24- # TP2 ## Segmentation 3D 1- Une acquisition RealSense est sous la forme d'un fichier d'extension `.ply` qui correspond à un nuage de points possédant une valeur RGB car il y a une correspondance avec une photo, ce qui, théoriquement, nous permet de dire qu'il y a autant de points que de pixels que de points trouvés entre 2 images. 4- On observe un nombre conséquent d'outliers à cause d'erreurs de projection et de la capture. ![](https://i.imgur.com/tMGxHUe.png) 5- Pour enlever les outliers on a utilisé la fonction `remove_statistical_outlier` qui va, en spécifiant le nombre de voisins à prendre en compte et un ratio, calculer la distance moyenne entre les points et regarder si la distance est inférieur au ratio, pour déterminer si un point est un outlier. ![](https://i.imgur.com/L02JSJI.png) 6- Pour calculer les normales on a utilisé la fonction `estimate_normals` qui va, pour chaque point, calculer sa normale en regardant les points adjacents. Le vecteur propre de celle-ci donne la normale au point considéré en analysant la matrice de covariance. L'alignement sert à uniformiser la direction des normales en donnant une direction privilégiée. En effet, l'heuristique précédente n'est sinon pas suffisante pour déterminer de manière stable quel côté d’une surface est l'intérieur La normalisation est la pour faciliter les calculs suivants. ![](https://i.imgur.com/iIHsY3c.png) 7- Pour déduire la normale au plan du sol on peut calculer la normale moyenne car on a gardé une bonne partie du sol. ![](https://i.imgur.com/rMDBxhk.png) 8- En faisant la normale moyenne on obtient ce vecteur : `[-0.03544495 0.92661147 0.37110546]` Pour aligner nos points avec la plan horizontal, on peut calculer la matrice de rotation entre la normale au sol et le vecteur (0,1,0) et appliquer cette rotation sur l'ensemble du nuage de points. 9- ![](https://i.imgur.com/85Q8Yxn.png) 10- ![](https://i.imgur.com/gYCB0kc.png) ## Contrôle qualité 12- La fonction `registration_icp` prend en paramètres: - Le nuage de points source, qu'on va vouloir bouger - Le nuage de points cible qu'on utilise pour se calibrer - Le nombre max de correspondances entre 2 points - La méthode d'estimation - Un critère de convergence Et elle retourne: - La matrice de transformation - Le score - L'erreur (RMSE) 13- 2 boîtes différentes segmentées ![](https://i.imgur.com/kQyy9I6.png) 14- L’algorithme choisit un sous-ensemble des points, fit un modèle, l’évalue sur l’ensemble des points, le conserve s'il est mieux que le meilleur rencontré jusque là, et recommence. - `fitness` mesure le ratio nombre de points dans la marge d’erreur/total, - `inlier_rmse` mesure l’erreur des points dans la marge. - `correspondence_set` l’ensemble des paires de points dans la marge d’erreur. ![](https://i.imgur.com/qMvE9eq.png) 15- L’algorithme point à point utilise la différence entre la position des points comme métrique d’erreur, tandis que celui point à plan mesure la distance entre le point transformé et le plan tangent à la surface au point source. 16- **Point to Point** ![](https://i.imgur.com/FMeQTAl.png) Le résultat est légèrement plus précis que le RANSAC tout seul. **Point to Plane** ![](https://i.imgur.com/iOnRyig.png) Les résultats sont vraiment hasardeux et non-déterministes. 18- # TP3 ## Création d'une image de référence 2- Nous allons utiliser la fonction d'OpenCV `getPerspectiveTransform` pour supprimer l'effet de perspective et n'avoir que la face de l'objet voulu. Les points sources correspondent aux positions des marqueurs dans notre image source, les coins de l'objet dans notre cas précis. Les points cibles/destinations correspondent aux positions des marqueurs dans l'image de destination, dans notre cas cela correspondra au coins `[[0,0], [0,1], [1,0], [1,1]]` pour remplir totalement l'image avec la face de notre objet. 5- Pour corriger la perspective nous allons utiliser la fonction `warpPerspective` 6- Image de départ ![](https://i.imgur.com/2xqaUl9.png) Image corrigée ![](https://i.imgur.com/OKFCFXt.png) ## Tracking 7- Comme vu en cours on pourrait aussi utiliser SIFT ou FLUSH mais ceux-ci sont breuvetés donc pour nous utilisons ici ORB et AKAZE qui eux sont open-source. 10- En sortie de `matcher.knnMatch`, on récupère un array de matchs. Un match correspond à une paire d'indices des descripteurs pour l'image `query` et l'image `train` et une distance entre les descripteurs. 11- Dans le test de **Lowe** les matchs sont filtrés par leurs distances en utilisant un ratio que l'on peut modifier. 12- On voit des lignes reliant les différents matchs entre nos 2 images. **Ratio = 1.0** ![](https://i.imgur.com/4UydMtk.png) **Ratio = 0.75** ![](https://i.imgur.com/hGb65bH.png) Lorsqu'on diminue le ratio, le nombre de matchs diminue et ils sont plus pertinents. Cela s'explique grâce au ratio qui est la pour enlever les matchs non-pertinents avec une distance trop grande. 15- ![](https://i.imgur.com/hKZKkv7.png) On voit bien un quadrangle s'afficher sur l'écran mais il ne correspond pas du tout a la forme de la face transformée. Cela semble être dû aux outliers. Il faudrait pour résoudre ce problème, ne prendre que les matchs avec la distance la plus petite pour effectuer la transformation et non tous les matchs. 16- ![](https://i.imgur.com/13QY3ob.png) `accumulateWeighted` implémente de l’inertie de la manière suivante: current = (1 - inertia) * current + alpha * prev. 17- Déjà les résultats sont plus pertinents en utilisant **AKAZE** que **ORB** mais les performances en sont amoindries. Ensuite, les resultats sont forcément plus pertinents en ayant un ratio moins élévé mais au risque de ne pas avoir assez de matchs pour calculer l'homographie. ## Détection de pose 20- C’est un problème qui consiste en la détection de la position et rotation d’une camera étant donné des coordonnées de points dans l’espace-monde et leur projection sur le plan image. TODO 21-