Перспективна проекция в Android в приложение за разширена реалност

В момента пиша приложение за добавена реалност и имам някои проблеми с показването на обектите на моя екран. За мен е много разочароващо, че не мога да трансформирам gps-точки в съответните екранни точки на моето устройство с Android. Прочетох много статии и много други публикации в stackoverflow (вече задавах подобни въпроси), но все още имам нужда от вашата помощ.

Направих перспективната проекция, която е обяснена в wikipedia.

Какво трябва да направя с резултата от перспективната проекция, за да получа резултатната екранна точка?


person Frame91    schedule 17.05.2013    source източник


Отговори (1)


Статията в Уикипедия също ме обърка, когато я прочетох преди време. Ето моя опит да го обясня по различен начин:


Положението

Нека опростим ситуацията. Ние имаме:

  • Нашата проектирана точка D(x,y,z) - това, което наричате относителна позицияX|Y|Z
  • Равнина на изображение с размер w * h
  • половин зрителен ъгъл α

...и ние искаме:

  • Координатите на B в равнината на изображението (нека ги наречем X и Y)

Схема за X-екранните координати:

E е позицията на нашето "око" в тази конфигурация, която избрах като начало за опростяване.

Фокусното разстояние f може да се оцени, като се знае, че:

  • tan(α) = (w/2) / f (1)

Малко геометрия

Можете да видите на снимката, че триъгълниците ECD и EBM са подобни, така че използването на теорема за страничен разделител, получаваме:

  • MB / CD = EM / EC ‹=> X / x = f / z (2)

И с (1), и с (2) вече имаме:

  • X = (x / z) * ( (w / 2) / tan(α) )

Ако се върнем към нотацията, използвана в статията в Wikipedia, нашето уравнение е еквивалентно на:

  • b_x = (d_x / d_z) * r_z

Можете да забележите, че пропускаме умножението с s_x / r_x. Това е така, защото в нашия случай "размерът на дисплея" и "повърхността на запис" са еднакви, така че s_x / r_x = 1.

Забележка: Същата аргументация за Y.


Практическа употреба

Някои забележки:

  • Обикновено се използва α = 45deg, което означава tan(α) = 1. Ето защо този термин не се появява в много реализации.
  • Ако искате да запазите съотношението на елементите, които показвате, дръжте f постоянно за X и Y, т.е. вместо да изчислявате:

    • X = (x / z) * ( (w / 2) / tan(α) ) and Y = (y / z) * ( (h / 2) / tan(α) )

    ... do:

    • X = (x / z) * ( (min(w,h) / 2) / tan(α) ) и Y = (y / z) * ( (min(w,h) / 2) / tan(α) )

    Забележка: когато казах, че „„размерът на дисплея“ и „записващата повърхност“ са еднакви“, това не беше съвсем вярно и мин е тук, за да компенсира това приближение, адаптирайки квадратната повърхност r към потенциално правоъгълната повърхност s.

    Бележка 2: Вместо да използва min(w,h) / 2, Appunta използва screenRatio= (getWidth()+getHeight())/2, както забелязахте. И двете решения запазват съотношението на елементите. Фокусът и следователно зрителният ъгъл просто ще бъдат малко по-различни в зависимост от съотношението на екрана. Всъщност можете да използвате всяка функция, която искате, за да дефинирате f.

  • Както може би сте забелязали на снимката по-горе, координатите на екрана тук са определени между [-w/2 ; w/2] за X и [-h/2 ; h/2] за Y, но вероятно искате [0 ; w] и [0 ; h] вместо това. X += w/2 и Y += h/2 - Проблемът е разрешен.


Заключение

Надявам се това да отговори на вашите въпроси. Ще остана наблизо, ако има нужда от издания.

Чао!

‹ Сигнал за самореклама > Всъщност направих преди известно време статия за 3D проекция и изобразяване. Изпълнението е в Javascript, но трябва да е доста лесно за превод.

