在OpenCV的reprojectImageTo3D()函数中,深度图的值是什么?

3

OpenCV的reprojectImageTo3D()函数输出一个“表示3D表面的三通道图像”。

您可以通过以下方式访问此数据:

Vec3f coordinates = _3dImage.at<Vec3f>(y,x);
float depth = _3dImage.at<Vec3f>(y,x)[2];

该函数返回一个向量[X,Y,Z]。

在Gary Bradski和Adrian Kaehler的《Learning OpenCV》中,解释了深度是通过以下公式计算的:

Z = f T / (x_left - x_right)

其中f为焦距,T为相机之间的基础/平移距离,(x_left - x_right)为视差

这个精确的公式已经在OpenCV中实现了(我查看了源代码——但出于某种原因,还有一个额外的负号)。问题是:X、Y、Z值以哪种单位指定?

T以您的单位(例如毫米)为单位,x_l - x_r以像素为单位,[ f ] = ?

当您校准相机时,您会指定棋盘在真实世界中的尺寸(例如毫米)。因此,内部矩阵是否具有真实世界单位?或者是以px为单位指定的?不幸的是,我在文档中找不到答案。

1个回答

2

进行深度重建的基本方程式为:

Z = fB/d,其中

  • f 是焦距(以像素为单位),您称之为相机之间的眼睛基线/平移
  • B 是立体基线(以米为单位)
  • d 是视差(以像素为单位),用于测量对应点之间视网膜位置的差异
  • Z 是沿相机 Z 轴的距离

图像点(例如以像素表示的 (u,v))的 3D 位置 (X,Y,Z) 可以用米、厘米、毫米或任何您选择的单位来表示,因为 3D 坐标 (X,Y,Z) 与棋盘格方格大小的单位相同。例如,如果您定义方格大小为 1 厘米,则 3D 坐标也将以厘米为单位。

即:

Size boardSize(4, 5); // 4x5 chessboard
float squareSize = 0.025F; // 0.025 meters
for( int i = 0; i < boardSize.height; i++ )
    for( int j = 0; j < boardSize.width; j++ )
        corners.push_back(Point3f(float(j*squareSize), float(i*squareSize), 0.0F));

p.s.:
确定 Z 后,可以使用通常的投影相机方程计算 XY

  • X = uZ/f
  • Y = vZ/f

是的,它由图案的大小定义。因此,Z的单位测量(即毫米)代表着人们选择的棋盘图案的任何测量单位。 - Kornel
但是这些信息不应该存储在内参矩阵中,因为内参不依赖于所观察的场景。这些信息存储在外参参数中,它们表示从三维世界坐标到三维相机坐标的坐标系变换。 - Kornel
1
我没有进行立体标定,只进行了单目标定。因此,我只有相机的内参,并手动提供外参参数 TB。因此,这是绝对值,而不是 X * squareSize - Jack
1
在这种情况下,统一的度量单位将是您手动提供的 TB 单位。 - Kornel
是的,您应该始终对您的设备进行立体校准!不幸的是,我确实没有这个选项。这让我很难入眠:https://stackoverflow.com/questions/31783840/find-fundamental-matrix-with-uncalibrated-stereo-camera - Jack
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接