我有两个水平设置的摄像头(彼此靠近)。我已经离开了相机cam1和右相机cam2。
首先我校准摄像机(我想校准50对图像):
- 我使用CV :: CalibrateCamera()() 分开校准这两个相机
- 我使用CV :: Stereocalibrate() 校准立体声
我的问题:
- 在立体校准中 - 我假设相机数据的顺序很重要。如果来自左相机的数据应为imagePoints1,而从右相机则应该是ImagePoints2或VICE,则无关紧要,只要在程序的每个点中相同的摄像机顺序相同?
- 在立体校准中 - 我在15,9319左右的RMS误差和8,4536左右的平均再投影误差。如果我使用来自相机的所有图像,我会得到该值。在其他情况下:首先,我保存图像,选择对整个棋盘都可以看到的对(Chessborad的所有正方形都在相机视图中,并且每个正方形都可以在整体上看到)我的RMS左右为0,7。如果这意味着只有离线校准很好,并且如果我想校准相机,我应该手动选择好的图像?还是有某种方法可以在线进行校准?通过在线,我的意思是我从相机开始捕获视图,从每个视图中,我都找到了棋盘角,然后在相机上停止捕获视图后,我校准了相机。
- 我只需要四个变形值,但我得到了五个(带有K3)。在旧的API版本cvstereocalibrate2中,我只有四个值,但是在CV ::立体校准中,我不知道该怎么做?是否有可能或唯一的方法是获得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);
我也有类似的问题。我的问题是,我通过假设两者都是分类的,正在阅读左图和右图。这里是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)
-
唯一重要的是相机/图像集的顺序重要的是您从
stereoCalibrate
函数中获得的旋转和翻译。首先将您放入函数中的图像将其设置为基础。因此,您获得的旋转和翻译是第二摄像头从第一台相机翻译和旋转的方式。当然,您可以扭转结果,这与切换图像集相同。当然,只有两组中的图像相互对应(它们的顺序),这当然才能保持。 -
这有点棘手,但是您遇到这个大RMS错误的原因很少。
- 首先,我不确定您如何检测棋盘角,但是如果整个棋盘不可见并且提供有效的棋盘型号,则
findChessboardCorners
应该返回false,因为它无法检测到棋盘。因此,您可以自动(=在线)省略这些"无机"图像。当然,您也必须从第二摄像头上扔掉图像,即使是有效的,才能在两组中保留正确的订单。 - 第二选项是为每个图像的所有角落重新投影,并分别计算所有图像的再投影误差(不仅用于整个校准)。然后,您可以通过此错误选择最佳的3/4图像,并在没有异常值的情况下重新计算校准。
- 其他原因可能是从2个摄像机捕捉图像之间的时间同步。如果延迟很大,并且您连续使用棋盘移动,那么您实际上是在尝试匹配略微翻译的棋盘的预测。
如果您想要强大的在线版本,恐怕您最终会选择第二个选项,因为它也可以帮助您摆脱模糊的图像,由于光条件而导致的错误检测等。您只需要仔细设置阈值(您将剪切多少个图像)即可不丢弃有效的数据。
- 首先,我不确定您如何检测棋盘角,但是如果整个棋盘不可见并且提供有效的棋盘型号,则
-
我在这个领域不确定,但是我想您可以计算其中的5个,只使用四个COZ,看起来您只是切断了泰勒系列的更高顺序。但是我不能保证它是真的。