OpenCV 校正,图像 C++ 上有太多黑色区域

Posted

技术标签:

【中文标题】OpenCV 校正,图像 C++ 上有太多黑色区域【英文标题】:OpenCV Rectification with too much black areas on images C++ 【发布时间】:2014-04-23 12:32:03 【问题描述】:

我正在使用 OpenCV 来校准和校正立体声系统。我有一个眼睛会聚的立体相机,实际上我是按照这个顺序运行这些功能的:

for(int j=0; j < ChessBoard.numSquares; j++)
    obj.push_back(Point3f((j/ChessBoard.numCornersHor)*ChessBoard.squareDim, (j%ChessBoard.numCornersHor)*ChessBoard.squareDim, 0.0f));
[...]

然后我循环它以获得我想要获取的图像的数量

found_L = findChessboardCorners(image_L, ChessBoard.board_sz, corners_L, CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CV_CALIB_CB_FILTER_QUADS + CALIB_CB_FAST_CHECK);
found_R= findChessboardCorners(image_R, ChessBoard.board_sz, corners_R, CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE + CV_CALIB_CB_FILTER_QUADS + CALIB_CB_FAST_CHECK);
found = found_L && found_R;
if(found)
   
    cornerSubPix(image_L, corners_L, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
    cornerSubPix(image_R, corners_R, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
    drawChessboardCorners(image_L, ChessBoard.board_sz, corners_L, found);
    drawChessboardCorners(image_R, ChessBoard.board_sz, corners_R, found);

    image_points[0].push_back(corners_L);
    image_points[1].push_back(corners_R);
    object_points.push_back(obj);
    printf("Right: coordinates stored\n");
    printf("Left: coordinates stored\n");
  

在这个块之后我称之为两个:

cameraMatrix[0] = Mat::eye(3, 3, CV_64F);
cameraMatrix[1] = Mat::eye(3, 3, CV_64F);

calibrateCamera(object_points, image_points[0], imageSize, cameraMatrix[0], distCoeffs[0], rvecs_L, tvecs_L);

calibrateCamera(object_points, image_points[1], imageSize, cameraMatrix[1], distCoeffs[1], rvecs_R, tvecs_R);

然后:

rms = stereoCalibrate(object_points, image_points[0], image_points[1],
                    cameraMatrix[0], distCoeffs[0],
                    cameraMatrix[1], distCoeffs[1],
                    imageSize, R, T, E, F,
                    TermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 100, 1e-5),
                    CV_CALIB_FIX_ASPECT_RATIO+CV_CALIB_FIX_INTRINSIC);

终于:

stereoRectify(cameraMatrix[0], distCoeffs[0],
                  cameraMatrix[1], distCoeffs[1],
                  imageSize, R, T, R1, R2, P1, P2, Q,
                  CALIB_ZERO_DISPARITY, -1, imageSize, &roi1, &roi2 );

initUndistortRectifyMap(cameraMatrix[0], distCoeffs[0], R1, P1, imageSize, CV_16SC2, map11, map12);
initUndistortRectifyMap(cameraMatrix[1], distCoeffs[1], R2, P2, imageSize, CV_16SC2, map21, map22);
remap(imgL, imgL, map11, map12, INTER_LINEAR,BORDER_CONSTANT, Scalar());
remap(imgR, imgR, map21, map22, INTER_LINEAR,BORDER_CONSTANT, Scalar());

这基本上是我正在做的,但结果非常糟糕,因为图像有一个非常大的黑色区域。这是一个例子:

这是我必须获得的校正图像,直接从相机拍摄:

如您所见,图像似乎在右侧平移并剪切,右侧相同但在左侧平移,结果几乎相同。

那么我怎样才能获得类似于上一个更好的结果呢?哪里有问题? 作为附加数据,我注意到 rms 不太好,大约为 0.4,重投影误差约为 0.2,我知道它们一定要低一些,但我已经尝试了很多次不同的图案、照明和以此类推,在校准中,但我总是得出相同的结果,甚至是最差的结果。

【问题讨论】:

【参考方案1】:

尝试像这样调用stereoRectify

stereoRectify(cameraMatrix[0], distCoeffs[0],
              cameraMatrix[1], distCoeffs[1],
              imageSize, R, T, R1, R2, P1, P2, Q,
              0, -1, imageSize, &roi1, &roi2 );

即使用0而不是标志CALIB_ZERO_DISPARITY

另外,为了提高stereoCalibrate获得的RMS,尝试使用标志CV_CALIB_USE_INTRINSIC_GUESS(见this related answer):

rms = stereoCalibrate(object_points, image_points[0], image_points[1],
                cameraMatrix[0], distCoeffs[0],
                cameraMatrix[1], distCoeffs[1],
                imageSize, R, T, E, F,
                TermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 100, 1e-5),
                CV_CALIB_USE_INTRINSIC_GUESS+
                    CV_CALIB_FIX_ASPECT_RATIO+CV_CALIB_FIX_INTRINSIC);

【讨论】:

这解决了主要问题,我看到了一个很好的视差图,但是现在我用于 reprojectImageTo3D 的 Q 矩阵真的很糟糕。我将结果用于距离计算并在可视化器中查看 3D 重建,但现在甚至不像以前那样接近事实。所以 Q 矩阵不能以这种方式很好地计算出来。为什么? @Elminster_cs 找出为什么reprojectImageTo3D 的结果不好需要额外的数据。您能否就该主题提出一个新问题并包括适当的代码(致电reprojectImageTo3D 等)和图片?在此处发布指向该新问题的链接作为评论,以便与该问题保持联系。谢谢。 重新项目的问题是一个简单的转换:我使用的是 disptype==CV_16S 而我需要一个 32F。所以我只是输入: disp.convertTo(disp16, CV_32F, 1./16);现在正在工作,谢谢!

以上是关于OpenCV 校正,图像 C++ 上有太多黑色区域的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV:创建一个透明蒙版?

opencv打印奇怪的黑色图像

怎么用opencv和python,只保留深蓝色部分,其他区域变为黑色

从黑色背景OpenCV C++中提取对象

将灰度图像中的像素转换为黑色(OpenCV)会导致意外结果?

opencv鱼眼图像畸变校正——标定校正