Mastering OpenCV with Practical Computer Vision Projects / Опановуюємо OpenCV через практичні проекти комп'ютерного зору: Розділ 2. Доповнена реальність на iOS та Android з використанням маркерів
| Английский оригинал | Перевод на украинский | |
|---|---|---|
Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
Обробка місцеположення маркера Atronax 18.02.21 в 07:41 |
|
|
Визначивши вірну орієнтацію маркера, повертаємо його кути так, щоб забезпечити правильний порядок: Atronax 18.02.21 в 07:44 |
||
|
Після розпізнавання маркера та декодування ідентифікатора, обробимо його кути. Ця операція знадобиться, коли ми оцінюватимемо положення маркера у тривимірному просторі. Щоб знайти положення точки з субпіксельною точністю, використаємо функцію cv::cornerSubPix: Atronax 18.02.21 в 07:49 |
||
|
Спершу підготуємо вхідні дані. Копіюємо список вершин у масив, після чого викликаємо функцію cv::cornerSubPix, передаємо поточне зображення, набір точок, а також встановлюємо групу параметрів, що впливають на якість та продуктивність обробки позицій. По закінченню процесу передаємо оброблені дані назад до кутів маркерів, як показано на наступному малюнку. Atronax 18.02.21 в 07:55 |
||
|
Ми не використовуємо функцію cornerSubPix на ранніх етапах через її складність. Це надто дорога операція, якщо на вхід подати велику кількість точок (говоримо про необхідний для обчислень час). Тому проводимо її лише для дійсних маркерів. Atronax 18.02.21 в 08:00 |
||
|
Розміщуємо маркер у тривимірному просторі Atronax 18.02.21 в 08:00 |
||
|
Доповнена реальність намагається об'єднати дійсний об'єкт з віртуальним контентом. Щоб помістити 3D-модель на сцені, потрібно знати її позу відповідно до камери, використаної для захоплення відеокадрів. Скористаємось евклідовими перетвореннями в прямокутній системі координат, щоб представити її. Позиція маркера в тривимірному та відповідна проєкція у двовимірному просторі обмежена наступним рівнянням: Atronax 18.02.21 в 08:09 |
||
|
Виконавши крок розпізнавання маркера, ми отримаємо чотири кути маркера у двовимірному просторі (проєкція в екранних координатах). У наступній частині ви дізнаєтесь, як знайти матрицю A та вектор параметрів M, а також як обрахувати перетворення [R|T]. Atronax 18.02.21 в 08:12 |
||
|
Калібрування камери Atronax 18.02.21 в 08:12 |
||
|
Кожна лінза камери має унікальний набір характеристик, серед яких фокусна відстань, кардинальна точка та модель викривлень. Пошук внутрішніх параметрів камери називають калібруванням. Цей процес важливий для застосунків з доповненою реальністю, адже описує перетворення перспективи та викривлення лінзи на вихідному зображенні. Щоб досягнути кращого досвіду користувача, візуалізація доповненого об'єкта має відбутися з тою ж перспективною проєкцією. Atronax 18.02.21 в 08:21 |
||
|
Для калібрування знадобиться особливе зображення шаблону (шахова дошка чи чорні кола на білому фоні). Камера, над якою здійснюють цей процес, робить 10-15 знімків шаблону з різних точок зору. Потім алгоритм калібрування знаходить оптимальні внутрішні параметри та вектор викривлень: Atronax 18.02.21 в 08:24 |
||
|
Для опису калібрування камери використаємо клас CameraCalibration: Atronax 18.02.21 в 08:31 |
||
|
Детальне пояснення процедури калібрування лежить за межами цього розділу. Зверніть увагу на приклад camera_calibration чи статтю "OpenCV: оцінка відношень проєкції на зображеннях" за адресою http://www.packtpub.com/article/opencv-estimating-projective-relations-images, щоб знайти додаткову інформацію чи код. Atronax 18.02.21 в 08:35 |
||
|
Що ж до цього прикладу, подамо внутрішні параметри для всіх сучасних пристроїв iOS (iPad2, iPad3 та iPhone 4). Atronax 18.02.21 в 08:43 |
||
|
Оцінка пози маркера Atronax 18.02.21 в 08:43 |
||
|
Маючи точне положення кутів, можна вирахувати перетворення між камерою та маркером у тривимірному просторі. Таку операцію називають оцінкою пози з урахуванням відношень 2D-3D. Даний процес дозволяє знайти евклідові перетворення (що складаються лише з компонентів повороту та перенесення) між камерою та об'єктом. Atronax 18.02.21 в 08:50 |
||
|
Точка С призначена позначати центр камери. P1-P4 - це тривимірні точки у світовій координатній системі, а p1-p4 - їхні проєкції на площину зображення. Ми маємо знайти відносні перетворення між відомою позицією маркера в 3D і камерою C, що використовує матрицю внутрішнього стану, та відомими проєкціями на поверхні зображення. Але ж як ми знайдемо координати позиції маркера у тривимірному просторі? Уявимо. Маркер завжди має квадратну форму, а вершини лежать в одній площині, тому кути можна визначити так: Atronax 18.02.21 в 08:59 |
||
|
Помістимо маркер на площину XY (компонента Z рівна нулю), причому центр маркера відповідатиме точці (0.0, 0.0, 0.0). Це необхідний крок, адже в такому випадку координатна система матиме початок в центрі маркера (вісь Z перпендикулярна площині маркера). Atronax 18.02.21 в 09:04 |
||
|
Параметр objectPoints - це вхідний масив точок об'єкта у локальній площині координат. Це може бути, наприклад, std::vector<cv::Point3f>. Матрицю OpenCV з розмірами 3xN чи Nx3, де N - це кількість точок, також можна передати як вхідний аргумент. Тут ми передаємо список координат маркера в тривимірному просторі (вектор 4 точок). Atronax 18.02.21 в 09:13 |
||
|
Об'єкт imagePoints - це масив відповідних точок зображення (чи проєкцій). Також аргумент може мати тип std::vector<cv::Point2f> чи cv::Mat з розмірами 2xN чи Nx2, де N - це кількість точок. Atronax 18.02.21 в 10:04 |
||
|
Сюди передаємо список знайдених кутів маркера. Atronax 18.02.21 в 10:33 |
||
|
Функція знаходить перетворення камери у спосіб, що мінімізує похибку повторної проєкції, тобто суму квадратів відстаней між спостереженими точками imagePoints та проєктованими objectPoints. Atronax 18.02.21 в 10:43 |
||
|
Вирахувані перетворення визначені поворотом (rvec) та перенесенням (tvec). Вони також відомі як евклідові або ортогональні. Atronax 18.02.21 в 10:47 |
||
|
Евклідові перетворення формально визначено як такі, що перетворюють будь-який вектор v на інший, T(v), що має форму: Atronax 18.02.21 в 10:53 |
||
|
Це значить, що R не формує віддзеркалень і, таким чином, визначає поворот (ортогональне перетворення, що зберігає орієнтацію). Для пошуку матриці розмірності 3x3 з вектора застосовано функцію cv::Rodrigues. Вона конвертує поворот, представлений вектором, та повертає еквівалентну матрицю. Atronax 18.02.21 в 11:03 |
||
|
Примітка Atronax 18.02.21 в 11:08 |
||
|
Це лістинг функції estimatePosition, яка шукає позицію виявлених маркерів: Atronax 18.02.21 в 11:12 |
||
|
Візуалізуємо тривимірний віртуальний об'єкт Atronax 18.02.21 в 11:13 |
||
|
Дотепер ми дізнались, яким чином шукати маркери на зображенні, щоб визначити їхню точну позицію в просторі відносно камери. Настав час дещо намалювати. Як вже зазначено, для цього ми використаємо функції OpenGL. 3D візуалізація - це наріжний камінь доповненої реальності. Бібліотека OpenGL пропонує базові можливості для створення високоякісної графіки. Atronax 18.02.21 в 11:18 |
||
|
Примітка Atronax 18.02.21 в 11:22 |
||
|
Розуміння принципів систем візуалізації наділить вас необхідним досвідом та знаннями, необхідними для використання цих двигунів чи створення власних. Atronax 18.02.21 в 11:23 |
||
|
Створюємо рівень візуалізації OpenGL Atronax 18.02.21 в 11:23 |
||
|
Щоб використати функції OpenGL у своєму застосунку, необхідно отримати контекстну поверхню графіки iOS, яка презентуватиме візуалізовану сцену. Частіше за все, контекст прив'язано до виду, який спостерігає користувач. Наступний скріншот показує ієрархію інтерфейсу програми в інструменті XCode для їх побудови: Atronax 18.02.21 в 11:30 |
||
|
Інкапсулюємо логіку налаштування контексту OpenGL у класі EAGLView: Atronax 18.02.21 в 11:38 |
||
|
Цей клас під'єднується до нашого виду у файлі визначень інтерфейсів, тому, коли завантажується файл NIB, потік виконання створить новий екземпляр класу EAGLView. Він прийматиме події від iOS та налаштує контекст візуалізації OpenGL. Atronax 18.02.21 в 12:16 |
||
|
Далі розміщено код функції initWithCoder: Atronax 18.02.21 в 12:22 |
||
|
- (void)createFramebuffer Atronax 18.02.21 в 12:24 |
||
|
Візуалізуємо сцену доповненої реальності Atronax 18.02.21 в 12:25 |
||
|
Вочевидь, клас EAGLView не включає методи для візуалізації тривимірних об'єктів та відео. Це робиться на вимогу. Завдання EAGLView - лише забезпечити наявність контексту. Подібне відокремлення відповідальності дозволяє пізніше змінити логіку візуалізації. Atronax 18.02.21 в 12:33 |
||
|
Для візуалізації доповненої реальності створимо окремий клас з назвою Atronax 18.02.21 в 12:35 |
||
|
Функція drawFrame виконує візуалізацію доповненої реальності на заданий цільовий вид EAGLView. Він включає наступні кроки: Atronax 18.02.21 в 12:43 |
||
|
Функцію drawFrame викликаємо, коли кадр повністю готовий для малювання. Це відбувається, коли зображення з камери вже надійшло до відеопам'яті, а етап розпізнавання маркера завершено. Наступний код належить цій функції: Atronax 18.02.21 в 12:52 |
||
|
- (void)drawFrame Atronax 18.02.21 в 12:55 |
||
|
Намалювати фон доволі легко; ми встановлюємо ортографічну проєкцію та виводимо повноекранну текстуру, створену із зображення поточного кадра. Ось лістинг коду, що використовує GLES 1 API з цією метою: Atronax 18.02.21 в 12:57 |
||
|
- (void) drawBackground Atronax 18.02.21 в 12:58 |
||
|
Візуалізація штучних об'єктів на сцені - доволі специфічна задача. Спершу маємо налаштувати матрицю проєкції OpenGL відносно внутрішньої матриці калібрування камери. Без цього ми отримаємо некоректне перетворення перспективи. А це призведе до неприродного вигляду штучних об'єктів, які, так би мовити, "здійматимуться над поверхнею", а не будуть частиною дійсності. Правильна перспектива життєво важлива для будь-якої програми з доповненою реальністю. Atronax 18.02.21 в 13:02 |
||
|
Це фрагмент коду, що формує матрицю проєкції OpenGL з внутрішніх характеристик камери: Atronax 18.02.21 в 13:10 |
||
|
projectionMatrix.data[0] = - 2.0 * f_x / screen_width; Atronax 18.02.21 в 13:10 |
||
|
Під'єднавши останню до потоку роботи OpenGL, намалюємо декілька об'єктів. Кожне перетворення можна описати матрицею розмірності 4x4 та завантажити у внутрішню бібліотеки, моделі-виду. Це перемістить початок координат у позицію маркера у світовій системі. Atronax 18.02.21 в 13:19 |
||
|
Наприклад, намалюємо над кожним маркером вісь координат, що покаже його орієнтацію в просторі, та чотирикутник із градієнтною заливкою, який заповнить увесь маркер. Таким чином ми сформуємо візуальний доказ того, що код працює як належить. Atronax 18.02.21 в 14:01 |
