OpenCV: Как рассчитать необходимую матрицу из совпадений объектов между двумя изображениями с разных камер, используя 5-точечный алгоритм? - PullRequest
0 голосов
/ 22 мая 2019

В основном я хочу сделать то же самое, что и эта функция здесь: https://docs.opencv.org/master/d9/d0c/group__calib3d.html#ga13f7e34de8fa516a686a56af1196247f

Однако в описании параметра говорится, что этот алгоритм предполагает, что совпадающие характерные точки двух изображений получены с камер с одинаковой матрицей камеры.

Что, если у меня совпадают функции, но изображения с двух разных камер с разными матрицами камер? Как тогда я могу вычислить 5-точечную матрицу?

Дополнительный вопрос : Если я вычислил основную матрицу, могу ли я просто использовать ее в качестве параметра в методе computeCorrespondEpilines() вместо основной матрицы, предполагая, что изображения уже выпрямлены?

1 Ответ

1 голос
/ 23 мая 2019

В 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() вместо основной матрицы, если предположить, что изображения уже выпрямлены?

Да, я думаю, это должно сработать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...