【问题标题】:Stereo Calibration in Open CV and 3D CoordinatesOpen CV 和 3D 坐标中的立体校准
【发布时间】:2014-04-29 04:25:25
【问题描述】:

我是OpenCV 的初学者,目前正在从事一个需要将像素精确映射到厘米/毫米/任何现实世界单位的项目。

我在OpenCV 中执行了立体声校准,然后进行了立体声校正。因此我得到了内在和外在参数。

在执行立体校准时,我没有在哪里输入棋盘图案的确切正方形尺寸(25 毫米 x 25 毫米)。我只输入了水平和垂直内角的数量以及板的数量。那么当我重新投影到 3D 时这会产生影响吗?如果是这样,我如何在 StereoCalibrate 函数中包含正方形大小。

其次,从相机矩阵得到的fxfy的值都是513.86,而从EXIF数据得出的值是3.7mm。那么,两者之间的确切关系是什么?

第三,我使用了reprojectImageTo3D,得到了3d世界坐标。现在这些坐标的确切单位是什么(厘米/毫米/英寸/等)?

基本上,我想获得从像素到真实世界单位的精确映射,经过大量阅读和搜索,我无法做到。请帮我解决这个问题。

【问题讨论】:

  • 您好!我对OpenCV 不够熟悉,无法回答您的问题,但由于您似乎有 3 个问题,最好将它们分成 3 个不同的问题。这样,您将获得更具体的答案,并且有机会完全回答其中一些问题,而另一些则保持开放,以防需要更多研究或努力才能得到答案。

标签: c++ opencv 3d stereo-3d


【解决方案1】:

我同意前两个问题的其他答案。但只是为了进一步澄清和详细说明,

1)

查看下面代码块中的参数“squareSize”。

这是您指定正方形大小的地方。它的作用是计算棋盘中每个角的位置,并将其推入一个点向量,称为 objectPoints。这是可能的,因为棋盘具有规则的图案。

向量 objectPoints 然后成为 StereoCalibrate 函数的第一个参数。

另外,请记住,无论您为 squareSize 指定什么单位,您的校准结果(当然 fx 和 fy 除外)都将采用相同的单位。

    for( j = 0; j < boardSize.height; j++ ){
        for( k = 0; k < boardSize.width; k++ ){
            objectPoints.push_back(Point3f(j*squareSize, k*squareSize, 0));
        }
    }

2)

你得到的 fx 和 fy 将以像素为单位。为了获得以毫米为单位的焦距,您需要将其乘以比例因子。

fx、fy 和您的实际焦距(以毫米为单位)之间的关系由相机传感器的尺寸决定。您应该能够在相机规格中找到此参数。

我上面提到的比例因子将是您的相机传感器每毫米的像素数。

3)

您获得的 3D 世界坐标正是您所提到的。 坐标。从系统中的某个点引用。它们是对象点的xyz坐标。坐标没有单位!

【讨论】:

    【解决方案2】:
    1. 函数StereoCalibrate的第一个参数是您需要自己创建的校准图案的实际尺寸。例如,如果您有一个 3 mm 方格的 6x5 棋盘网格,您需要创建一个矩阵,其中包含在棋盘 e.x. 的参考系统中表示的每个角的位置。 [(0,0,0)(0,3,0)(0,6,0)...] 等等。
    2. 焦距以像素尺寸表示。您应该只检查像素的实际尺寸(通常以微米为单位)并将fxfy 乘以它。
    3. 单位取决于您创建校准图案的方式(问题一)。在示例中,我制作的棋盘具有 3 毫米的正方形,因此网格中角的位置以毫米表示。那是你的结果的单位。

    【讨论】:

    • 非常感谢。在您的第三点中,您提到如果我以 mm 为平方大小,mm 将是我的结果的单位。你说的“结果”是什么?我已经获得了 Q 矩阵并将图像重新投影到 3d 坐标。现在坐标轴也以毫米为单位吗?我应该采取什么方法来计算任意两个坐标之间的距离?
    【解决方案3】:

    到目前为止,我可以回答前两个问题:

    1:cv::stereoCalibrate中的第一个参数是物体点的向量,你可以使用下面的函数来填充它:

    void CalcBoardCornerPositions(cv::Size boardSize, double squareSize, std::vector<cv::Point3f>& corners) {
        corners.clear();
        for( int i = 0; i < boardSize.height; ++i )
            for( int j = 0; j < boardSize.width; ++j )
                corners.push_back(cv::Point3f(float( j*squareSize ), float( i*squareSize ), 0)); 
    }
    

    然后使用它:

     std::vector<std::vector<cv::Point3f> > objectPoints(1);
     CalcBoardCornerPositions(boardSize, squareSize, objectPoints[0]);
     cv::stereoCalibrate(objectPoints, imagePointsA, imagePointsB, _cameraMatrixA, /// etc
    

    2: 相机矩阵 fx 和 fy 实际上是焦距分别乘以 x 和 y 方向的像素密度。这意味着

    fx = f * cx

    fy = f * cy

    其中 cx = imageSize.width / sensorSize.width 和 cy = imageSize.height / sensorSize.height。 在现代相机中,通常 cx == cy。您可以在相机手册中找到相机传感器的尺寸。

    【讨论】:

      猜你喜欢
      • 2021-04-01
      • 2014-12-22
      • 2014-07-04
      • 1970-01-01
      • 2012-02-10
      • 1970-01-01
      • 1970-01-01
      • 2013-10-12
      • 2017-10-18
      相关资源
      最近更新 更多