2

目前我正在实施立体视觉的校准方法。我正在使用 OpenCV 库。

示例文件夹中有一个示例,但我对实现有一些疑问:

这些数组的用途是什么?这些 CvMat 变量是什么?

// ARRAY AND VECTOR STORAGE:
double M1[3][3], M2[3][3], D1[5], D2[5];
double R[3][3], T[3], E[3][3], F[3][3];
CvMat _M1 = cvMat(3, 3, CV_64F, M1 );
CvMat _M2 = cvMat(3, 3, CV_64F, M2 );
CvMat _D1 = cvMat(1, 5, CV_64F, D1 );
CvMat _D2 = cvMat(1, 5, CV_64F, D2 );
CvMat _R = cvMat(3, 3, CV_64F, R );
CvMat _T = cvMat(3, 1, CV_64F, T );
CvMat _E = cvMat(3, 3, CV_64F, E );
CvMat _F = cvMat(3, 3, CV_64F, F );

在其他示例中,我看到以下代码:

//--------Find and Draw chessboard--------------------------------------------------    

    if((frame++ % 20) == 0)
    {
        //----------------CAM1-------------------------------------------------------------------------------------------------------
        result1 = cvFindChessboardCorners( frame1, board_sz,&temp1[0], &count1,CV_CALIB_CB_ADAPTIVE_THRESH|CV_CALIB_CB_FILTER_QUADS);
        cvCvtColor( frame1, gray_fr1, CV_BGR2GRAY );

if 语句究竟做了什么?为什么是 %20?

先感谢您!


更新:

我对一些实现代码有两个问题:link

-1:在第 18 行声明并在第 25 行的 board_sz 变量中使用的那些 nx 和 ny 变量。这些 nx 和 ny 是棋盘图案中的行和列还是角?(我认为这些是行和列,因为 cvSize 具有宽度和高度参数)。

-2:这些 CvMat 变量有什么用(第 143 - 146 行)?

CvMat _objectPoints = cvMat(1, N, CV_32FC3, &objectPoints[0] );
CvMat _imagePoints1 = cvMat(1, N, CV_32FC2, &points[0][0] );
CvMat _imagePoints2 = cvMat(1, N, CV_32FC2, &points[1][0] );
CvMat _npoints = cvMat(1, npoints.size(), CV_32S, &npoints[0] );
4

1 回答 1

3

这些矩阵中的每一个都在极线几何中具有意义。它们描述了 3D 空间中两台相机之间的关系以及它们记录的图像之间的关系。

在您的示例中,它们是:

  • M1 - 左相机的相机内在矩阵
  • M2 - 你的右相机的相机内在矩阵
  • D1 - 左相机的畸变系数
  • D2 - 右相机的畸变系数
  • R - 从右到左相机的旋转矩阵
  • T - 从右到左相机的平移向量
  • E - 立体声设置的基本矩阵
  • F - 立体声设置的基本矩阵

在这些矩阵的基础上,您可以对图像进行不失真校正,这使您可以通过视差(基本上是 x 的差异)来提取您在两幅图像中看到的点的深度。在两幅图像中找到一个点称为匹配,通常是校正后的最后一步。

对极几何和立体视觉的任何好的介绍都可能比我在这里输入的任何内容都要好。我推荐Learning OpenCV这本书,你的示例代码是从中获取的,它非常详细地解释了基础知识。

您的问题的第二部分已在评论中得到解答: (frame++ % 20) 是 0 对于从您的网络摄像头记录的每 20 帧,因此 if 子句中的代码每 20 帧执行一次。


回复您的更新:

nx 和 ny 是校准图像中棋盘图案中的角数。na "正常" 8x8 棋盘,nx = ny = 7。你可以看到,在第 138-139 行中,一个理想棋盘的点是通过将 nx*ny 个点与 squareSize 的距离偏移来创建的,即你的一个正方形的大小棋盘。

CvMat 变量“objectPoints”、“imagePoints”和“npoints”被传递到 cvStereoCalibrate 函数中。

  • objectPoints 包含校准对象(棋盘)的点
  • imagePoints1/2 包含每个相机看到的这些点
  • npoints 仅包含每个图像中的点数(作为 M×1 矩阵) - 随意忽略它,无论如何它不再在 OpenCV C++ API 中使用。

基本上,cvStereoCalibrate 将 imagePoints 拟合到 objectPoints,并返回 1) 失真系数,2) 固有相机矩阵和 3) 两个相机的空间关系作为旋转矩阵 R 和平移向量 T。第一个用于不失真您的图像,第二个将您的像素坐标传递到真实世界的坐标,第三个允许您纠正您的两个图像。

附带说明:我记得在立体校准时遇到了问题,因为在左右摄像头图像中检测到的棋盘方向可能不同。除非您的相机之间的角度很大(这不是一个好主意)或者您的棋盘倾斜很多(这不是必需的),否则这应该不是问题,但您仍然可以留意。

于 2013-05-11T04:46:23.250 回答