当我从每个相机的视图中获取对象的图片时,如何使用 OpenCV 检索每个相机的旋转矩阵、平移向量和一些缩放因子?对于每张图片,我都有几个特征点的图像坐标。并非所有特征点在所有图片中都可见。我想将对象特征点的计算 3D 坐标映射到稍微不同的对象,以将第二个对象的形状与第一个对象对齐。
我听说可以使用cv::calibrateCamera(...)
,但我无法完全通过它...
有人遇到过这种问题吗?
当我从每个相机的视图中获取对象的图片时,如何使用 OpenCV 检索每个相机的旋转矩阵、平移向量和一些缩放因子?对于每张图片,我都有几个特征点的图像坐标。并非所有特征点在所有图片中都可见。我想将对象特征点的计算 3D 坐标映射到稍微不同的对象,以将第二个对象的形状与第一个对象对齐。
我听说可以使用cv::calibrateCamera(...)
,但我无法完全通过它...
有人遇到过这种问题吗?
在 OpenCV 中,我遇到了和你一样的问题。我有一个立体图像对,我想计算相机的外部参数和所有观察点的世界坐标。此处已处理此问题:
Berthold KP 霍恩。重新审视了相对方向。Berthold KP 霍恩。麻省理工学院人工智能实验室,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
您是否希望校准这些静态相机以供将来用作立体相机对?在这种情况下,您需要使用cv::stereoCalibrate()函数。OpenCV 包含一些示例代码,其中之一是可能值得研究的 stereo_calib.cpp。