Mastering OpenCV with Practical Computer Vision Projects / Опановуюємо OpenCV через практичні проекти комп'ютерного зору: Розділ 2. Доповнена реальність на iOS та Android з використанням маркерів
| Английский оригинал | Перевод на украинский | |
|---|---|---|
Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
Доповнена реальність (AR) - це живе зображення реального середовища із фрагментами, доповненими згенерованими комп'ютером графічними елементами. В результаті технології покращують сприйняття людиною дійсності. За домовленістю доповнення відбувається в режимі реального часу та семантичному контексті з елементами середовища. Завдяки розвиненим AR технологіям (наприклад, приєднанню комп'ютерного зору та розпізнавання об'єктів) інформація про навколишній світ користувача стає інтерактивною та може оброблюватись цифровими методами. Штучні дані про середовище та об'єкти можна розмістити над реальними кадрами. Atronax 16.02.21 в 07:35 |
|
|
У цьому розділі ми створимо AR застосунок для мобільних пристроїв iPhone/iPad. Для початку зупинимось на програмі, що використовує маркери для виводу штучних об'єктів на поверхні отриманих з камери кадрів. Ви зрозумієте, як налаштувати проєкт в середовищі розробки XCode та приєднати до нього бібліотеку OpenCV. Окрім того, пояснено такі речі як захоплення відеопотоку з вбудованої камери, візуалізація тривимірної сцени з використанням OpenGL ES та побудова базової архітектури застосунку AR. Перш за все, подамо вичерпний список знань та необхідних програмних рішень: Atronax 16.02.21 в 07:58 |
||
|
Знадобиться комп'ютер Apple зі встановленим середовищем XCode. Розробка застосунків для iPhone/iPad можлива лише з його використанням. Це єдиний спосіб програмувати для платформи iOS. Atronax 16.02.21 в 08:19 |
||
|
З цього розділу ви дізнаєтесь більше про маркери, а також повну процедуру їх розпізнавання. Читаючи далі, ви зможете створити власний алгоритм розпізнавання маркерів, оцінити їх позу у тривимірному просторі залежно від пози камери та використати перетворення між останніми, щоб візуалізувати довільні 3D об'єкти. Atronax 16.02.21 в 08:23 |
||
|
Серед додатків до книги доступний навчальний проєкт до цього розділу. Це добра початкова точка для створення першого мобільного застосунку з доповненою реальністю. Atronax 16.02.21 в 08:29 |
||
|
Створення iOS проєкту, що використовує OpenCV Atronax 16.02.21 в 08:39 |
||
|
Почнемо зі створення нового проєкту XCode. Оберемо шаблон "iOS Single View Application", як показано на наступному скріншоті: Atronax 16.02.21 в 08:41 |
||
|
Тепер маємо додати OpenCV до проєкту. Цей крок необхідний, адже застосунок використає багато функцій бібліотеки для розпізнавання маркерів та оцінки їх пози. Atronax 16.02.21 в 08:42 |
||
|
OpenCV - це бібліотека для програмування функцій комп'ютерного зору в режимі реального часу. Вона розроблена компанією Intel, а зараз підтримується авторами Willow Garage та Itseez. Бібліотека написана мовами C та С++. Існує також офіційний модуль для Python та неофіційні для Java та .NET. Atronax 16.02.21 в 08:45 |
||
|
Додаємо фреймворк OpenCV Atronax 16.02.21 в 08:47 |
||
|
На щастя, бібліотека кросплатформова, тому її можна використати на пристроях iOS. Починаючи з версії 2.4.2, OpenCV офіційно підтримується на платформі iOS, відповідний пакет можна завантажити із сайту бібліотеки на http://opencv.org/. За адресою OpenCV для iOS знаходиться зменшений фреймворк оригінального продукту. Не хвилюйтесь, якщо вперше стикаєтесь із розробкою для iOS; фреймворк - це лише набір файлів. Звичайно, кожен пакет фреймворку включає файли заголовків та статично зв'язані бібліотеки. Фреймворки дозволяють легко поширювати завчасно збудовані бібліотеки розробникам. Atronax 16.02.21 в 08:59 |
||
|
Звісно, можна будувати й власні бібліотеки з нуля. Документація OpenCV детально пояснює цей процес. Для простоти слідуватимемо рекомендованому шляху та застосуємо фреймворк для цього розділу. Завантаживши файли, скопіюємо їх вміст у теку проєкту, як показано на наступному скріншоті: Atronax 16.02.21 в 09:52 |
||
|
Щоб XCode використав який-небудь фреймворк на етапі побудови рішення, виберіть налаштування проєкту та знайдіть закладку з фазами. Тут можна додати чи видалити список тих із них, що стосуються процесу побудови. Натисніть на знак плюса, аби додати новий фреймворк. Результат має бути приблизно таким: Atronax 16.02.21 в 09:57 |
||
|
Обрати можна зі списку стандартних фреймворків. Але щоб додати користувацький фреймворк, маємо натиснути на кнопку "Додати інше". Відкриється діалогове вікно відкриття файлу. Вкажіть на теку проєкту opencv2.framework ось так: Atronax 16.02.21 в 10:00 |
||
|
Підключаємо заголовки OpenCV Atronax 16.02.21 в 10:01 |
||
|
Ми додали фреймворк OpenCV до проєкту, тому найважливішу частину завдання вже виконано. Залишилося останнє - під'єднати заголовки OpenCV до попередньо скомпільованих для цього проєкту. Це чудова річ, яка дозволяє прискорити етап компіляції. Додаючи відповідні файли таким чином, ми автоматично включимо заголовки OpenCV до всього вихідного коду. Знайдіть файл .pch у дереві проєкту та модифікуйте його так: Atronax 16.02.21 в 10:12 |
||
|
Наступний код показує, як модифікувати файл .pch у дереві проєкту: Atronax 16.02.21 в 10:13 |
||
|
// Atronax 16.02.21 в 10:14 |
||
|
Тепер можна викликати будь-яку функцію OpenCV в будь-якому місці вашого проєкту. Atronax 16.02.21 в 10:17 |
||
|
Архітектура застосунку Atronax 16.02.21 в 10:17 |
||
|
Кожна програма iOS має принаймні один екземпляр інтерфейсу UIViewController, що оброблює всі події виду та керує бізнес-логікою застосунку. Клас пропонує фундаментальну модель управління видом для всіх програм iOS. Контролер виду керує набором елементів, що формує частину інтерфейсу користувача застосунку. Відіграючи роль частини відповідного рівня, контролер виду координує зусилля з об'єктами моделі та іншими структурами - включно з рештою контролерів виду - тому застосунок матиме єдиний послідовний графічний інтерфейс. Atronax 16.02.21 в 10:41 |
||
|
Застосунок, який ми запрограмуємо, матиме лише один вид; тому оберемо шаблон "SingleView Application". Використаємо його, щоб зобразити малюнок. Наш клас ViewController включатиме три головні компоненти, необхідні кожному застосунку доповненої реальності (дивіться наступну діаграму): Atronax 16.02.21 в 10:45 |
||
|
Джерело відео відповідальне за передачу нових кадрів від вбудованої камери в код користувача. Це значить, що він повинен мати можливість обирати тип камери (передня чи задня), налаштовувати її параметри (наприклад, роздільна здатність отриманого відео, баланс білого та витримка), та отримувати кадри, не зупиняючи основний потік графічного інтерфейсу. Atronax 16.02.21 в 10:50 |
||
|
Процедуру обробки зображення інкапсульовано в клас MarkerDetector. Клас пропонує крихітний інтерфейс для коду користувача - набір функцій, подібних до processFrame та getResult. Взагалі кажучи, це все, про що має знати ViewController. Не потрібно виставляти напоказ низькорівневі структури даних та алгоритми рівню видів без особливої необхідності. VisualizationController включає всю логіку, пов'язану з візуалізацією доповненої реальності на елементах виду. Atronax 16.02.21 в 10:58 |
||
|
VisualizationController також є фасадом, що абстрагує конкретну реалізацію способу візуалізації. Слабка послідовність коду дає можливість змінювати ці компоненти без необхідності переписувати решту коду. Atronax 16.02.21 в 11:00 |
||
|
Подібний підхід дозволяє вільно використовувати незалежні модулі на інших платформах і компіляторах. Наприклад, можна легко застосувати клас MarkerDetector, щоб запрограмувати настільні рішення для систем Mac, Windows та Linux без жодних змін у коді. Подібним чином, можна перенести VisualizationController на платформу Windows та використати Direct3D для візуалізації. У цьому випадку знадобиться написати лише нову реалізацію VisualizationController, а інші частини коду залишити тими ж. Atronax 16.02.21 в 11:05 |
||
|
Головна процедура обробки починається з отримання нового кадру від джерела відео. Це змушує відеопотік інформувати код користувача про цю подію з використанням функції зворотного виклику. ViewController оброблює її результат та виконує наступні операції: Atronax 16.02.21 в 11:08 |
||
|
Розглянемо процедуру більш детально. Візуалізація AR-сцени включає вивід фонового зображення останнього отриманого кадру; штучні тривимірні об'єкти малюються дещо пізніше. Коли новий кадр відправляється на етап візуалізації, ми копіюємо дані у внутрішні буфери двигуна. Це все ще не візуалізація; ми лише оновлюємо текст новим растровим зображенням. Atronax 16.02.21 в 11:17 |
||
|
Другий крок - це обробка нового кадру та розпізнавання маркера. Ми передаємо зображення як вхідні дані, а в результаті отримуємо список знайдених маркерів. Останні передаємо контролеру візуалізації, що знає, як з ними працювати. Поглянемо на діаграму послідовності виконання цієї процедури: Atronax 16.02.21 в 11:21 |
||
|
Розробку почнемо зі створення компоненти відеозахоплення. Цей клас відповідатиме за передачу кадрів в код користувача та відправлення захоплених кадрів через функцію зворотного виклику. Пізніше напишемо алгоритм розпізнавання маркера. Дана процедура є ядром застосунку. У цій частині програми ми використаємо багато функцій OpenCV для обробки зображень, пошуку контурів, прямокутників маркерів та оцінки їх позицій. Після цього сконцентруємось на візуалізації результатів з використанням доповненої реальності. Поєднавши ці речі, отримаємо перший AR-застосунок. Тому не зупиняємось і йдемо далі! Atronax 16.02.21 в 11:27 |
||
|
Отримуємо доступ до камери Atronax 16.02.21 в 11:27 |
||
|
Застосунок з доповненою реальністю неможливо створити без двох найважливіших речей: захоплення відеопотоку та візуалізації. Перший етап включає передачу кадрів з камери пристрою, виконання важливих перетворень кольору та відправлення результатів на обробку. Оскільки для програм з AR критична швидкість обробки кожного кадра, процес захоплення має бути настільки ефективним, наскільки можливо. Atronax 16.02.21 в 11:32 |
||
|
Кращий спосіб досягнути максимальної продуктивності - отримати прямий доступ до кадрів камери. Така змога з'явилася, починаючи з четвертої версії iOS. Наявні інструменти для програмування з фреймворку AVFoundation дають необхідну функціональність для прямого зчитування з буферів зображень у пам'ять. Atronax 16.02.21 в 11:37 |
||
|
Існує багато прикладів, що використовують клас AVCaptureVideoPreviewLayer та функцію UIGetScreenImage, щоб захоплювати відеопотік камери. Цією технікою користувались в iOS версії 3 та нижче. Atronax 16.02.21 в 11:39 |
||
|
Зараз цей підхід вийшов з ужитку, адже має два суттєвих недоліки: Atronax 16.02.21 в 11:46 |
||
|
Щоб зобразити доповнену реальність, треба надбудувати прозорий вид, що її представлятиме. Згідно з настановами Apple, слід уникати незаповнених прошарків, бо їхнє змішування повільне на мобільних процесорах. Atronax 16.02.21 в 11:50 |
||
|
Класи AVCaptureDevice та AVCaptureVideoDataOutput дозволять налаштувати, захопити та визначити необроблені кадри відео у 32-бітному форматі BGRA. Також можна змінити бажану роздільну здатність результату. Майте на увазі, це впливає на продуктивність, адже чим більші розміри кадру, тим більше часу для обробки та пам'яті вимагається. Atronax 16.02.21 в 11:57 |
||
|
Існує непогана альтернатива високопродуктивному захопленню відеопотоку. Програмний інтерфейс AVFoundation пропонує значно швидший та елегантніший спосіб отримати кадри напряму з камери. Але спершу поглянемо на наступний малюнок, де зображений процес захоплення для iOS: Atronax 16.02.21 в 11:59 |
||
|
AVCaptureSession - це наріжний об'єкт захоплення відеопотоку, який ми маємо створити. Процес потребує два компоненти - вхід та вихід. Пристрій входу може бути фізичним (камера) або відеофайлом (не показано на діаграмі). У нашому випадку це вбудована камера (передня чи задня). Вихідний пристрій можна представити одним з наступних інтерфейсів: Atronax 16.02.21 в 12:02 |
||
|
Інтерфейс AVCaptureMovieFileOutput використовується для запису відео у файл, AVCaptureStillImageOutput - для створення зображень, а AVCaptureVideoPreviewLayer - для програвання відеоматеріалу на екрані. Ми зацікавлені в роботі з інтерфейсом AVCaptureVideoDataOutput, адже він дає прямий доступ до даних відео. Atronax 16.02.21 в 12:03 |
||
|
Примітка Atronax 17.02.21 в 07:31 |
||
|
Щоб інкапсулювати процес захоплення відео, ми створимо інтерфейс VideoSource як показано нижче: Atronax 17.02.21 в 07:35 |
||
|
У цій функції зворотного виклику ми замикаємо буфер зображення, щоб запобігти модифікаціям новими кадрами, отримуємо вказівник на дані зображення та його розміри. Далі створюємо тимчасовий об'єкт BGRAVideoFrame, що передається назовні за допомогою особливого делегата з таким прототипом: Atronax 17.02.21 в 07:45 |
||
|
У межах VideoSourceDelegate інтерфейс VideoSource інформує код користувача про прибуття нового кадра. Atronax 17.02.21 в 07:46 |
||
|
Покроковий процес налаштування відеопотоку виглядає так: Atronax 17.02.21 в 08:01 |
||
|
Пояснимо деякі з кроків більш детально. Після створення сесії захоплення можна визначити бажані налаштування якості задля впевненості, що ми отримаємо оптимальну продуктивність. Оскільки оброблювати відео HD якості не потрібно, роздільної якості 640х480 чи навіть нижче достатньо: Atronax 17.02.21 в 08:03 |
||
|
- (id)init Atronax 17.02.21 в 08:05 |
||
|
Примітка Atronax 17.02.21 в 08:08 |
||
|
Після створення сесії захоплення маємо додати об'єкт входу - екземпляр AVCaptureDeviceInput взаємодіятиме з фізичною камерою. Допоміжна функція cameraWithPosition повертає пристрій із вказаною позицією (передня, задня чи за замовчуванням): Atronax 17.02.21 в 08:14 |
||
|
- (bool) startWithDevicePosition: Atronax 17.02.21 в 08:16 |
