什么是 cv::calibrateCamera 的"acceptable"返回值?
What is an "acceptable" return value from cv::calibrateCamera?
背景:
我目前正在使用OpenCV进行立体视觉项目。我正在尝试从一组两个校正图像中创建视差图,但我没有得到我期望的结果。查看校正后的图像时,图像之间存在明显的垂直偏移,校正后不应存在。我目前正在寻找错误可能是什么。我的代码基于 OpenCV 书中的立体声校准和对应代码,以及此示例。我使用OpenCV的C++界面。我的OpenCV版本是2.1,来自Ubuntu 11.04存储库。
问题的简短版本:
函数可接受的 RMS 返回值:
double cv::calibrateCamera(...)
我目前使用一组~20个棋盘图像对来校准每个相机。相机是两个相同的PS3眼睛(分辨率为640 * 480像素)并排安装。 cv::calibrateCamera
返回 160 到 300 之间的 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);
我为许多图像对执行此操作,并将结果点放在imagePointsLeft
和imagePointsRight
中。我已经在单独的程序中对相同的图像运行了检查,在该程序中,我直观地确认左右图像以相同的顺序正确注册了所有角落,使用 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
时,我使用此函数的相机内在(此处的文档中建议使用这种立体声校准方式)。
我继续打电话给cv::stereoRectify
和cv::initUndistortRectifyMap
,后者用于两个相机。校正后的图像是使用initUndistortRectifyMap
输出和摄像机实时馈送cv::remap
生成的。两个图像都仅包含有效像素(无黑色区域)。我的问题是给定行的像素与另一张图像中的同一行不匹配(有轻微的垂直偏移)。这使得很难从StereoBM等对应算法中获得任何良好的结果。
相机校准存在问题:cv::calibrateCamera()
返回均方根 (RMS) 重投影误差 [1],在良好的校准中应介于 0.1 和 1.0 像素之间。作为参考,我使用由两个硬件同步的Playstation Eye相机组成的自定义立体相机以640 x 480分辨率运行,得到大约0.25 px RMS错误。
您确定 cv::findChessboardCorners()
返回的像素坐标与 obj
中的像素坐标顺序相同吗?如果轴被翻转,你会得到类似于你所描述的症状。
[1]:OpenCV通过使用最终一组校准参数将棋盘点的三维投影到图像中并比较角的位置来计算重投影误差。RMS 误差为 300 意味着平均而言,这些投影点中的每一个都距离其实际位置 300 像素。
- 从python中调用C++函数并获取返回值
- 为什么模板类中的对象不能返回值
- 返回值优化:显式移动还是隐式
- lock_guard是否保护返回值
- 调用CreateProcess()并获取字符串的返回值
- 如何使 windows 命令提示符在C++可执行文件上显示返回值?
- 编译器警告:执行到达值返回函数的末尾而不返回值
- 查找 GCD:并非所有控制路径都返回值
- 在 Arduino 上使用 sscanf 会导致与 const char * 不匹配,并且返回值始终相同,尽管输入值不同
- 将返回值存储在函数指针数组的指针中是如何工作的?
- 如何从 std::thread 返回值
- 将返回值从 exe 传递到 bat,并将其传递给 C# 中的进程
- 方法错误"not all control paths return a value"和方法不返回值
- 如何读取 C++ SAFEARRAY**,该 SAFEARRAY** 是 COM 互操作的结果,其中 C# 返回值为
- 对fread的返回值感到困惑
- 程序不向函数返回值
- 如何在另一个函数中使用返回值作为参数?
- 如何使用 uint64_t 键类型从 std::map<int, std::string> 返回值?
- 使用 std::p air 进行返回值优化
- 什么是 cv::calibrateCamera 的"acceptable"返回值?