проблемы в 3D-реконструкции с помощью триангуляции opencv

В настоящее время я работаю над проектом стереовидения, в котором я должен реконструировать 3D-точки из соответствий, найденных в каждом представлении камеры, и для этого я использую OpenCV 2.4.7 для С++.

Я смог правильно откалибровать обе камеры, вычислить основную матрицу, вычислить матрицу перепроекции, а также исправить изображения.

Моя проблема заключается в заключительной части проекта, которая заключается в вычислении трехмерных мировых координат из двухмерных соответствий точек. Я уже пытался использовать cv::triangulatePoints, но результаты, где точки с координатами (0, 0, 0), независимо от того, какие точки ввода были. Я также попробовал алгоритм линейной триангуляции Хартли и Струма, но и он не дал хороших результатов.

Может ли кто-нибудь дать мне подсказку о том, какую функцию я должен использовать? Или, может быть, несколько советов, как правильно реализовать те, о которых я говорил. Моя самая большая проблема — найти хорошую документацию в Интернете, поэтому я решил спросить здесь.

Спасибо!


person user3100319    schedule 22.06.2014    source источник
comment
Возможно, вы передаете неверный ввод методу triangulatePoints. Проверьте этот другой вопрос: stackoverflow.com/questions/16295551/   -  person Esparver    schedule 28.06.2014


Ответы (1)


Я также пробовал cv::triangulatePoints, и он вычисляет мусор. Мне пришлось реализовать метод линейной триангуляции вручную, который возвращает триангулированную 3D-точку с учетом соответствия стереопикселя:

Mat triangulate_Linear_LS(Mat mat_P_l, Mat mat_P_r, Mat warped_back_l, Mat warped_back_r)
{
    Mat A(4,3,CV_64FC1), b(4,1,CV_64FC1), X(3,1,CV_64FC1), X_homogeneous(4,1,CV_64FC1), W(1,1,CV_64FC1);
    W.at<double>(0,0) = 1.0;
    A.at<double>(0,0) = (warped_back_l.at<double>(0,0)/warped_back_l.at<double>(2,0))*mat_P_l.at<double>(2,0) - mat_P_l.at<double>(0,0);
    A.at<double>(0,1) = (warped_back_l.at<double>(0,0)/warped_back_l.at<double>(2,0))*mat_P_l.at<double>(2,1) - mat_P_l.at<double>(0,1);
    A.at<double>(0,2) = (warped_back_l.at<double>(0,0)/warped_back_l.at<double>(2,0))*mat_P_l.at<double>(2,2) - mat_P_l.at<double>(0,2);
    A.at<double>(1,0) = (warped_back_l.at<double>(1,0)/warped_back_l.at<double>(2,0))*mat_P_l.at<double>(2,0) - mat_P_l.at<double>(1,0);
    A.at<double>(1,1) = (warped_back_l.at<double>(1,0)/warped_back_l.at<double>(2,0))*mat_P_l.at<double>(2,1) - mat_P_l.at<double>(1,1);
    A.at<double>(1,2) = (warped_back_l.at<double>(1,0)/warped_back_l.at<double>(2,0))*mat_P_l.at<double>(2,2) - mat_P_l.at<double>(1,2);
    A.at<double>(2,0) = (warped_back_r.at<double>(0,0)/warped_back_r.at<double>(2,0))*mat_P_r.at<double>(2,0) - mat_P_r.at<double>(0,0);
    A.at<double>(2,1) = (warped_back_r.at<double>(0,0)/warped_back_r.at<double>(2,0))*mat_P_r.at<double>(2,1) - mat_P_r.at<double>(0,1);
    A.at<double>(2,2) = (warped_back_r.at<double>(0,0)/warped_back_r.at<double>(2,0))*mat_P_r.at<double>(2,2) - mat_P_r.at<double>(0,2);
    A.at<double>(3,0) = (warped_back_r.at<double>(1,0)/warped_back_r.at<double>(2,0))*mat_P_r.at<double>(2,0) - mat_P_r.at<double>(1,0);
    A.at<double>(3,1) = (warped_back_r.at<double>(1,0)/warped_back_r.at<double>(2,0))*mat_P_r.at<double>(2,1) - mat_P_r.at<double>(1,1);
    A.at<double>(3,2) = (warped_back_r.at<double>(1,0)/warped_back_r.at<double>(2,0))*mat_P_r.at<double>(2,2) - mat_P_r.at<double>(1,2);
    b.at<double>(0,0) = -((warped_back_l.at<double>(0,0)/warped_back_l.at<double>(2,0))*mat_P_l.at<double>(2,3) - mat_P_l.at<double>(0,3));
    b.at<double>(1,0) = -((warped_back_l.at<double>(1,0)/warped_back_l.at<double>(2,0))*mat_P_l.at<double>(2,3) - mat_P_l.at<double>(1,3));
    b.at<double>(2,0) = -((warped_back_r.at<double>(0,0)/warped_back_r.at<double>(2,0))*mat_P_r.at<double>(2,3) - mat_P_r.at<double>(0,3));
    b.at<double>(3,0) = -((warped_back_r.at<double>(1,0)/warped_back_r.at<double>(2,0))*mat_P_r.at<double>(2,3) - mat_P_r.at<double>(1,3));
    solve(A,b,X,DECOMP_SVD);
    vconcat(X,W,X_homogeneous);
    return X_homogeneous;
}

входными параметрами являются две матрицы проекций камеры 3x4 и соответствующие однородные координаты левого/правого пикселя.

person YuZ    schedule 12.09.2014
comment
сделайте себе одолжение и используйте Mat_<double> для такого рода приключений, тогда вы можете пропустить часть at<double>, и доступ будет, например. хороший b(1,0) . огромный выигрыш в читаемости/ясности - person berak; 12.09.2014
comment
на днях попробую - person YuZ; 12.09.2014
comment
Объясните, пожалуйста, почему, например, в (warped_back_r.at<double>(1,0)/warped_back_r.at<double>(2,0))*mat_P_r.at<double>(2,3) - mat_P_r.at<double>(1,3) r(1,0) делится на r(2,0)*P(2,3)? - person stackoverflower; 28.09.2018
comment
Алгоритм представляет собой линейную триангуляцию (для справки прочитайте главу 12.2 бесплатной онлайн-книги Multiple View Geometry in Computer Vision Эндрю Циссерманна). Идея состоит в том, чтобы вывести X в уравнении x=PX с x в качестве координат пикселя, P в качестве матрицы камеры и X в качестве пространственных координат. Поскольку левый и правый члены равны, их векторное произведение равно нулю, что можно изменить как AX=0. Приведенный выше метод решает это уравнение после создания A из x и P. - person YuZ; 30.09.2018