“在线” cv:stereoCalibration 时出现高 RMS 错误

Posted

技术标签:

【中文标题】“在线” cv:stereoCalibration 时出现高 RMS 错误【英文标题】:High RMS error while "online" cv:stereoCalibration 【发布时间】:2016-12-01 14:34:32 【问题描述】:

我有两个水平设置的摄像机(彼此靠近)。我有左摄像头 cam1 和右摄像头 cam2。

首先我校准相机(我想校准 50 对图像):

    我使用 cv::calibrateCamera() 分别校准两个摄像头 我使用 cv::stereoCalibrate() 校准立体声

我的问题:

    在 stereoCalibrate - 我认为相机数据的顺序很重要。如果来自左侧摄像头的数据应该是 imagePoints1,而来自右侧摄像头的数据应该是 imagePoints2,反之亦然,或者只要程序的每个点的摄像头顺序相同,这并不重要? 在 stereoCalibrate - 我得到大约 15,9319 的 RMS 误差和大约 8,4536 的平均重投影误差。如果我使用来自相机的所有图像,我会得到该值。在其他情况下:首先我保存图像,我选择整个棋盘可见的对(所有棋盘的方块都在相机视图中,并且每个方块都完整可见)我得到大约 0.7 的 RMS。如果这意味着只有离线校准是好的,如果我想校准相机,我应该手动选择好的图像?或者有什么方法可以在线进行校准?在线是指我开始从相机捕获视图,并且在每个视图中我都找到了棋盘角,并在停止从相机捕获视图后校准相机。 我只需要四个失真值,但我得到了其中的五个(使用 k3)。在旧的 api 版本 cvStereoCalibrate2 我只有四个值,但在 cv::stereoCalibrate 我不知道该怎么做?是否有可能或唯一的方法是获取 5 个值并在以后只使用其中的四个?

我的代码:

Mat cameraMatrix[2], distCoeffs[2];
distCoeffs[0] = Mat(4, 1, CV_64F);
distCoeffs[1] = Mat(4, 1, CV_64F);

vector<Mat> rvec1, rvec2, tvec1, tvec2;

double rms1 = cv::calibrateCamera(objectPoints, imagePoints[0], imageSize, cameraMatrix[0], distCoeffs[0],rvec1, tvec1, CALIB_FIX_K3, TermCriteria(
                                     TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON));

double rms2 = cv::calibrateCamera(objectPoints, imagePoints[1], imageSize, cameraMatrix[1], distCoeffs[1],rvec2, tvec2, CALIB_FIX_K3, TermCriteria(
                                     TermCriteria::COUNT+TermCriteria::EPS, 30, DBL_EPSILON));

qDebug()<<"Rms1: "<<rms1;
qDebug()<<"Rms2: "<<rms2;

Mat R, T, E, F;

double rms = cv::stereoCalibrate(objectPoints, imagePoints[0], imagePoints[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_INTRINSIC+
   CV_CALIB_SAME_FOCAL_LENGTH);

【问题讨论】:

【参考方案1】:

我遇到了类似的问题。我的问题是我通过假设两者都已排序来读取左侧图像和右侧图像。这里是Python中的一部分代码 我通过在第二行中使用“排序”来修复。

images = glob.glob(path_left)
for fname in sorted(images):
    img = cv2.imread(fname)
    gray1 = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # Find the chess board corners
    ret, corners1 = cv2.findChessboardCorners(gray1, (n, m), None)
    # If found, add object points, image points (after refining them)
    if ret == True:
        i = i + 1
        print("Cam1. Chess pattern was detected")
        objpoints1.append(objp)
        cv2.cornerSubPix(gray1, corners1, (5, 5), (-1, -1), criteria)
        imgpoints1.append(corners1)
        cv2.drawChessboardCorners(img, (n, m), corners1, ret)
        cv2.imshow('img', img)
        cv2.waitKey(100)

【讨论】:

【参考方案2】:

    相机/图像集的顺序之所以重要的唯一原因是您从stereoCalibrate 函数获得的旋转和平移。您首先放入函数的图像集作为基础。所以你得到的旋转和平移就是第二个摄像机是如何从第一个摄像机平移和旋转的。当然你可以把结果反过来,这和切换图像集是一样的。当然,这只有在两组中的图像相互对应(它们的顺序)时才成立。

    这有点棘手,但您得到如此大的 RMS 错误的原因很少。

    首先,我不确定您是如何检测棋盘角的,但如果看不到整个棋盘并且您提供了有效的棋盘模型,findChessboardCorners 应该返回 false,因为它没有检测到棋盘。因此,您可以自动(=在线)省略这些“无棋子”图像。当然,您还必须丢弃第二台相机中的图像,即使那个是有效的,以保持两组中的正确顺序。 第二个选项是对每张图像的所有角点进行反投影,并分别计算所有图像的重投影误差(不仅针对整个校准)。然后,您可以通过该误差选择最佳 3/4 图像,然后重新计算没有异常值的校准。 其他原因可能是来自 2 个摄像头的抓拍图像之间的时间同步。如果延迟很大并且您连续移动棋盘,那么您实际上是在尝试匹配略微平移的棋盘的投影。

    如果您想要强大的在线版本,恐怕您最终会选择第二个选项,因为它还可以帮助您摆脱图像模糊、光照条件导致的错误检测等问题。您只需要仔细设置阈值(将多少张图像作为异常值剪切),以免丢弃有效数据。

    我在这个领域不太确定,但我想说你可以计算其中的 5 个并且只使用 4 个,因为看起来你只是切断了泰勒级数的高阶。但我不能保证这是真的。

【讨论】:

以上是关于“在线” cv:stereoCalibration 时出现高 RMS 错误的主要内容,如果未能解决你的问题,请参考以下文章

在线使用在线软件来完成任务

一些有用的在线工具

一些有用的在线工具

一些有用的在线工具

集博文,项目,手册,在线工具,在线图书,在线代码,开发平台的网站

PHP语言在线代码运行编译工具推荐