Як зняти чотирикутник на прямокутник?


10

tl; dr: Математична задача в геометрії проективності: як можна знайти матрицю камери 4x4, яка дає проекцію, як показано нижче, такі, що точки A, B, C, D знаходяться десь на краях одиничного блоку (наприклад, нормалізований пристрій OpenGL координати), а кути блоку одиниці падають десь розумно вздовж променів EA, EB, EC, ED?

(Це може бути особливий випадок, можливо, гомографії, перспективності та / або колінеації. Не знайомий з термінологією.)


опрацювання

Враховуючи чотирикутник ABCD у вікні перегляду, я думаю, існує унікальне (?) Перетворення, яке відображає його назад у прямокутник. Як видно із зображення нижче: чотирикутник ABCD у вікні перегляду виступає фізичним "вікном", і якщо ми повернемо його до прямокутника, він виявиться спотвореним.

введіть тут опис зображення

(поле праворуч представляє NDC, про який я розповім пізніше)

Мета - швидко отримати зображення праворуч. Ми могли б простежити кожну точку, щоб отримати зображення (що я зробив), але я вважаю за краще використовувати OpenGL або інші проективні методи, тому що хотів скористатися такими речами, як змішування, примітиви тощо.

перша спроба

Я вважаю, що я можу вирішити проблему пошуку матриці камери 3x4, яка робить 3 + 1-мірну однорідну координату в 3-просторі (зліва) і спроектує її вниз на 2 + 1 розмірну однорідну координату в 2-просторі (на право). Вирішити це можна за допомогою прямого лінійного перетворення, щоб отримати систему рівнянь Ba=0для невідомих записів aматриці камери та вирішити систему за допомогою розкладання сингулярного значення.(SVD). Я б вважав вектори EA, EB, EC, ED (де E - ваше фізичне око або камера у світовому просторі) як точки на попередньому зображенні, і (0,0), (1,0), (1 , 1), (0,1) або щось подібне до точок на пост-зображенні, і кожна пара точок дала б декілька лінійних рівнянь для підключення до SVD. Отримана матриця відображатиме EA -> (0,0) тощо (якщо припустимо, що існує достатня ступінь свободи, тобто якщо рішення унікальне, в чому я не впевнений, див. Примітку [a])

