【问题标题】:OpenCV: How to calculate essential matrix from feature matches between two images from different cameras using 5-point algorithm?OpenCV:如何使用 5 点算法从来自不同相机的两幅图像之间的特征匹配计算基本矩阵?
【发布时间】:2019-10-09 02:38:35
【问题描述】:

基本上我想在这里做与这个函数相同的事情: https://docs.opencv.org/master/d9/d0c/group__calib3d.html#ga13f7e34de8fa516a686a56af1196247f

但是,参数描述表明,该算法假设两个图像的匹配特征点来自具有相同相机矩阵的相机。

如果我有匹配的特征,但图像来自具有不同相机矩阵的两个不同相机,该怎么办?那么如何计算五点本质矩阵呢?

其他问题: 如果我已经计算了基本矩阵,我可以在方法computeCorrespondEpilines() 中使用它作为参数,而不是基本矩阵,假设图像已经被纠正了吗?

【问题讨论】:

    标签: c++ opencv computer-vision


    【解决方案1】:

    在 OpenCV 中,没有使用两个不同的相机计算基本矩阵的标准函数。但是自己实现它非常容易。 您可以向five-point.cpp 添加一个函数并重新编译OpenCV。 我刚刚添加了一个重载函数cv::findEssentialMat,并为第二个摄像头矩阵添加了一个附加参数。

    cv::Mat cv::findEssentialMat(InputArray _points1, InputArray _points2, InputArray _cameraMatrix1, InputArray _cameraMatrix2, int method, double prob, double threshold, OutputArray _mask)
    {
        CV_INSTRUMENT_REGION();
    
        Mat points1, points2, cameraMatrix1, cameraMatrix2;
        _points1.getMat().convertTo(points1, CV_64F);
        _points2.getMat().convertTo(points2, CV_64F);
        _cameraMatrix1.getMat().convertTo(cameraMatrix1, CV_64F);
        _cameraMatrix2.getMat().convertTo(cameraMatrix2, CV_64F);
    
        int npoints = points1.checkVector(2);
        CV_Assert(npoints >= 0 && points2.checkVector(2) == npoints &&
            points1.type() == points2.type());
    
        CV_Assert(cameraMatrix1.rows == 3 && cameraMatrix1.cols == 3 && cameraMatrix1.channels() == 1);
        CV_Assert(cameraMatrix2.rows == 3 && cameraMatrix2.cols == 3 && cameraMatrix2.channels() == 1);
    
        if (points1.channels() > 1)
        {
            points1 = points1.reshape(1, npoints);
            points2 = points2.reshape(1, npoints);
        }
    
        double fx1 = cameraMatrix1.at<double>(0, 0);
        double fy1 = cameraMatrix1.at<double>(1, 1);
        double cx1 = cameraMatrix1.at<double>(0, 2);
        double cy1 = cameraMatrix1.at<double>(1, 2);
        double fx2 = cameraMatrix2.at<double>(0, 0);
        double fy2 = cameraMatrix2.at<double>(1, 1);
        double cx2 = cameraMatrix2.at<double>(0, 2);
        double cy2 = cameraMatrix2.at<double>(1, 2);
    
        points1.col(0) = (points1.col(0) - cx1) / fx1;
        points2.col(0) = (points2.col(0) - cx2) / fx2;
        points1.col(1) = (points1.col(1) - cy1) / fy1;
        points2.col(1) = (points2.col(1) - cy2) / fy2;
    
        // Reshape data to fit opencv ransac function
        points1 = points1.reshape(2, npoints);
        points2 = points2.reshape(2, npoints);
    
        threshold /= (fx1 + fy1) / 2;
    
        Mat E;
        if (method == RANSAC)
            createRANSACPointSetRegistrator(makePtr<EMEstimatorCallback>(), 5, threshold, prob)->run(points1, points2, E, _mask);
        else
            createLMeDSPointSetRegistrator(makePtr<EMEstimatorCallback>(), 5, prob)->run(points1, points2, E, _mask);
    
        return E;
    }
    

    然后你必须将函数声明添加到calib3d.hpp,重新编译并重新安装你的OpenCV版本。

    附加问题:如果我已经计算了基本矩阵,我是否可以将其用作方法computeCorrespondEpilines() 中的参数,而不是基本矩阵,假设图像已经校正?

    是的,我认为这应该可行。

    【讨论】:

    • 谢谢你的信息,帮助很大:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-27
    • 2021-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多