[PYTHON] Calibrage de la caméra

J'ai trouvé que la traduction suivante se trouve sur le site de l'Université Tottori.

[Calibration de la caméra et restauration 3D](http://labs.eecs.tottori-u.ac.jp/sd/Member/oyamada/OpenCV/html/py_tutorials/py_calib3d/py_table_of_contents_calib3d/py_table_of_contents_calib3d.html of-content-calib)

Ma traduction merdique n'est plus nécessaire.


"Tutoriels OpenCV-Python" en traduction japonaise Camera Calibration J'ai fait une traduction de. Texte original en 3.1

Comme il s'agit d'une mauvaise traduction, il peut y avoir des erreurs dans la traduction des termes et dans l'interprétation des phrases. Pour une solide compréhension "CV ouvert détaillé" Il est fortement recommandé de lire.

L'œuvre originale a depuis été publiée dans une version compatible avec OpenCV3. Learning OpenCV 3 Computer Vision in C++ with the OpenCV Library Je serais heureux si la traduction japonaise de

Correction: je donnais la mauvaise traduction pour la grille circulaire. Retraduit sous forme de grille de cercles. (07/05/2016)


Calibrage de la caméra {#tutorial_py_calibration}

Goal

Dans cette section

Basics

Les appareils photo à sténopé bon marché d'aujourd'hui ont beaucoup de distorsion. Les deux principales distorsions Distorsion radiale et distorsion circonférentielle.

La ligne droite semble pliée en raison de la distorsion radiale. L'effet augmente lorsque vous vous éloignez du centre de l'image. À titre d'exemple, une image est présentée ci-dessous. Les deux bords de l'échiquier sont indiqués par la ligne rouge. Cependant, vous remarquerez que les limites ne sont pas des lignes droites et ne coïncident pas avec les lignes droites rouges. Toutes les lignes droites attendues sont bombées vers l'extérieur. Pour plus de détails, voir [Distorsion] Veuillez demander (https://ja.wikipedia.org/wiki/%E6%AD%AA%E6%9B%B2%E5%8F%8E%E5%B7%AE).

image

Cette distorsion s'exprime par:

歪みの式

De même, l'autre distorsion est la distorsion circonférentielle, qui se produit dans les photographies prises avec des objectifs qui ne sont pas parfaitement parallèles au plan de l'image. Par conséquent, certaines zones de l'image peuvent apparaître plus proches que prévu. La distorsion est exprimée comme suit.

歪みの式2

En bref, vous devez trouver les cinq paramètres suivants appelés coefficients de déformation:

distortionCoef.png

Note du traducteur: La formule de correction lorsqu'il y a deux distorsions est décrite dans "OpenCV détaillé" p.399.

En plus de cela, vous devez trouver des informations. Paramètres internes et externes de la caméra. Les paramètres internes sont spécifiques à chaque caméra. Il contient des informations telles que la distance focale (\ f $ f_x, f_y \ f $) et le centre optique (\ f $ c_x, c_y \ f $). Aussi appelé matrice de caméra. Les paramètres internes sont réservés à la caméra, donc une fois calculés, ils peuvent être enregistrés pour une utilisation future. Les paramètres internes sont représentés par une matrice 3x3.

cameraMatrix.png

Les paramètres externes correspondent aux vecteurs de rotation et de mouvement qui mappent les coordonnées d'un point 3D à un autre système de coordonnées.

Pour les applications stéréo, ces distorsions doivent d'abord être corrigées. Tout ce que vous avez à faire pour trouver tous ces paramètres est de fournir de nombreux exemples d'images d'un modèle bien défini (par exemple, un échiquier). Trouvez plusieurs points caractéristiques (coins carrés de l'échiquier) dessus. Je connais les coordonnées dans ces espaces réels, et je connais les coordonnées dans l'image. Avec ces données, un problème mathématique est résolu dans les coulisses pour obtenir ce coefficient de distorsion. C'est un résumé de la situation dans son ensemble. Vous aurez besoin d'au moins 10 modèles de test pour obtenir de bons résultats.

Code

Comme mentionné ci-dessus, au moins 10 motifs de test sont nécessaires pour l'étalonnage de la caméra. OpenCV est livré avec plusieurs images d'échiquier. (Voir samples / cpp / left01.jpg --left14.jpg) Par conséquent, utilisez-le. Par souci de compréhension, considérez un seul échiquier. Les données d'entrée importantes requises pour l'étalonnage de la caméra sont un ensemble de points 3D dans l'espace réel et des points d'image 2D correspondants. Des points sur l'image 2D peuvent être facilement trouvés dans l'image. (Ces points d'image sont l'endroit où les deux carrés noirs se touchent sur l'échiquier.)

Note du traducteur: $(opencv)\sources\samples\data Il y a left01.jpg --left14.jpg dans.

Qu'en est-il des points 3D de l'espace réel? Ces images ont été prises à partir d'une caméra fixe et les échiquiers sont placés dans différentes positions et orientations. Vous devez donc savoir (X, Y, Z). Cependant, pour plus de simplicité, l'échiquier est dans le plan XY (c'est-à-dire toujours Z = 0) et vous pouvez supposer que la caméra se déplace. Avec cette considération, il vous suffit de trouver les valeurs X et Y. Comme pour les valeurs de X et Y, vous pouvez simplement passer plusieurs points à la manière de (0,0), (1,0), (2,0), .... Dans ce cas, le résultat obtenu est la valeur à l'échelle de la taille carrée (30 mm) de l'échiquier. Vous pouvez donc passer des valeurs telles que (0,0), (30,0), (60,0), ... et vous recevrez le résultat en mm. (Dans cet exemple, nous ne prenons pas ces images, donc nous ne connaissons pas la taille du carré, nous transmettons donc la taille du carré comme une unité.)

Les points 3D sont appelés ** points objet **, et les points sur les images 2D sont appelés ** points image **.

Setup

Pour trouver le motif de l'échiquier ** cv2.findChessboardCorners () ** Utilisez la fonction. Vous devez transmettre le type de motif que vous recherchez, par exemple une grille 8x8 ou une grille 5x5. Dans cet exemple, nous utilisons une grille 7x6. (Habituellement, un échiquier a un carré 8x8 et des coins internes 7x7.) La fonction renvoie plusieurs points d'angle et un retour qui renvoie True lorsqu'un motif est détecté. Ces coins sont dans l'ordre de gauche à droite et de haut en bas.

@sa Cette fonction peut ne pas trouver le motif requis dans toutes les images. Une bonne option dans ce cas est d'écrire le code, d'activer la caméra et de faire vérifier à chaque image le motif requis. Une fois que vous avez le motif, recherchez le coin et enregistrez-le dans la liste. Laissez un espace avant de lire l'image suivante. Cela permet à l'échiquier d'être ajusté dans une orientation différente. Continuez ce processus jusqu'à ce que vous ayez le nombre requis de bons modèles. Même dans l'exemple ici, nous ne savons pas combien de feuilles sont bonnes quand nous nous éloignons des 14 données. Par conséquent, toutes les images sont lues et traitées comme bonnes.

@sa Au lieu d'un échiquier, vous pouvez utiliser une grille circulaire. Dans ce cas, utilisez ** cv2.findCirclesGrid () ** pour trouver le modèle. Lors de l'utilisation d'une grille de cercles, on dit qu'un petit nombre est suffisant.

Une fois que vous avez trouvé un coin, vous pouvez utiliser ** cv2.cornerSubPix () ** pour améliorer la précision du coin. Vous pouvez dessiner des motifs en utilisant ** cv2.drawChessboardCorners () **. Toutes ces étapes sont incluses dans le code ci-dessous.

python


import numpy as np
import cv2
import glob

# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((6*7,3), np.float32)
objp[:,:2] = np.mgrid[0:7,0:6].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.

images = glob.glob('*.jpg')

for fname in images:
    img = cv2.imread(fname)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

    # Find the chess board corners
    ret, corners = cv2.findChessboardCorners(gray, (7,6),None)

    # If found, add object points, image points (after refining them)
    if ret == True:
        objpoints.append(objp)

        cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
        imgpoints.append(corners)

        # Draw and display the corners
        cv2.drawChessboardCorners(img, (7,6), corners2,ret)
        cv2.imshow('img',img)
        cv2.waitKey(500)

cv2.destroyAllWindows()

Ce qui suit est une image avec le motif écrit dessus.

image

Étalonnage

Maintenant que nous avons des points objets et des points image, nous sommes prêts à calibrer. Pour l'étalonnage, utilisez ** cv2.calibrateCamera () **. Cette fonction renvoie la matrice de la caméra, le facteur de distorsion, les vecteurs de rotation et de translation, etc.

python


ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)

Undistorsion

J'ai découvert que j'essayais de le faire. Maintenant, prenez une photo et corrigez la distorsion de cette photo. Il existe deux méthodes pour OpenCV. Il est montré ci-dessous. Mais avant cela, vous pouvez utiliser ** cv2.getOptimalNewCameraMatrix () ** pour améliorer la matrice de la caméra en fonction du paramètre de mise à l'échelle libre. Lors de la mise à l'échelle du paramètre alpha = 0, la fonction renvoie l'image corrigée de la distorsion d'une manière qui minimise les pixels que vous ne voulez pas. Par conséquent, vous souhaiterez peut-être supprimer certains pixels dans les coins de l'image. Lorsque alpha = 1, tous les pixels sont conservés et la partie sans les données d'origine devient une image noire. La fonction renvoie également le retour sur investissement de l'image et peut être utilisée pour recadrer le résultat.

Prenons maintenant une nouvelle image (nous utiliserons ici left12.jpg, la première image de ce chapitre).

python


img = cv2.imread('left12.jpg')
h,  w = img.shape[:2]
newcameramtx, roi=cv2.getOptimalNewCameraMatrix(mtx,dist,(w,h),1,(w,h))

Note du traducteur: left12.jpg peut être obtenu à partir de l'URL suivante. Https://github.com/rajatsaxena/OpenCV

1. Utilisez ** cv2.undistort () **

Ceci est une procédure rapide. Appelez la fonction et découpez le résultat en utilisant le retour sur investissement obtenu ci-dessus.

python


# undistort
dst = cv2.undistort(img, mtx, dist, None, newcameramtx)

# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png',dst)

2. Utilisation du remappage

Il s'agit d'une procédure détournée. Tout d'abord, recherchez la fonction de mappage de l'image déformée à l'image corrigée déformée. Ensuite, utilisez cette fonction de remappage.

python


# undistort
mapx,mapy = cv2.initUndistortRectifyMap(mtx,dist,None,newcameramtx,(w,h),5)
dst = cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR)

# crop the image
x,y,w,h = roi
dst = dst[y:y+h, x:x+w]
cv2.imwrite('calibresult.png',dst)

Les deux méthodes donnent le même résultat. Voir les résultats ci-dessous.

image

Dans l'image résultante, vous pouvez voir que tous les bords sont droits. Vous pouvez maintenant enregistrer la matrice de la caméra et le facteur de distorsion pour une utilisation ultérieure en utilisant les fonctions d'écriture de Numpy (np.savez, np.savetxt, etc.).

Erreur de re-projection

L'erreur de reprojection est un bon moyen d'évaluer la précision des paramètres trouvés. Il est souhaitable que la valeur soit aussi proche que possible de 0. Compte tenu des paramètres internes, de la distorsion, de la rotation et de la progression parallèle, utilisez d'abord ** cv2.projectPoints () ** pour convertir les points d'objet en points d'image. Ensuite, la norme de la différence entre le résultat de la conversion et l'algorithme de détection de coin (résultat) est calculée. Pour obtenir l'erreur moyenne, calculez la moyenne arithmétique de l'erreur pour toutes les images calibrées.

python


mean_error = 0
for i in xrange(len(objpoints)):
    imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
    error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
    tot_error += error

print "total error: ", mean_error/len(objpoints)

Additional Resources

Postscript par le traducteur "Calibrage de la caméra à l'aide d'un modèle polynomial d'ordre élevé d'un objectif ultra grand angle à faible distorsion" http://www.roboken.esys.tsukuba.ac.jp/~ohya/pdf/Robomech2014-KNS.pdf

Exercises

-# Try camera calibration with circular grid.


** Supplément par traducteur **

Supplément au "Calibrage de la caméra" des didacticiels OpenCV-Python J'ai fait un article séparé comme.

Liste des exemples de sources pour OpenCV 2.4.0 (samples / cpp)

https://github.com/YusukeSuzuki/opencv_sample_list_jp/blob/master/samples_cpp.rst Il est également utile de lire des exemples de programmes liés à la stéréo en C ++ à partir de.

Modèle Tsai

Tsai Camera Calibration http://homepages.inf.ed.ac.uk/rbf/CVonline/LOCAL_COPIES/DIAS1/ pyTsai - automated camera calibration in Python https://github.com/Csega/pyTsai/blob/master/doc/index.rst

Recommended Posts

Calibrage de la caméra
Comprendre visuellement l'étalonnage de la caméra
Utiliser le fichier d'étalonnage de la caméra avec OpenCvSharp4
Créez un modèle d'échiquier pour l'étalonnage de la caméra
Calibrage et utilisation de la caméra avec opencv-python [méthode chang]
Capture de caméra WEB
Supplément à "Calibration de la caméra" des didacticiels OpenCV-Python
[Windows] [Python] Calibrage de la caméra de l'objectif fisheye avec OpenCV