OpenCV来自特征点的外在摄像头

时间:2011-11-15 18:02:08

标签: opencv computer-vision camera-calibration perspectivecamera

当我从每个摄像机的视图中查看对象的图片时,如何使用OpenCV检索旋转矩阵,平移向量以及每个摄像机的某些缩放因子?对于每张图片,我都有几个特征点的图像坐标。并非所有特征点都在所有图片中都可见。 我想将对象特征点的计算3D坐标映射到稍微不同的对象,以将第二个对象的形状与第一个对象对齐。

我听说有可能使用cv::calibrateCamera(...),但我无法完成它......

有人有这种问题的经历吗?

2 个答案:

答案 0 :(得分:12)

在OpenCV中,我遇到了和你一样的问题。我有一个立体图像对,我想计算相机的外部参数和所有观察点的世界坐标。此问题已在此处理:

Berthold K. P. Horn。相对方向重新审视。 Berthold K. P. Horn。人工智能实验室,麻省理工学院,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矢量欧米茄参数化,我使用cv :: Rodrigues计算旋转矩阵)然后我通过在具有数字jacobian的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/

答案 1 :(得分:2)

您希望校准这些静态相机以备将来用作立体声对吗?在这种情况下,您可能希望使用cv::stereoCalibrate()函数。 OpenCV包含一些示例代码,其中一个是stereo_calib.cpp,可能值得研究。