Але, на превеликий жаль, це не так, як OpenGL працює. OpenGL не проектує безпосередньо 3d-2d з матрицею 3x4. OpenGL вимагає "нормалізованих координат пристрою" (NDC), які є тривимірними точками. Після проектування в NDC, все у вікні "одиниця" складається від (-1, -1, -1,1) до (1,1,1,1); все зовні відсікається (оскільки ми маємо справу з однорідними координатами: будь-яка точка (x, y, z, w) з'явиться на екрані лише у випадку, якщо перші три координати (x / w, y / w, z / w) , 1) знаходяться в коробці одиниць від -1 до 1).

Тож виникає питання: чи існує якась обґрунтована трансформація, яка відображає якусь дивну кубовидну кубоїду в однорідних координатах (зокрема кубоїді, намальованій зліва, з ABCD (передні точки) та A'B'C'D '(зворотні точки, приховані за передніми точками)) до одиничного куба, наприклад, використовуючи матрицю 4x4? Як це зробити?

що я спробував

Я спробував щось сильніше: я зробив ABCD і A'B'C'D 'схожими на звичайний пірамідальний фруструм (наприклад, gl frustrum) (тобто в цій гіпотетичній установці зображення ліворуч буде просто чорним прямокутником, накладеним на це, а не чотирикутник), а потім використовував DLT / пряме лінійне перетворення для вирішення імовірної матриці 4x4. Однак коли я спробував це, здавалося, не вистачало ступеня свободи ... отримана матриця 4x4 не відображала кожен вхідний вектор на кожен вихідний вектор. Під час використання A, B, C, D, A '(5 пар векторів перед трансформацією та після трансформації) я / майже / отримую результат, який я хочу ... вектори відображаються правильно, але, наприклад, B', C ', D' відображаються на (3,3,1,1) замість (-1, -1,1,1) і відсікаються OpenGL. Якщо я спробую додати шосту точку (6 пар точок для матриці 4x4 до проекту), моє рішення здається виродженим (нулі, нескінченність). Скільки ступенів свободи я маю тут справу, і чи можливо це за допомогою матриці 4x4, що відображає звичайні 4 вектори (3 + 1-мірні однорідні координатні вектори), які ми знаємо і любимо?

випадкові другорядні думки

Я здогадуюсь, що неможливо зіставити будь-яку довільну кубоїду до будь-якої довільної кубоїди з матрицею 4х4, хоча я збентежений, тому що я думав, що можна зіставити будь-який опуклий чотирикутник на будь-який інший опуклий чотирикутник у 2d з якоюсь матрицею, наприклад, у , скажімо, Photoshop? ... може / не можна цього зробити за допомогою проективного перетворення? І як це узагальнюється до 3d? ...... Також, враховуючи невдалу спробу знайти матрицю 4x4, лінійна алгебра говорить, що ми не повинні очікувати, що матриця NxN відобразить більше ніж N лінійно незалежних точок на N цільових точок в кращому випадку, але я відчуваю це якось однорідним Координати це обманюють, бо відбувається якась прихована узгодженість? Я думаю що ні?

інше рішення?

Я думаю, можна також зробити наступну потворну річ, де ви використовуєте типову матрицю проекції камери фрустру, знайдіть 2d точки, що відповідають кутам, а потім виконайте 2d перспективу спотворює гомографію, але якщо це відбудеться після надання пікселів (наприклад, фотошоп), тоді виникнуть проблеми з роздільною здатністю ... можливо, гіпотетично можна було б знайти матрицю для виконання цього перетворення на площині XY всередині NDC-простору, а потім скласти його за допомогою звичайної матриці на основі фрустру?

(Примітка [a]: Ступінь свободи: ABCD можна додатково обмежувати пост-зображенням проективного перетворення, що діє на прямокутник, якщо це необхідно ... тобто чорний прямокутник ліворуч можна сказати результат проектування графічної моделі фоторамки)


1
Якщо ви перейдете на Google для кутового штифта, ви отримаєте кілька реалізацій цього
joojaa

Відповіді:


1

Я думаю, що рішення шукає проективну трансформацію, яка правильно трансформує чотири точки.

тобто

y=P×x

де іx=[x0,x1,1]y=[y0y2,y1y2]

P - матриця 3x3 з 9 записами. Завдяки остаточній нормалізації це унікально до масштабування, залишаючи 8 ступенів свободи, які однозначно визначаються 8 рівняннями, поданими відповідності (2 на пару бальних пар).

Тепер ви можете використовувати алгебру для цього або просто використовувати OpenCV getPerspectiveTransform:).

Також ознайомтеся з омоногенними координатами у вікіпедії, щоб ознайомитись з концепцією.


Дякую! (Я вирішив це деякий час тому і опублікував рішення саме зараз, коли побачив ваш коментар.)
ninjagecko

0

Я вирішив власне питання, реалізуючи Пряме лінійне перетворення . Розділ із прикладами у Вікіпедії був моїм випадком використання.

Щоб отримати рівняння, підключіть матриці (наприклад [x1 x2 x3 x4; x5 x6 x7 x8; x9 x10 x11 x12]) до вашої улюбленої системи комп'ютерної алгебри, наприклад SageMath, а потім розв’яжіть необхідне матричне рівняння, як показано на малюнку, скопіюйте та вставте рішення у вигляді змінних у свій код та відрегулюйте форматування.

Тоді можна було б адаптувати рішення до власного випадку використання шляхом масштабування або ігнорування конкретних розмірів, якщо це доречно (наприклад, ігноруйте координату глибини / z у матриці нормалізованих координат пристрою відповідно до випадку використання).

Вам знадобиться функція або бібліотека розкладання SVD на вашій мові.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.