OpenCV stereoRectify扭曲图像

OpenCV stereoRectify扭曲图像

问题描述:

我们有一个ELP 1.0百万像素双镜头USB立体相机,我们正在尝试使用C++中的OpenCV 3.1进行校准。但是,校准的结果完全不可用,因为调用stereoRectify会完全颠倒图像。这是我们做什么:OpenCV stereoRectify扭曲图像

查找校准(棋盘)在这两个摄像头的图案,棋盘大小的5x7且不论结果几乎一样采取

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)); 

图像的数量所有棋盘正确检测出是使用

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

然后我们单独校准每个相机(但是这一步似乎并没有被用于立体声校准很重要),但我们可以用它来单独验证每个摄像头

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

然后我们做立体校准

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); 

计算整改变换

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]); 

初始化地图重映射

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); 

结果是完全扭曲的图像。正如我在开始时所说的,所有校准/棋盘模式都可以正确检测到,如果我们不调用stereoRectify函数,那么未失真的图像(重新映射后)看起来很完美。如果我们调用stereoRectify函数,问题就来了。

有什么我们错过了吗? 校准图像的数量似乎没有任何影响(有时,2张图像比10张图像提供更好的结果(但仍不可用))

这是校准图案的示例。我们采取几种不同的方向:

enter image description here

这是校准的结果,如果我们不叫stereoRectify: enter image description here

这是错误的结果,如果我们称之为stereoRectify(但大多获得了很多更糟糕): enter image description here

在此先感谢您的任何帮助,可能是错误的。

嘿你有没有试过改变函数stereoRectify中参数alpha的值。我记得一旦我也获得了这样的结果,并且将α的值改为0就为我做了工作。 请让我知道你用alpha = -1,alpha = 0获得的结果。5和α= 0

+0

感谢您的建议。它帮助了很多,但我注意到以下几点: - 至少CALIB_FIX_K3需要传递到CalibrateCamera和CALIB_SAME_FOCAL_LENGTH info stereoCalibrate否则结果是完全混淆的 - 我得到的RMS距离calibrateCamera约为0.1,但距离stereoCalibrate约为20的RMS非常高 - 虽然现在看起来效果不错,但图像在重映射后似乎变得稍微变大了 - 我有320x240,如果我在棋盘检测之前手动将图像大小调整为640x480,然后将结果缩小2.0,结果似乎是完美的 – bigmuscle

+0

您可以使用参数alpha控制图像的缩放级别,并且您是否拥有正确的相机外观?因为在我的情况下翻译矢量是3-4厘米。虽然它不相关,但我会补充说,使用CalTech ToolBox for Matlab可以获得更好的结果。 –

+1

Alpha参数确实影响缩放级别。但是,与alpha = 0不同的任何东西都会使图像边缘产生波动,并将其围绕黑色区域(这是可以理解的),但是我得到的最好结果(=不失真,无扭曲等)与alpha = 0并且在放大棋盘图像之前findChessboardCorners,然后缩小检测到的角落。 – bigmuscle

只是为了sumarize如果有人需要类似的帮助,这是我做的,以获得最佳lookable结果:

高档角落检测之前的棋盘图像:

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 

下限值所检测到的角:

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

校准每个摄像机分别:

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); 

校准立体摄像机:

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)); 

计算整流(具有α= 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]); 

这些校准结果矩阵

内在函数:

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. ] 

个外部参数:

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

我的另一个问题是,是否有对变量初始化任何特殊要求,或是否足够呢?

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

我想你应该发布一个新问题。 – Abc