person benjaminplanche    schedule 23.05.2013
comment
Хей! Благодаря за този наистина информативен отговор!! Ще пробвам :) И ти благодаря за статията за 3D проекцията! Наистина ми е полезно ;) - person Frame91; 23.05.2013
comment
Може ли да ми обясните какво под зрителен ъгъл имате предвид? Имам хоризонтален и вертикален зрителен ъгъл (не проверих дали са равни), а в статията в wikipedia се споменава и диагонален зрителен ъгъл (: - person Frame91; 23.05.2013
comment
В метода, който представям, е както хоризонталния, така и вертикалния зрителен ъгъл (тъй като използвам по-малка ефективна квадратна равнина на изображение с размери min(h,w) ) x min(h,w)). Но можете да го настроите, за да използвате вашите 2 стойности и целия ефективен екран w x h вместо това, ако искате. - person benjaminplanche; 23.05.2013
comment
Ако съм разбрал правилно, трябва да използвам хоризонталния зрителен ъгъл в X = (x / z) * ( (min(w,h) / 2) / tan(α)) и вертикалния зрителен ъгъл в Y = (y / z) * ((min(w,h) / 2) / tan(α)). Размерът ще бъде h*w вместо min(h,w)*min(h,w)? Така че получавам: X = (x / z) * (w / 2) / тен(вертикален ъгъл на видимост)) и Y = (y / z) * (h / 2) / тен(хоризонтален ъгъл на видимост))? Благодаря много! - person Frame91; 23.05.2013
comment
Да, тогава просто проверете коефициента си. В зависимост от вашите ъгли и размери, резултатите може да са малко засегнати (но предполагам, че вашите ъгли трябва вече да са изчислени, за да предотвратите това, така че трябва да е добре) :) - person benjaminplanche; 23.05.2013
comment
Благодаря ти много! Не получавам никаква добра стойност, но мисля, че това зависи от моята трансформация от шир/дължина/надморска височина към декартова координатна система. Координатните ми данни са в метри (x,y,z) и ги изчислявам с формулата на haversina и пеленга между камерата до точката, която искам да проектирам. И с двете стойности мога да използвам тригонометрия за изчисляване на x и y. Моята z стойност е просто изваждане от височината на камерата и височината на точката. Използваема ли е тази координатна система? Трябва ли да конвертирам метрите в някаква друга стойност? (напр. пиксел?) благодаря много! - person Frame91; 23.05.2013
comment
Хей, не съм много запознат с координатите шир/дължина/височина, съжалявам. Но може би първо трябва да проверите откъде идва грешката - преобразуването на вашата координатна система или вашата проекция. Опитайте например да използвате своя проекционен метод с просто въвеждане (8 точки, образуващи куб например), за да можете да проверите изхода, знаейки какво да очаквате (куб от избраната точка на изглед). - person benjaminplanche; 25.05.2013
comment
добре..както и да е... благодаря много за вашите наистина информативни отговори!! - person Frame91; 25.05.2013
comment
Добре... Имам един последен въпрос ;) Какво не разбирам: Как моята проекция знае къде да проектира точката на екрана, защото: Моята координатна система е в метри, моята ширина/височина на екрана е в пиксел. Например, мога да променя координатната си система на ECEF или друга декартова координатна система и ще получа други dx, dy, dz стойности... което е наистина странно. Споменахте, че не увеличавате нещата, така че мисля, че просто разработвате 3D приложения с виртуална камера. Височината/ширината на вашата камера в същата единица ли е като вашия свят? - person Frame91; 26.05.2013
comment
По време на проекцията, когато правите b_x = (d_x / d_z) * r_z, d_x и d_z са в единицата за реалния свят, която сте избрали, докато b_x и r_z са в единицата на вашия екран (вероятно пиксели). Следователно (d_x / d_z) е без единица, тъй като изчислявате относителната пропорция и като умножите по r_z, прилагате тази пропорция към размера на екрана. - person benjaminplanche; 26.05.2013
comment
Хей... отново аз, тествах няколко неща и все още не разбирам как проекцията знае кое е далеч и кое е близо: Когато променям координатната си система в милиметри, получавам стойности 1000 пъти по-високи от преди. Моята относителна позиция X е например 1100 в този случай. Това води до координати на точки на екрана като (5000,10000), които не могат да бъдат показани на моя дисплей. В момента моята координатна система е в метри и получавам някои валидни стойности... но проекцията ми не може да знае за това. Къде трябва да управлявам това? Благодаря - person Frame91; 26.05.2013
comment
Опитах се да отговоря по-изрично в другата ви тема (stackoverflow.com/a/16792965/624547). Надявам се, че ще помогне. - person benjaminplanche; 28.05.2013
comment
Здравейте, съжалявам за некропоста, но можете ли да обясните Обикновено се използва α = 90 градуса, което означава tan(α) = 1? Не трябва ли tan(90deg) да е недефиниран? - person kikito; 09.11.2016
comment
Здравей @kikito, благодаря, че забеляза правописната грешка! Трябваше да бъде 2α = 90deg (или α = 45deg). Коригирах отговорите си съответно. Благодаря отново! - person benjaminplanche; 12.11.2016