2016-10-04 3 views
2

Nous avons une caméra stéréo USB à double objectif ELP de 1,0 mégapixel et nous essayons de la calibrer en utilisant OpenCV 3.1 en C++. Cependant, le résultat du calibrage est totalement inutilisable, car l'appel de stereoRectify twiste totalement l'image. C'est ce que nous faisons:OpenCV stereoRectify déforme l'image

modèle d'étalonnage Finding (jeu d'échecs) dans les deux caméras, la taille de jeu d'échecs est 5x7 et le résultat est presque identique quel que soit le nombre d'images prises

findChessboardCorners(img[k], boardSize, corners, CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE) 
cornerSubPix(img[k], corners, Size(11, 11), Size(-1, -1), TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01)); 

Tous les échiquiers sont correctement détectés qui est vérifiée à l'aide

drawChessboardCorners(img[k], boardSize, corners, bFound); 

Ensuite, nous calibrons chaque caméra séparément (mais cette étape ne semble pas être important pour l'étalonnage stéréo), mais nous pouvons l'utiliser pour vérifier chaque caméra séparément

calibrateCamera(objectPoints, imagePoints[k], Size(320, 240), cameraMatrix[k], distCoeffs[k], rvecs, tvecs, 0) 

Ensuite, nous faisons l'étalonnage stéréo

stereoCalibrate(objectPoints, imagePoints[0], imagePoints[1], cameraMatrix[0], distCoeffs[0], cameraMatrix[1], distCoeffs[1], 
    Size(320, 240), R, T, E, F, CALIB_USE_INTRINSIC_GUESS); 

Compute la rectification transform

stereoRectify(cameraMatrix[0], distCoeffs[0], cameraMatrix[1], distCoeffs[1], Size(320, 240), R, T, R1, R2, P1, P2, Q, 
    CALIB_ZERO_DISPARITY, 1, Size(320, 240), &validRoI[0], &validRoI[1]); 

Initialiser cartes pour remap

Mat rmap[2][2]; 
initUndistortRectifyMap(cameraMatrix[0], distCoeffs[0], R1, P1, Size(FRAME_WIDTH, FRAME_HEIGHT), CV_16SC2, rmap[0][0], rmap[0][1]); 
initUndistortRectifyMap(cameraMatrix[1], distCoeffs[1], R2, P2, Size(FRAME_WIDTH, FRAME_HEIGHT), CV_16SC2, rmap[1][0], rmap[1][1]); 
... 
remap(img, rimg, rmap[k][0], rmap[k][1], INTER_LINEAR); 
imshow("Canvas", rimg); 

Le résultat est l'image totalement déformée. Comme je l'ai dit au début, tous les modèles d'étalonnage/échiquier sont correctement détectés et si nous n'appelons pas la fonction stereoRectify, les images non déformées (après remappage) semblent parfaites. Le problème vient si nous appelons la fonction stereoRectify.

Y a-t-il quelque chose qui nous manque? Le nombre d'images d'étalonnage ne semble pas avoir

un effet (prenant parfois 2 images donne un meilleur résultat (mais pas encore utilisable) de 10 images) Ceci est l'exemple du modèle d'étalonnage. Nous prenons plusieurs orientations différentes:

enter image description here

Ceci est le résultat de l'étalonnage si nous ne remettons pas stereoRectify: enter image description here

Ceci est le résultat erroné si nous appelons stereoRectify (mais surtout il est beaucoup (pire): enter image description here

Merci d'avance pour toute aide que pourrait avoir tort.

Répondre

2

Hey avez-vous essayé de changer la valeur du paramètre alpha dans la fonction stereoRectify. Je me souviens qu'une fois que j'ai également obtenu de tels résultats et en changeant la valeur de alpha à 0, le travail a été fait pour moi. Faites-moi savoir les résultats que vous obtenez avec alpha = -1, alpha = 0.5 et alpha = 0

+0

Nous vous remercions de votre conseil. Cela m'a beaucoup aidé, mais j'ai remarqué ce qui suit: - CALIB_FIX_K3 doit au moins être passé dans CalibrateCamera et CALIB_SAME_FOCAL_LENGTH info stereoCalibrate sinon le résultat est totalement désordonné - J'obtiens RMS autour de 0.1 de calibrateCamera mais RMS très élevé autour de 20 de stereoCalibrate - bien que le résultat semble bon maintenant, l'image semble être un peu zoomée après remappage - J'ai 320x240, si je redimensionne manuellement l'image à 640x480 avant la détection de l'échiquier, puis redimensionner le résultat par 2.0, le résultat semble être parfait – bigmuscle

+0

Vous pouvez contrôler le niveau de zoom de l'image avec le paramètre alpha et avez-vous les extrinsèques de l'appareil photo corrects? Parce que dans mon cas le vecteur de traduction était éteint de 3-4 cm. Bien que ce ne soit pas pertinent, j'ajouterais que j'ai obtenu de meilleurs résultats avec CalTech ToolBox pour Matlab. –

+1

Le paramètre alpha affecte réellement le niveau de zoom. Cependant, tout ce qui est différent de alpha = 0 ondule les bords de l'image et l'entoure de zones noires (c'est compréhensible), mais le résultat le plus fin (= pas de distorsion, pas de torsion etc.) est alpha = 0 et upscaling l'image échiquier avant findChessboardCorners puis redimensionnement des coins détectés. – bigmuscle

4

Juste pour sumarize si quelqu'un a besoin d'aide similaire, ce que je fais pour obtenir le meilleur résultat lookable:

Haut de gamme l'image chessboard avant la détection d'angle:

Mat resized; 
resize(img[k], resized, Size(FRAME_WIDTH * 2, FRAME_HEIGHT * 2), 0.0, 0.0, INTER_LINEAR); 
findChessboardCorners(resized, boardSize, corners, CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE 

Downscale les coins détectés:

for (int i = 0; i < corners.size(); ++i) { 
    corners[i].x /= 2.0; 
    corners[i].y /= 2.0; 
} 

calibrer chaque appareil séparément:

double rms = calibrateCamera(objectPoints, imagePoints[k], Size(FRAME_WIDTH, FRAME_HEIGHT), cameraMatrix[k], distCoeffs[k], rvecs, tvecs, 
    CALIB_FIX_PRINCIPAL_POINT | CALIB_FIX_ASPECT_RATIO | CALIB_ZERO_TANGENT_DIST | CALIB_RATIONAL_MODEL | CALIB_FIX_K3 | CALIB_FIX_K4 | CALIB_FIX_K5); 

Calibrate caméra stéréo:

stereoCalibrate(objectPoints, imagePoints[0], imagePoints[1], cameraMatrix[0], distCoeffs[0], cameraMatrix[1], distCoeffs[1], 
    Size(FRAME_WIDTH, FRAME_HEIGHT), R, T, E, F, 
    CALIB_FIX_INTRINSIC | CALIB_SAME_FOCAL_LENGTH, 
    TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, 0)); 

rectification Compute (alpha = 0,0):

stereoRectify(cameraMatrix[0], distCoeffs[0], cameraMatrix[1], distCoeffs[1], Size(FRAME_WIDTH, FRAME_HEIGHT), 
    R, T, R1, R2, P1, P2, Q, 
    CALIB_ZERO_DISPARITY, 0.0, Size(FRAME_WIDTH, FRAME_HEIGHT), &validRoI[0], &validRoI[1]); 

Ce sont les matrices de résultats d'étalonnage

Intrinsics:

M1: !!opencv-matrix 
    rows: 3 
    cols: 3 
    dt: d 
    data: [ 2.6187262304487734e+02, 0., 1.5950000000000000e+02, 0., 
     2.6187262304487734e+02, 1.1950000000000000e+02, 0., 0., 1. ] 
D1: !!opencv-matrix 
    rows: 1 
    cols: 5 
    dt: d 
    data: [ -4.6768074176991381e-01, 2.0221327568191746e-01, 0., 0., 0. ] 
M2: !!opencv-matrix 
    rows: 3 
    cols: 3 
    dt: d 
    data: [ 2.6400975025525213e+02, 0., 1.5950000000000000e+02, 0., 
     2.6400975025525213e+02, 1.1950000000000000e+02, 0., 0., 1. ] 
D2: !!opencv-matrix 
    rows: 1 
    cols: 5 
    dt: d 
    data: [ -4.5713211677198845e-01, 2.8855737500717565e-01, 0., 0., 0. ] 

extrinsèques:

R: !!opencv-matrix 
    rows: 3 
    cols: 3 
    dt: d 
    data: [ 9.9963073433190641e-01, 4.6310793035473068e-04, 
     2.7169477545556639e-02, -6.9475632716349024e-04, 
     9.9996348636555088e-01, 8.5172324905818230e-03, 
     -2.7164541091274301e-02, -8.5329635354663789e-03, 
     9.9959455592785362e-01 ] 
T: !!opencv-matrix 
    rows: 3 
    cols: 1 
    dt: d 
    data: [ -6.1830090720273198e+01, 1.6774590574449604e+00, 
     1.8118983433925613e+00 ] 

enter image description here

Mon autre question est de savoir s'il y a des demandes spéciales pour les initialisations variables ou est-ce suffisant?

Mat cameraMatrix[2] = { Mat::eye(3, 3, CV_64F), Mat::eye(3, 3, CV_64F) }; 
Mat distCoeffs[2], R, T, E, F, R1, R2, P1, P2, Q; 
+0

Je pense que vous devriez poster une nouvelle question. – Abc