在线"在线"高RMS错误CV:stereoCalibration

时间:2016-12-01 14:34:32

标签: visual-studio opencv camera-calibration

我有两个水平设置的相机(彼此靠近)。我离开了摄像机cam1和右摄像机cam2。

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

  1. 我使用cv :: calibrateCamera()
  2. 分别校准两个摄像机
  3. 我使用cv :: stereoCalibrate()
  4. 校准立体声

    我的问题:

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

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

2 个答案:

答案 0 :(得分:0)

我有类似的问题。我的问题是我正在阅读左图像和右图像,假设两者都已分类。这是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)

答案 1 :(得分:0)

  1. 唯一重要的原因是摄像机/图像集的顺序是从stereoCalibrate函数获得的旋转和平移。首先放入函数中的图像集将作为基础。因此,您得到的旋转和平移就是第二台摄像机如何从第一台摄像机平移和旋转。当然,您可以反转结果,这与切换图像集相同。当然,只有两组中的图像相互对应(它们的顺序)时,这种情况才会成立。

  2. 这有点棘手,但是有几个原因导致您收到此大RMS错误。

    • 首先,我不确定如何检测棋盘角,但是如果整个棋盘不可见并且您提供有效的棋盘模型,findChessboardCorners应该返回false,因为它不会检测到棋盘。因此,您可以自动(=在线)忽略这些“简单的”图像。当然,即使那个摄像机是有效的,您也必须丢弃第二台摄像机的图像,以保持两组正确的顺序。
    • 第二个选项是对每个图像的所有角进行反投影,并分别计算所有图像的重投影误差(不仅适用于整个校准)。然后,您可以通过该误差选择最佳的3/4图像,然后重新计算校正值而没有异常值。
    • 其他原因可能是从2个摄像机捕捉图像之间的时间同步。如果延迟很大,并且您不断移动棋盘,则实际上是在尝试匹配稍微平移的棋盘的投影。

    如果您想要强大的在线版本,恐怕您将获得第二种选择,因为它可以帮助您消除模糊的图像,由于光照条件而导致的错误检测等。您只需要仔细设置阈值(您将剪切多少张图像作为离群值),以免丢弃有效数据。

  3. 在该领域我不确定,但是我想说您可以计算出其中的5个并仅使用4个coz,就好像您切断了泰勒级数的更高阶。但是我不能保证这是真的。