2012-01-19 3 views
38

У меня есть 4 компланарных точки в видео (или изображении), представляющих квадрат (не обязательно квадрат или прямоугольник), и я хотел бы иметь возможность отображать виртуальный куб на вершины которых, где углы куба стоят точно на углах видеокарты.Компьютерная камера с гомографической матрицей на основе 4 копланарных точек

Поскольку точки являются копланарными, я могу вычислить гомографию между углами единичного квадрата (т.е. [0,0] [0,1] [1,0] [1,1]) и видеокодами квад.

Из этой гомографии я должен был бы вычислить правильную позу камеры, то есть [R | t], где R является матрицей вращения 3x3, а t является вектором трансляции 3x1, так что виртуальный куб лежит на видеоцикле.

Я прочитал много решений (некоторые из них на SO) и попытался их реализовать, но они, похоже, работают только в некоторых «простых» случаях (например, когда квадрат видео является квадратом), но не работают в большинстве случаев.

Вот методы, которые я пробовал (большинство из них основаны на одних и тех же принципах, только вычисление перевода несколько отличается). Пусть K - внутренняя матрица из камеры, H - гомография. Подсчитаем:

A = K-1 * H 

Пусть a1, a2, a3 быть векторами-столбцами А и r1, r2, r3 векторы-столбцы матрицы вращения R.

r1 = a1/||a1|| 
r2 = a2/||a2|| 
r3 = r1 x r2 
t = a3/sqrt(||a1||*||a2||) 

Вопрос заключается в том, что это делает не работают в большинстве случаев. Чтобы проверить мои результаты, я сравнил R и t с результатами, полученными методом solvePnP OpenCV (используя следующие трехмерные точки [0,0,0] [0,1,0] [1,0,0] [1,1 , 0]).

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

В теории, так как мои точки лежат в одной плоскости, можно вычислить позу от омографии, но я не мог найти правильный путь, чтобы вычислить позу от H.

Любые идеи о том, что я делаю неправильно ?

Edit после попытки @ метода Jav_Rock в

Привет Jav_Rock, большое спасибо за ваш ответ, я попробовал ваш подход (как и многие другие, а), который, кажется, более или менее в порядке. Тем не менее у меня все еще возникают проблемы при вычислении позы на основе 4-х компланарных точек. Чтобы проверить результаты, я сравниваю с результатами solvePnP (что будет намного лучше из-за итеративного подхода к минимизации погрешностей).

Вот пример:

cube

  • Желтый куб: Решите ПНФ
  • Black Cube: Техника Jav_Rock в
  • Cyan (и фиолетовый) куб (ы): некоторые другие методы, учитывая точные результаты

Как вы можете видеть, черный куб больше или менее ОК, но, похоже, не очень пропорционален, хотя векторы кажутся ортонормированными.

EDIT2: Я нормализовал v3 после его вычисления (для обеспечения ортонормальности), и, похоже, он также решает некоторые проблемы.

+2

Так solvepnp OpenCV обеспечивает правильные результаты, а ваша реализация не так? – nav

+1

Да solvePnP дает правильные результаты, тогда как моя реализация с использованием гомологий не дает правильных векторов поворота/трансляции. – JimN

+1

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

ответ

25

Если у вас есть гомография, вы можете вычислить камеры создают что-то вроде этого:

void cameraPoseFromHomography(const Mat& H, Mat& pose) 
{ 
    pose = Mat::eye(3, 4, CV_32FC1);  // 3x4 matrix, the camera pose 
    float norm1 = (float)norm(H.col(0)); 
    float norm2 = (float)norm(H.col(1)); 
    float tnorm = (norm1 + norm2)/2.0f; // Normalization value 

    Mat p1 = H.col(0);  // Pointer to first column of H 
    Mat p2 = pose.col(0); // Pointer to first column of pose (empty) 

    cv::normalize(p1, p2); // Normalize the rotation, and copies the column to pose 

    p1 = H.col(1);   // Pointer to second column of H 
    p2 = pose.col(1);  // Pointer to second column of pose (empty) 

    cv::normalize(p1, p2); // Normalize the rotation and copies the column to pose 

    p1 = pose.col(0); 
    p2 = pose.col(1); 

    Mat p3 = p1.cross(p2); // Computes the cross-product of p1 and p2 
    Mat c2 = pose.col(2); // Pointer to third column of pose 
    p3.copyTo(c2);  // Third column is the crossproduct of columns one and two 

    pose.col(3) = H.col(2)/tnorm; //vector t [R|t] is the last column of pose 
} 

