Намерете 3D позицията и ориентацията на камерата ми според 2D маркер

В момента изграждам приложение за разширена реалност и се спрях на проблем, който изглежда доста лесен, но е много труден за мен ... Проблемът е както следва:

Камерата на устройството ми е калибрирана и открива 2D маркер (като QRCode). Знам фокусното разстояние, позицията на сензора, разстоянието между камерата ми и центъра на маркера, реалния размер на маркера и координатите на 4-те ъгъла на маркера и на неговия център върху 2D изображението, което получих от камера. Вижте следното изображение:

илюстрация

На изображението знаем разстоянията a, b, c, d и координатите на червените точки.

Това, което трябва да знам, е позицията и ориентацията на камерата според маркера (както е представено на изображението, началото е центърът на маркера).

Има ли лесен и бърз начин да го направите? Опитах някакъв метод, измислен от мен (използвайки формулите на Ал-Каши), но това завърши с твърде много грешки :(. Може ли някой да посочи начин да ме измъкне от това?


person Cocottier    schedule 14.01.2015    source източник
comment
Това обикновено се разрешава чрез така наречения PnP алгоритъм (вижте напр. тази статия). Какъв програмен език/библиотека използвате?   -  person BConic    schedule 14.01.2015
comment
Знаех за това решение, но е твърде сложно за мен, познанията ми не са достатъчно добри, за да го разбера напълно. Използвам C и рисувам с OpenGL (и нищо повече). Имам напълно работещо AR приложение, което развивам, за да използвам маркери (преди това използвахме библиотека, наречена Vuforia). Единственото, което остава, е да заемете тази проклета позиция на камерата :( Има ли по-лесен начин?   -  person Cocottier    schedule 14.01.2015
comment
Това не е прост проблем, не мисля, че има по-лесен начин... Но може би можете да намерите някакъв код или лека библиотека, която да използвате.   -  person BConic    schedule 14.01.2015
comment
Ще потърся това (донякъде вече го направих, но обикновено функциите не са толкова коментирани, така че все още са трудни за разбиране и използването на нещо, което не разбирам как работи, е нещо, което малко не ми харесва). Може да намеря такъв, който да ми помогне да разбера по-добре проблема!   -  person Cocottier    schedule 15.01.2015


Отговори (2)


Можете да намерите примерен код за алгоритъма EPnP на тази уеб страница. Този код се състои от един заглавен файл и един изходен файл, плюс един файл за примера за използване, така че не би трябвало да е твърде трудно да го включите в кода си.

Обърнете внимание, че този код е пуснат само за целите на проучване/оценка, както е споменато на тази страница.

РЕДАКТИРАНЕ:

Току-що разбрах, че този код се нуждае от OpenCV, за да работи. Между другото, въпреки че това би добавило доста голяма зависимост към вашия проект, текущата версия на OpenCV има вградена функция, наречена solvePnP, която прави това, което искате.

person BConic    schedule 15.01.2015
comment
Ще потърся и двамата и ще ви държа в течение, благодаря ви за помощта! - person Cocottier; 15.01.2015
comment
Така че разглеждах функцията solvePnP от OpenCV, но нито един от методите, извикани във функцията, не е достъпен (PnP(), P3Psolver(), ...), нито е посочен в заглавка (така че няма външна библиотека). Как е възможно? О_о - person Cocottier; 15.01.2015
comment
Те са вътрешни за библиотеката. Трябва да използвате функцията solvePnP директно. Има известна документация за тази функция. FYI, PnP и P3PSolver са екземпляри на функтори от типове epnp и p3p (вижте редове 64 и 76 на solvepnp.cpp), които са дефинирани в p3p.h/cpp и epnp.h/cpp. - person BConic; 15.01.2015
comment
Добре, проучвам още малко как да разреша проблема си благодарение на вас и OpenCV, но останах на този ред: github.com/Itseez/opencv/blob/ Какъв е неговият ефект? Мислех, че извика конструктора, който също не разбирам: github.com/Itseez/opencv/blob/ Някаква идея? - person Cocottier; 15.01.2015
comment
Отново, това е функтор: svd е екземпляр на класа cv::SVD, който претоварва operator(). Следователно извършването на svd(...) е като извикване на функция. Вижте тази публикация за повече подробности относно функторите. - person BConic; 15.01.2015
comment
Разбрах, но какво прави тази функция? Искам да кажа, че в примера, който ми даде, създадохме нов екземпляр на функтора (това правим с cv::SVD и след това използваме този функтор svd(...)), но тук функцията зад функтора не се появява: operator ()(m, flags);. Изобщо нищо ли не прави? Имам предвид, че тялото на функтора е заменено с ; ... Разбирам лесно поведението на този в примера int operator()(int y) { return x + y; }. Но като използвам този пример, този с SVD изглежда очевидно не прави нищо, трябва да греша, защото няма да има смисъл да извиквам нищо ... - person Cocottier; 15.01.2015
comment
Тъй като cv::SVD е клас, тялото на operator() може да бъде дефинирано другаде, както всяка друга членска функция. Обикновено декларирате членски функции в заглавни файлове и дефинирате тялото им в cpp файлове, същото важи и за операторите. В този конкретен случай cv::SVD::operator() е дефинирано на ред 1614 от lapack.cpp. Това изчислява SVD (т.е. Разлагане на единична стойност) на матрица a, което след това се използва в остатък от функцията, чрез svd.u svd.vt и svd.w. - person BConic; 15.01.2015
comment
Тъй като не мога да разбера как работят тези неща, просто ще използвам OpenCV, за да реша проблема си. Много благодаря за твоята помощ. Може да го погледна отново някой ден, но в момента това ме устройва. Благодаря отново, че ме научи какво представляват функторите :) - person Cocottier; 19.01.2015

Можете да изчислите хомографията между точките на изображението и съответните световни точки. След това от хомографията можете да изчислите ротацията и транслацията, преобразувайки точка от координатната система на маркера в координатната система на камерата. Математиката е описана в документ за калибриране на камера от Джан.

Ето един пример в MATLAB с помощта на Computer Vision System Toolbox, който прави повечето от това, от което се нуждаете. Той използва функцията extrinsics, която изчислява 3D ротация и транслация от съвпадащо изображение и световни точки. Не е необходимо точките да идват от шахматна дъска.

person Dima    schedule 15.01.2015
comment
Здравейте, благодаря, че посочихте този метод. Тъй като имам много по-малко точки от шахматна дъска, мислите ли, че все още мога да използвам този метод? Ако да, възможно ли е да се намери източникът на външната функция? - person Cocottier; 15.01.2015
comment
@user2342594, Имате нужда от поне 4 неколинеарни точки, за да изчислите хомографията, която е 2d проективна трансформация. Математиката за изчисляване на R и t от известна вътрешна матрица и хомография е дадена на страница 6 от документа. Това е доста лесно за кодиране. Ако имате скорошна версия на MATLAB с Computer Vision System Toolbox, можете просто да погледнете източника за extrinsics(). - person Dima; 15.01.2015