来自cv :: calibrateCamera的"可接受"返回值是多少?

Ork*_*rka 24 c++ opencv computer-vision

背景:

我目前正在使用OpenCV开展立体视觉项目.我正在尝试从一组两个校正的图像创建一个视差图,但我没有得到我期望的结果.在查看校正后的图像时,图像之间会有明显的垂直偏移,整改后不应该出现这种情况.我正在寻找错误可能是什么.我的代码基于OpenCV书籍和本例中的立体声校准和对应代码.我使用OpenCV的C++接口.我的OpenCV版本是2.1,来自Ubuntu 11.04存储库.

问题的简短版本:

函数可接受的RMS返回值是多少:

double cv::calibrateCamera(...)
Run Code Online (Sandbox Code Playgroud)

我目前使用一组~20个棋盘图像对来校准每个摄像机.相机是两个相同的PS3眼睛(分辨率为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);
Run Code Online (Sandbox Code Playgroud)

我为多个图像对执行此操作,并将结果点放入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);
Run Code Online (Sandbox Code Playgroud)

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

double rms = cv::calibrateCamera(objectPoints, imagePointsLeft, m_imageSize, m_cameraMatrixLeft, m_distortionMatrixLeft, rvecsLeft, tvecsLeft);
Run Code Online (Sandbox Code Playgroud)

我当我打电话用相机内在这个函数cv::stereoCalibrate使用标志CV_CALIB_FIX_INTRINSIC(立体声校准这样建议的文件中,在这里).

我继续呼吁cv::stereoRectifycv::initUndistortRectifyMap,对于相机的后者.cv::remap使用initUndistortRectifyMap相机和相机的输出生成校正后的图像.两个图像仅包含有效像素(无黑色区域).我的问题是给定行的像素与另一个图像中的同一行不匹配(存在轻微的垂直偏移).这使得很难从诸如StereoBM之类的对应算法中获得任何好的结果.

Mic*_*val 27

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

你确定返回的像素坐标cv::findChessboardCorners()与那些中的相同obj吗?如果轴被翻转,您将得到类似于您描述的症状.

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