Qu'est-ce qu'une valeur de retour "acceptable" de cv:: calibrateCamera?

Contexte:

Je travaille actuellement sur un projet de vision stéréo utilisant OpenCV. J'essaie de créer une carte de disparité à partir d'un ensemble de deux images rectifiées, mais je n'obtiens pas le résultat escompté. En regardant les images rectifiées, il y a un décalage vertical notable entre les images, qui ne devrait pas être là après la rectification. Je suis actuellement à la recherche de ce que l'erreur peut être. Mon code est basé sur le calibrage stéréo et le code de correspondance de le livre OpenCV, et cet exemple . J'utilise L'interface c++ D'OpenCV. Ma version OpenCV est 2.1, à partir du référentiel Ubuntu 11.04.

Version Courte de la question:

Quelle valeur de retour RMS est acceptable pour la fonction:

double cv::calibrateCamera(...)

Je calibre actuellement chaque caméra en utilisant un ensemble d'environ 20 paires d'images d'échiquier. Les caméras sont deux yeux PS3 identiques (avec une résolution de 640*480 pixels) montés l'un à côté de l'autre. cv::calibrateCamera renvoie une erreur RMS de entre 160 et 300 (j'ai eu un résultat différent avec différents ensembles d'images). Est-ce une valeur acceptable pour cette résolution d'image ou devrais-je essayer d'obtenir de meilleures images d'échiquier?

Version Longue (détails, des exemples de code):

Pour obtenir la vision stéréo de travail; tout d'abord, je veux être sûr que la routine d'étalonnage de la caméra fonctionne correctement. J'utilise une série d'images d'échiquier pour calibrer ma configuration stéréo, comme ceci:

// Find chessboard corners
cv::Mat left = ... //Load image
vector<cv::Point2f> points;

bool found = cv::findChessboardCorners(left, patternSize, points, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_NORMALIZE_IMAGE);
if(found)
  cv::cornerSubPix(left, points, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
imagePointsLeft.push_back(points);

Je le fais pour un nombre de paires d'images et mettre les points résultants dans imagePointsLeft et imagePointsRight. J'ai effectué une vérification dans un programme séparé sur les mêmes images où je confirme visuellement que les images gauche et droite enregistrent correctement tous les coins, dans le même ordre, en utilisant cv::drawChessboardCorners. Pour chaque paire d'images, je remplis également un ensemble de coordonnées d'objet comme ceci:

vector<cv::Point3f> obj;
for(int i = 0; i < ny; i++)
  for(int j = 0; j < nx; j++)
    obj.push_back(cv::Point3f(i*squareSize,j*squareSize,0.0));
objectPoints.push_back(obj);

J'essaie alors de calibrer les caméras avec ces images:

double rms = cv::calibrateCamera(objectPoints, imagePointsLeft, m_imageSize, m_cameraMatrixLeft, m_distortionMatrixLeft, rvecsLeft, tvecsLeft);

J'ai l'appareil photo intrinsèques de cette fonction lorsque j'appelle cv::stereoCalibrate en utilisant le drapeau CV_CALIB_FIX_INTRINSIC (cette méthode d'étalonnage stéréo est suggérée dans la documentation, ici ).

Je procède à l'appel cv::stereoRectify et cv::initUndistortRectifyMap, ce dernier pour les deux caméras. Les images rectifiées sont produites avec cv::remap en utilisant la sortie de initUndistortRectifyMap et une caméra livefeed. Les deux images ne contiennent que des pixels valides (pas de zones noires). Mon problème est que les pixels d'une ligne donnée ne correspond pas à la même ligne dans l'autre image (il y a un léger décalage vertical). De ce fait, il est difficile d'obtenir tout bon résultats d'algorithmes de correspondance tels que StereoBM.

23
demandé sur Angie Quijano 2011-05-13 08:38:15

1 réponses

Il y a un problème avec l'étalonnage de votre caméra: cv::calibrateCamera() renvoie l'erreur de reprojection RMS (root mean square) [1] et devrait être comprise entre 0,1 et 1,0 pixels dans un bon étalonnage. Pour un point de référence, je reçois une erreur RMS d'environ 0,25 px en utilisant ma caméra stéréo personnalisée composée de deux caméras PlayStation Eye synchronisées par le matériel fonctionnant à la résolution 640 x 480.

Êtes-vous sûr que les coordonnées de pixels renvoyées par cv::findChessboardCorners() sont dans le même ordre que celles de obj? Si les axes ont été retournés, vous obtiendrez des symptômes similaires à ceux que vous décrivez.

[1]: OpenCV calcule l'erreur de reprojection en projetant en trois dimensions des points d'échiquier dans l'image en utilisant l'ensemble final de paramètres d'étalonnage et en comparant la position des coins. Une erreur RMS de 300 signifie que, en moyenne, chacun de ces points projetés est à 300 px de sa position réelle.

24
répondu Michael Koval 2012-04-04 17:32:21