OpenCV stereoRectify扭曲图像

big*_*cle 3 c++ opencv camera-calibration

我们有一个ELP 1.0百万像素双镜头Usb立体相机,我们正在尝试使用C++中的OpenCV 3.1进行校准.但是,校准的结果完全无法使用,因为调用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));
Run Code Online (Sandbox Code Playgroud)

正确检测所有使用的棋盘

drawChessboardCorners(img[k], boardSize, corners, bFound);
Run Code Online (Sandbox Code Playgroud)

然后我们分别校准每个摄像机(但这一步似乎对立体声校准不重要),但我们可以用它来分别验证每个摄像机

calibrateCamera(objectPoints, imagePoints[k], Size(320, 240), cameraMatrix[k], distCoeffs[k], rvecs, tvecs, 0)
Run Code Online (Sandbox Code Playgroud)

然后我们做立体声校准

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);
Run Code Online (Sandbox Code Playgroud)

计算整流变换

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]);
Run Code Online (Sandbox Code Playgroud)

初始化重映射的映射

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);
Run Code Online (Sandbox Code Playgroud)

结果是完全扭曲的图像.正如我在开始时说,所有校准/棋盘图案被正确地检测,如果我们不叫stereoRectify功能,图像不变形(重映射后)看起来很完美.如果我们调用stereoRectify函数就会出现问题.

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

这是校准模式的示例.我们采取了几种不同的方向:

在此输入图像描述

如果我们不调用stereoRectify,这是校准的结果: 在此输入图像描述

如果我们调用stereoRectify(但大多数情况会变得更糟),这是错误的结果: 在此输入图像描述

在此先感谢任何帮助可能是错误的.

big*_*cle 6

如果有人需要类似的帮助,那就是为了获得最好的可观结果:

在角落检测之前升级棋盘图像:

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
Run Code Online (Sandbox Code Playgroud)

缩小检测到的角落:

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

分别校准每个摄像头:

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);
Run Code Online (Sandbox Code Playgroud)

校准立体相机:

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));
Run Code Online (Sandbox Code Playgroud)

计算校正(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]);
Run Code Online (Sandbox Code Playgroud)

这些是校准结果矩阵

内部函数:

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. ]
Run Code Online (Sandbox Code Playgroud)

外部参数:

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 ]
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

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

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;
Run Code Online (Sandbox Code Playgroud)


小智 3

嘿,您是否尝试过更改函数stereoRectify 中参数alpha 的值。我记得有一次我也获得了这样的结果,并将 alpha 值更改为 0 为我完成了工作。请告诉我您在 alpha = -1、alpha=0.5 和 alpha =0 时获得的结果