2016-03-11 2 views
2

Я пытаюсь решить проблему плоскости plane2plane, используя функцию findHomography, найденную в библиотеке OpenCV. В качестве примера игрушек у меня есть набор точек в R2, P и второй набор точек в R2, Q, где Qx = Px + 50, Qy = Py. Смысл я взаимозачет координаты х на 50. Теперь я запускаю следующий код:OpenCV: Странные матрицы вращения и перевода из декомпозицииHomographyMat

Mat projectionMatrix = findHomography(Q, P); 
vector<Point2f> projectedPoints(objectCoordinates.size()); 
perspectiveTransform(Q, projectedPoints, projectionMatrix); 

И это дает мне P, который является большим. Однако теперь мне нужны матрицы вращения и перевода, R & T, и вот где я запутался. OpenCV 3 имеет функцию decomposeHomographyMat, которая возвращает до 4 решений для R и T (также возвращает нормали, но я их не храню). Я бегу как например:

vector<Mat> Rs; 
vector<Mat> Ts; 
decomposeHomographyMat(projectionMatrix, cameraMatrix, Rs, Ts, noArray()); 

cameraMatrix я использую испытанный из предыдущих экспериментов. Хорошо, поэтому я получаю свои четыре результата. Глядя на них, я замечаю, что я получаю идентификационную матрицу в результате для всех R, что здорово. Однако все векторы трансляции [0,0,0] T, тогда как я ожидал бы хотя бы одного из них [-50,0,0] T. Есть ли что-то, что мне нужно сделать с результатом decomposeHomographyMat, чтобы получить ожидаемое поведение?

Благодаря

+0

Вы проверили, что вычисленная гомография не равна нулю? – SpamBot

+0

@SpamBot Да, вычисленная гомография (с очень небольшим округлением): [1 0 -50; 0 1 0; 0 0 1]. – IlliteratePhD

+0

Это всего лишь догадка, может быть, разложениеHomographyMat не обрабатывает специальный случай аффинной гомографии? – SpamBot

ответ

7

Оказывается, я был неправ в некоторых местах, так что я решил переписать этот ответ.

Вкратце - вы получаете странные результаты из-за неправильной внутренней матрицы параметров.

Использование терминологии из статьи «Малис, E и Варгас, М», «Более глубокое понимание разложения гомографии для управления на основе зрения» (на котором основано разложение гомографии в OpenCV), перспективное преобразование обозначается Н и называется евклидово гомография матрица, и результатом ее нормализации гайанских = к^-1 * Н * к (где к является калибровка матрицы камеры) называется матрица гомографии

И cv::findHomography()cv::decomposeHomographyMat() и работа с евклидовой гомографией матрицей. Но для того, чтобы разложить его на сдвиг и вращение, cv::decomposeHomographyMat() нормализует Евклидовую гомографическую матрицу для получения гомографическая матрица. Он полагается на K, предоставленный от пользователя, для выполнения этой нормализации.

Что касается оценки K, я думаю, что это выходит за рамки этого вопроса. Эта проблема называется Camera auto-calibration, вот соответствующая цитата из этой вики статьи:

Таким образом, три вида является минимально необходимым для полной калибровки с фиксированными внутренними параметрами между видами. Современные датчики и оптические датчики качества также могут обеспечить дополнительные предварительные ограничения на калибровку, такие как нулевое отклонение (сетка ортогонального пикселя) и единичное соотношение сторон (квадратные пиксели). Интеграция этих приоритетов уменьшит минимальное количество изображений, необходимых для двух.

кажется, что вы можете извлечь K из Correspondances изображения в течение 2 кадров из одной и той же камеры при нулевой перекоса и квадратными допущений пикселей. Но я не знаком с этой темой, поэтому не могу дать вам больше предложений.

Итак, чтобы проверить правильность моей интерпретации, я сделал небольшой пример, который проектирует некоторые точки на плоскости в 3D на двух виртуальных камерах, находит гомографию, разлагает ее и позволяет сравнивать это разложение с земной истиной векторы вращения и трансляции. Это лучше, чем реальные входы, потому что таким образом мы точно знаем K и можем отделить ошибку при ее оценке от ошибки в R и t. Для входов, которые я проверил, он смог правильно оценить векторы вращения и трансляции, хотя по какой-то причине перевод всегда меньше, чем основная правда 10 раз. Возможно, это разложение определяется только до масштаба (я не уверен сейчас), но интересно, что это связано с истинным значением истины с фиксированным коэффициентом.

Вот источник:

#include <opencv2/opencv.hpp> 
#include <iostream> 
#include <vector> 


