在 OpenCV 中,我遇到了与您相同的问题。我有一个立体图像对,我想计算相机的外部参数和所有观察点的世界坐标。此问题已在此处处理:
Berthold K. P. 霍恩。重新审视了相对方向。 Berthold K. P. 霍恩。麻省理工学院人工智能实验室,545科技...
http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.64.4700
但是,我找不到此问题的合适实现(也许您会找到一个)。由于时间限制,我没有时间理解本文中的所有数学并自己实现它,所以我想出了一个适合我的快速而简单的解决方案。我将解释我做了什么来解决它:
假设我们有两个摄像头,其中第一个摄像头有外部参数 RT = Matx::eye()。现在猜测第二个摄像机的旋转 R。对于在两幅图像中观察到的每一对图像点,我们计算它们在世界坐标中对应光线的方向,并将它们存储在二维数组 dirs 中(编辑:假设内部相机参数是已知的)。我们可以这样做,因为我们假设我们知道每个相机的方向。现在我们建立一个超定线性系统AC = 0,其中C是第二个相机的中心。我为你提供了计算 A 的函数:
Mat buildA(Matx<double, 3, 3> &R, Array<Vec3d, 2> dirs)
{
CV_Assert(dirs.size(0) == 2);
int pointCount = dirs.size(1);
Mat A(pointCount, 3, DataType<double>::type);
Vec3d *a = (Vec3d *)A.data;
for (int i = 0; i < pointCount; i++)
{
a[i] = dirs(0, i).cross(toVec(R*dirs(1, i)));
double length = norm(a[i]);
if (length == 0.0)
{
CV_Assert(false);
}
else
{
a[i] *= (1.0/length);
}
}
return A;
}
然后调用 cv::SVD::solveZ(A) 将为您提供该系统的范数 1 的最小二乘解。这样,您可以获得第二个相机的旋转和平移。然而,由于我只是猜测了第二台摄像机的旋转,我对它的旋转做了几个猜测(使用 3x1 向量 omega 进行参数化,我使用 cv::Rodrigues 计算旋转矩阵)然后我通过在具有数值雅可比的 Levenberg-Marquardt 优化器中重复求解系统 AC = 0。它对我有用,但有点脏,所以如果你有时间,我鼓励你实现论文中解释的内容。
编辑:
这是 Levenberg-Marquardt 优化器中用于评估残差向量的例程:
void Stereo::eval(Mat &X, Mat &residues, Mat &weights)
{
Matx<double, 3, 3> R2Ref = getRot(X); // Map the 3x1 euler angle to a rotation matrix
Mat A = buildA(R2Ref, _dirs); // Compute the A matrix that measures the distance between ray pairs
Vec3d c;
Mat cMat(c, false);
SVD::solveZ(A, cMat); // Find the optimum camera centre of the second camera at distance 1 from the first camera
residues = A*cMat; // Compute the output vector whose length we are minimizing
weights.setTo(1.0);
}
顺便说一句,我在互联网上搜索了一些其他代码,这些代码可能对计算相机之间的相对方向很有用。我还没有尝试过任何代码,但它似乎很有用:
http://www9.in.tum.de/praktika/ppbv.WS02/doc/html/reference/cpp/toc_tools_stereo.html
http://lear.inrialpes.fr/people/triggs/src/
http://www.maths.lth.se/vision/downloads/