【问题标题】:What is an "acceptable" return value from cv::calibrateCamera?什么是 cv::calibrateCamera 的“可接受”返回值?
【发布时间】:2011-08-24 15:26:01
【问题描述】:

背景:

我目前正在使用 OpenCV 进行立体视觉项目。我正在尝试从一组两个校正图像创建视差图,但我没有得到我期望的结果。查看校正后的图像时,图像之间存在明显的垂直偏移,校正后不应存在。我目前正在寻找错误可能是什么。我的代码基于 OpenCV 书中的立体校准和对应代码以及this example。我使用 OpenCV 的 C++ 接口。我的 OpenCV 版本是 2.1,来自 Ubuntu 11.04 存储库。

简短的问题:

函数可接受的 RMS 返回值:

double cv::calibrateCamera(...)

我目前使用一组约 20 个棋盘图像对来校准每个相机。相机是两个相同的 PS3 Eyes(分辨率为 640*480 像素)并排安装。 cv::calibrateCamera 返回 160300 之间的 RMS 误差(我对不同的图像集有不同的结果)。这是该图像分辨率的可接受值还是我应该尝试获得更好的棋盘图像?

长版(详细信息、代码示例):

获得有效的立体视觉;首先,我想确保相机校准程序正常工作。我使用一系列棋盘图像来校准我的立体设置,如下所示:

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

我对许多图像对执行此操作,并将结果点放在imagePointsLeftimagePointsRight 中。我在一个单独的程序中对相同的图像运行了检查,在该程序中,我使用cv::drawChessboardCorners 目测确认左右图像以相同的顺序正确注册了所有角。对于每个图像对,我还填充了一组对象坐标,如下所示:

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

然后我尝试使用这些图像校准相机:

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

当我使用标志CV_CALIB_FIX_INTRINSIC 调用cv::stereoCalibrate 时,我使用此函数中的相机内在函数(文档中建议使用这种立体校准方式,here)。

我继续致电cv::stereoRectifycv::initUndistortRectifyMap,后者用于两台摄像机。通过cv::remap 使用initUndistortRectifyMap 的输出和相机实时馈送生成校正后的图像。两个图像都只包含有效像素(没有黑色区域)。我的问题是给定行的像素与另一张图像中的同一行不匹配(有轻微的垂直偏移)。这使得 StereoBM 等对应算法很难得到任何好的结果。

【问题讨论】:

    标签: c++ opencv computer-vision


    【解决方案1】:

    您的相机校准存在问题:cv::calibrateCamera() 返回均方根 (RMS) 重投影误差 [1],在良好校准中应介于 0.1 和 1.0 像素之间。作为参考,我使用我的自定义立体相机得到大约 0.25 px RMS 误差,该相机由两个硬件同步的 Playstation Eye 相机组成,分辨率为 640 x 480。

    您确定cv::findChessboardCorners() 返回的像素坐标与obj 中的像素坐标顺序相同吗?如果轴被翻转,您会得到与您所描述的症状相似的症状。

    [1]:OpenCV 通过使用最终的校准参数集将棋盘点的三维投影到图像中并比较角的位置来计算重投影误差。 300 的 RMS 误差意味着,这些投影点中的每一个平均距离其实际位置 300 像素。

    【讨论】:

    • 感谢您的快速回复!现在我知道要寻找什么了。拍摄校准图像时,我会尝试一些不同的设置。
    • @Michael:你是说 cv::calibrateCamera() 吗? findChessboardCorners() 不返回错误值。
    • @neuviemeporte 是的,你完全正确。我已经更正了我原来的帖子。
    • @MichaelKoval 你从哪里得到这个范围 - 0.1 到 1.0?我很难超过 1.3。
    • @CameronLowellPalmer 这不是硬性规定。在实践中,我发现良好的校准会给我带来亚像素再现误差。您可以实现的实际错误很大程度上取决于您的相机和您使用的镜头类型(即它是否与 OpenCV 的失真模型之一匹配)。
    猜你喜欢
    • 1970-01-01
    • 2015-06-20
    • 1970-01-01
    • 1970-01-01
    • 2012-02-07
    • 1970-01-01
    • 2012-02-12
    • 2015-11-08
    • 2016-02-07
    相关资源
    最近更新 更多