int main() { 
    // set up a virtual camera 
    float f = 100, w = 640, h = 480; 

    cv::Mat1f K = (cv::Mat1f(3, 3) << 
     f, 0, w/2, 
     0, f, h/2, 
     0, 0, 1); 

    // set transformation from 1st to 2nd camera (assume K is unchanged) 
    cv::Mat1f rvecDeg = (cv::Mat1f(3, 1) << 45, 12, 66); 
    cv::Mat1f t = (cv::Mat1f(3, 1) << 100, 200, 300); 

    std::cout << "-------------------------------------------\n"; 
    std::cout << "Ground truth:\n"; 

    std::cout << "K = \n" << K << std::endl << std::endl; 
    std::cout << "rvec = \n" << rvecDeg << std::endl << std::endl; 
    std::cout << "t = \n" << t << std::endl << std::endl; 

    // set up points on a plane 
    std::vector<cv::Point3f> p3d{{0, 0, 10}, 
           {100, 0, 10}, 
           {0, 100, 10}, 
           {100, 100, 10}}; 

    // project on both cameras 
    std::vector<cv::Point2f> Q, P, S; 

    cv::projectPoints(p3d, 
        cv::Mat1d::zeros(3, 1), 
        cv::Mat1d::zeros(3, 1), 
        K, 
        cv::Mat(), 
        Q); 

    cv::projectPoints(p3d, 
        rvecDeg*CV_PI/180, 
        t, 
        K, 
        cv::Mat(), 
        P); 

    // find homography 
    cv::Mat H = cv::findHomography(Q, P); 

    std::cout << "-------------------------------------------\n"; 
    std::cout << "Estimated H = \n" << H << std::endl << std::endl; 


    // check by reprojection 
    std::vector<cv::Point2f> P_(P.size()); 
    cv::perspectiveTransform(Q, P_, H); 

    float sumError = 0; 

    for (size_t i = 0; i < P.size(); i++) { 
    sumError += cv::norm(P[i] - P_[i]); 
    } 

    std::cout << "-------------------------------------------\n"; 
    std::cout << "Average reprojection error = " 
     << sumError/P.size() << std::endl << std::endl; 


    // decompose using identity as internal parameters matrix 
    std::vector<cv::Mat> Rs, Ts; 
    cv::decomposeHomographyMat(H, 
          K, 
          Rs, Ts, 
          cv::noArray()); 

    std::cout << "-------------------------------------------\n"; 
    std::cout << "Estimated decomposition:\n\n"; 
    std::cout << "rvec = " << std::endl; 
    for (auto R_ : Rs) { 
    cv::Mat1d rvec; 
    cv::Rodrigues(R_, rvec); 
    std::cout << rvec*180/CV_PI << std::endl << std::endl; 
    } 

    std::cout << std::endl; 

    std::cout << "t = " << std::endl; 
    for (auto t_ : Ts) { 
    std::cout << t_ << std::endl << std::endl; 
    } 

    return 0; 
} 

А вот выход на моей машине:

------------------------------------------- 
Ground truth: 
K = 
[100, 0, 320; 
0, 100, 240; 
0, 0, 1] 

rvec = 
[45; 
12; 
66] 

t = 
[100; 
200; 
300] 

------------------------------------------- 
Estimated H = 
[0.04136041220427821, 0.04748763375951008, 358.5557917287962; 
0.05074854454707714, 0.06137211243830468, 297.4585754092336; 
8.294458769850147e-05, 0.0002294875562580223, 1] 

------------------------------------------- 
Average reprojection error = 0 

------------------------------------------- 
Estimated decomposition: 

rvec = 
[-73.21470385654712; 
56.64668212487194; 
82.09114210289061] 

[-73.21470385654712; 
56.64668212487194; 
82.09114210289061] 

[45.00005330430893; 
12.00000697952995; 
65.99998380038915] 

[45.00005330430893; 
12.00000697952995; 
65.99998380038915] 


t = 
[10.76993852870029; 
18.60689642878277; 
30.62344129378435] 

[-10.76993852870029; 
-18.60689642878277; 
-30.62344129378435] 

[10.00001378255982; 
20.00002581449634; 
30.0000336510648] 

[-10.00001378255982; 
-20.00002581449634; 
-30.0000336510648] 

Как вы можете видеть, есть правильная оценка вектора вращения между гипотезой и есть вверх правильная оценка перевода.

+0

Благодарим вас за подробный и информативный ответ! Я прочитал некоторые ссылки, которые вы предоставили, и я думаю, что следую общим концепциям. Я все еще не уверен в роли K, поскольку это, кажется, полностью игнорируется. Однако, когда я применяю рабочий процесс выше до двух изображений с поворотом камеры на 30 градусов и отмеченными точками, мои результаты плохие. Опять же, перспективное преобразование с использованием оценки H дает идеальный результат. Но разложение дает плохие результаты. Я предполагаю, что я пропускаю какую-то нормализацию своих очков при применении R и t, но не могу понять, что. – IlliteratePhD

+0

Я немного придумаю. Я вручную разместил 12 маркеров в перекрывающихся частях двух сцен, где камера поворачивалась на 30 градусов вокруг оси y. Поскольку камера была повернута вокруг одной оси, я подумал, что я получу R, демонстрирующую поворот, и t = 0. Я, однако, вижу волшебные большие переводы и просто бессмысленные вращения. – IlliteratePhD

+0

Были ли точки равномерно распределены по области изображения? Потому что, когда вы наблюдаете небольшую часть вращающегося объекта, его можно локально описать с помощью поступательного движения. – alexisrozhkov

Смежные вопросы