Отслеживание маркера + перспективная деформация маркера

Я отслеживаю маркер с помощью ARToolKit+. Я получаю матрицу представления модели, которая выглядит примерно правильно. Теперь я хотел бы деформировать изображение таким образом, чтобы маркер выглядел так же, как если бы я смотрел прямо на него. Но что бы я ни делал, результат выглядит просто крайне искаженным. Я знаю, что ARToolKit хранит матрицу 4x4 в основном порядке столбцов, поэтому я исправил это для OpenCV.

До сих пор я пробовал: 1) исправить порядок основного порядка строк 2) вычислить обратный с помощью cvInverse (хотя должно быть достаточно транспонирования части вращения 3x3 + инвертирования перевода) 3) использовать эту матрицу с cvPerspectiveWarp

Я делаю что-то неправильно?

tl;dr: я хочу это: https://www.youtube.com/watch?v=qZ-LU-C2p2Q Вместо этого я получаю искаженные линии и много черного.


person Community    schedule 06.12.2012    source источник
comment
Я предполагаю, что ваша проблема заключается в переходе от матрицы 4x4 из ARTK к 3x3 для деформации перспективы. Как ты это делаешь?   -  person Hammer    schedule 07.12.2012
comment
Насколько я знаю, последний столбец — это перевод x/y/z, а последняя строка всегда 0 0 0 1, 1 для однородной координаты. Прямо сейчас я просто убираю их и просто сохраняю часть масштабирования и вращения... в то время как масштабирование должно быть 1.0.   -  person    schedule 07.12.2012


Ответы (1)


Ваша проблема в преобразовании из 4х4 в 3х3. Короткий ответ заключается в том, что вы хотите удалить 3-й столбец и нижнюю строку, чтобы сделать 3x3, а затем предварительно умножить на матрицу вашей камеры. Для более подробного объяснения см. 13106130#13106130">здесь

Пояснение Поза, которую вы получаете от ARTK, представляет собой преобразование из одного места в другое. Когда я говорю «исходное изображение появляется без вращения», я имею в виду, что ваше преобразование переходит из начального состояния, в котором нет вращения вокруг оси x или y, в текущее состояние. Это прекрасное предположение для большинства приложений дополненной реальности, я упомянул его просто для тщательности.

Что касается того, почему вы можете опустить 3-й столбец. Поскольку вы преобразуете плоскость, ваша координата z может быть полностью выражена вашими координатами x и y с учетом уравнения вашей плоскости. Если мы предположим, что изначально нет вращения, то ваша начальная координата z является постоянным значением. Если есть вращение, то z не является постоянным, но детерминировано изменяется по x и y в соответствии с его уравнением плоскости, которое все еще может быть выражено в одной матрице (хотя вам это не нужно). Поскольку в вашем случае ваше преобразование 4x4, вероятно, выражает преобразование из маркера, лежащего плоско на z = 0, в его текущее положение, 3-й столбец вашей матрицы 4x4 ничего не делает (все это умножается на 0), поэтому его можно отбросить, не затрагивая результат.

Вкратце: забудьте о вращении, это сложнее, чем вам нужно, просто поймите, что преобразование происходит от начальных координат к конечным координатам, а ваши начальные координаты всегда

[x,y,0,1]

что делает ваш третий столбец неактуальным.

Обновить Простите! Я только что перечитал ваш вопрос и понял, что вы просто хотите деформировать маркер, чтобы он выглядел как прямой, я увлекся описанием общего преобразования с 4x4 на 3x3. Преобразование 4x4, которое вы получаете от ARTK, — это не преобразование, которое деформирует варкер, это преобразование, которое перемещает маркер из исходного положения в его конечное положение. Чтобы деформировать маркер, как вы просили, процесс аналогичен, но будет немного отличаться. Я не делал этого раньше, но вот мое предположение.

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

initial_marker_pose = [1,0,0,0
                       0,1,0,0
                       0,0,1,100
                       0,0,0,1];

Теперь у вас есть преобразование из исходной точки в то, что вы хотите, в качестве «начальной» позиции и преобразование из исходной точки в вашу «конечную» позицию. Чтобы получить преобразование от начального к конечному, просто

initial_to_final = origin_to_marker*initial_marker_pose.inv();

Теперь вы должны следовать процессу, описанному в ссылке, которую я вам дал, в этом случае ваш начальный zpos больше не 0, а 100. Затем, когда вы закончите, вам нужно будет инвертировать матрицу 3x3. Это потому, что этот процесс переносит вас с прямого вида на тот, который определяется позой из ARTK, а вы хотите противоположного этому. Вам нужно будет поэкспериментировать с начальной позицией z. Чем он меньше, тем крупнее будет ваш маркер после устранения деформации.

Надеюсь, это сработает, извините за путаницу в вашем вопросе.

person Hammer    schedule 07.12.2012
comment
Спасибо, я посмотрел на ваш длинный ответ, но я действительно не понял всего этого. Если я уберу третий столбец, не лишит ли это части ротации? Кроме того, я не очень понял, что вы подразумеваете под Если вам нужно, чтобы решение работало без предположения, что исходное изображение появляется без вращения, дайте мне знать - маркер на изображении можно вращать по всем трем осям. Вы имеете в виду само полное изображение или маркер внутри него? - person ; 07.12.2012
comment
Спасибо за ваш обновленный ответ, это немного помогло. Я попытался реализовать это, и результаты, как мне кажется, стали лучше, но все равно происходит много искажений. Я делаю следующее: создаю матрицу (преобразованную, из вашего длинного ответа с zpos = 0), инвертирую ее и умножаю на матрицу моей камеры. Что-то еще не так? - person ; 10.12.2012
comment
@LaurelWolf единственное, что вы должны инвертировать, это матрица камеры. Результат длинного ответа: camera_matконвертируетсяпроецируется - person Hammer; 10.12.2012
comment
Извините, я неправильно понял ваш пост. Хотя сейчас я делаю так, как вы говорите, и все, что я получаю, — это один пиксель, растянутый до нового изображения. :[ Я сам измерил пиксельные координаты маркера, и opencv создал для меня перспективное преобразование, чтобы сравнить мой вывод с тем, что было бы правильным (я использовал углы маркера в качестве входных данных). Результат для матрицы преобразования перспективы OpenCV: 4,17 -0,3 -0. 0,05 3,09 -540 -0. -0. 1. Мой результат: -0. 0,0,5 -0,0 0,0 -0,4 -0,0 -0. 0,1 (когда я пишу 0, я имею в виду, что это не совсем ноль, но близко). Любые идеи? - person ; 11.12.2012
comment
Если поможет: матрица камеры такая: 534 0 309 0 534 214 0 0 1. матрица проекции: 0.002 -3.5e-10 -0.6 -6.5e-10 0.002 -0.4. преобразованная матрица: -0,986 -0,071 26 0,0578 0,994 11,1 -0,156 -0,08 342 - person ; 11.12.2012