首页 文章

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

提问于
浏览
12

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

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

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

2 回答

  • 2

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

  • 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.对于在两个图像中观察到的每对图像点,我们计算它们在世界坐标中的相应光线的方向并将它们存储在2d阵列中(编辑:假设内部相机参数是已知的) . 我们可以这样做,因为我们假设我们知道每个相机的方向 . 现在我们构建一个超定线性系统 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/

相关问题