Этот метод работы формируют меня. Удачи.

+1

Можете ли вы прокомментировать, что происходит в коде? –

+7

Привет, Jav_Rock, большое спасибо за ваш ответ, я попробовал ваш метод и отредактировал сообщение, чтобы вы могли видеть полученные результаты. Еще раз спасибо. – JimN

+3

Я думаю, что изображение не видно. В любом случае, если вы хотите углубиться в теорию, вы можете прочитать этот вопрос из dsp.stackexchange http://dsp.stackexchange.com/q/2736/1473 –

4

Только в случае, если кто-то нуждается в питоне перенесении функции, написанной @Jav_Rock:

def cameraPoseFromHomography(H): 
    H1 = H[:, 0] 
    H2 = H[:, 1] 
    H3 = np.cross(H1, H2) 

    norm1 = np.linalg.norm(H1) 
    norm2 = np.linalg.norm(H2) 
    tnorm = (norm1 + norm2)/2.0; 

    T = H[:, 2]/tnorm 
    return np.mat([H1, H2, H3, T]) 

отлично работают в моих задачах.

+0

Как это работает без внутренних параметров камеры? – Mehdi

+0

@Mehdi Предполагаю, что гомография предполагается работать над нормализованными координатами: p '= K^(- 1) [p; 1]. –

-1

Вот версия python, основанная на том, что был представлен Дмитрием Волошиным, который нормализует матрицу вращения и переносит результат на 3x4.

def cameraPoseFromHomography(H): 
    norm1 = np.linalg.norm(H[:, 0]) 
    norm2 = np.linalg.norm(H[:, 1]) 
    tnorm = (norm1 + norm2)/2.0; 

    H1 = H[:, 0]/norm1 
    H2 = H[:, 1]/norm2 
    H3 = np.cross(H1, H2) 
    T = H[:, 2]/tnorm 

    return np.array([H1, H2, H3, T]).transpose() 
5

Вычисление [R | T] из матрицы гомографии немного сложнее, чем ответ Jav_Rock.

В OpenCV 3.0 существует метод cv :: decposeHomographyMat, который возвращает четыре потенциальных решения, один из которых правильный. Однако OpenCV не предоставил метод для выбора правильного.

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

+3

Вы поняли, как выбрать правильное решение? –

7

Ответ, предложенный Jav_Rock, не дает правильного решения для позы камеры в трехмерном пространстве.

Для оценки древомерного преобразования и вращения, вызванного гомографией, существуют множественные подходы. One of them предоставляет закрытые формулы для разложения гомографии, но они очень сложны. Кроме того, решения никогда не являются уникальными.

К счастью, OpenCV 3 уже реализует это разложение (decomposeHomographyMat). Учитывая гомографию и правильно масштабированную матрицу внутренних функций, функция предоставляет набор из четырех возможных поворотов и переводов.

+0

Расчет выбора правильного решения из двух последних возможных решений очень сложный. Знаете ли вы какую-либо реализацию статьи, которая может вернуть одно решение из последних двух решений? –

0

Самолет, содержащий вашу площадь на изображении, имеет исчезающие полосы движения вашей камеры. Уравнение этой линии A x + B y + C = 0.

Обычный самолет (A, B, C)!

Пусть p00, p01, p10, p11 являются координатами точки после применения собственных параметров камеры и в однородной форме e.г, P00 = (x00, y00,1)

линии Исчезновение может быть вычислена как:

  • вниз = поперечному P00 P01;
  • left = p00 cross p10;
  • правый = p01 крест p11;
  • up = p10 cross p11;
  • v1 = левый крест правый;
  • v2 = вверх скрестить;
  • vanish_line = v1 cross v2;

Где в стандартном векторное произведение крест