Mastering OpenCV with Practical Computer Vision Projects / Опановуюємо OpenCV через практичні проекти комп'ютерного зору: Розділ 4. Побудова структури з руху на основі OpenCV
| Английский оригинал | Перевод на украинский | |
|---|---|---|
Сожалеем, но текст оригинала доступен только зарегистрированным пользователям. |
У цьому розділі з'ясуємо, що відноситься до структури з руху (Structure for Motion, SfM), інакше кажучи, як отримувати геометричні структури із зображень за рахунок обробки кадрів з різних положень камери з використанням API OpenCV. Обмежимось однією (такий підхід частіше за все називають монокулярним), а також дискретним прорідженим набором кадрів замість послідовного потоку. Ці обмеження суттєво спростять систему, яку будуватимемо надалі, та допожуть зрозуміти основи методу SfM. Щоб реалізувати його, повторимо шлях Хартлі та Зіссермана (відтепер позначатимемо їх як Х. та З.), задокументований ними у розділах 9-12 книги "Multiple View Geometry in Computer Vision" Atronax 22.02.21 в 12:04 |
|
|
Надалі опишемо такі теми: Atronax 22.02.21 в 11:50 |
||
|
У розділі припускаємо наявність заздалегідь налаштованої камери. Калібрування використовується повсюдно в програмах комп'ютерного зору, ця операцію, доступну в бібліотеці OpenCV у вигляді інструменту для командної стрічки, ми обговорювали в попередніх розділах. Тому вважатимемо, що в матриці K зберігаються внутрішні параметри камери, отримані у ході процесу калібрування. Atronax 22.02.21 в 12:11 |
||
|
Щоб спростити пояснення, надалі термін "камера" позначатиме певний вид на сцену, а не оптичні лінзи та пристрої, що створюють знімок. Вона має певне положення в просторі та вектор погляду. Для перетворень між двома камерами можна скористатись компонентами перенесення (рух у просторі) та повороту напряму. Atronax 22.02.21 в 13:27 |
||
|
Об'єднаємо також терміни для координати точки на сцені, світові, дійсні чи 3D як єдині, що існують в дійсності. Те ж відноситься до двовимірних точок на зображенні, які позначають елементи у площині координат зображення, що відповідають 3D-точкам, спроєктованим сенсором камери у певному місці й у певний час. У коді цього розділу ви побачите посилання на книгу "Multiple View Geometry in Computer Vision", наприклад // HZ 9.12. Це відноситься до рівняння 12 з дев'ятого розділу. Текст включатиме лише фрагменти коду, а повністю робоча програма доступна в матеріалах, що супроводжують книгу. Atronax 22.02.21 в 13:38 |
||
|
Концепції структури з руху Atronax 22.02.21 в 13:39 |
||
|
Спершу ми маємо зрозуміти відмінність між стерео (чи будь-яким іншим мультивидом), 3D-реконструкцією з використанням каліброваних наборів та структурою з руху (SfM). Маючи набір з двох або більше камер, ми вже припускаємо наявність руху між ними, у випадку ж SfM ця характеристика невідома, ми лише бажаємо визначити її. Калібровані системи, якщо сказати простіше, дозволяють зробити більш точну реконструкцію тривимірної геометрії, адже не існує похибки оцінки відстані та поворотів між камерами, ці характеристики вже відомі. Перший крок реалізації системи SfM - це визначення руху між камерами. Бібліотека OpenCV надає декілька способів отримати цей рух, наприклад за допомогою функції findFundamentalMat. Atronax 22.02.21 в 13:52 |
||
|
Навіщо, власне, потрібен алгоритм SfM? У першу чергу нам важлива геометрія сцени, яким власне чином об'єкти розміщені відносно камери та якою є їх форма. Припустивши, що вже відомий рух між камерами, що напрямлені на ту ж сцену з двох доволі близьких точок зору, ми матимемо змогу реконструювати геометрію. На жаргоні комп'ютерного зору цей процес називають триангуляцією, існує чимало способів його виконати. Наприклад, можна спробувати знайти перетин двох променів: по одному для кожного центру проєкції камери і точки на відповідній площині зображення. Перетин променів у просторі, в ідеальних умовах, відбудеться в єдиній тривимірній точці дійсності, яка була спроєктованою кожною камерою як показано на наступній діаграмі: Atronax 22.02.21 в 15:49 |
||
|
Насправді, пошук точки перетину променів - надто ненадійний метод; Х. та З. рекомендують не використовувати його. Причиною є те, що промені зазвичай не перетинаються, змушуючи йти на поступки та обирати середню точку на найкоротшому сегменті, що з'єднує два промені. Замість цього, Х. та З. пропонують декілька способів триангулювати точки, деякі з яких опишемо в частині "Реконструкція сцени". Поточна версія OpenCV не має простого API для триангуляції, тому цю частину запрограмуємо власноруч. Atronax 22.02.21 в 15:56 |
||
|
Відновивши тривимірну геометрію з двох точок зору, спробуємо під'єднати більше камер, напрямлених на ту ж сцену, щоб покращити якість реконструкції. На даному етапі більшість алгоритмів SfM намагатимуться оптимізувати набір знайдених позицій камер та тривимірних точок методом регулювання груп, що описаний в частині "Уточнення реконструкції". Бібліотека OpenCV зберігає відповідні функції в новому наборі для зшивання зображень. Разом з тим, краса роботи з С++ полягає в можливості легко інтегрувати та застосувати зовнішні інструменти. Тому спробуємо використати зовнішній регулятор груп, бібліотеку SSBA. Atronax 22.02.21 в 16:11 |
||
|
Поверхнево сформулювавши основи підходу до SfM з використанням OpenCV, перейдемо до реалізації кожного окремого елемента. Atronax 22.02.21 в 16:12 |
||
|
Визначаємо рух камери для двох зображень Atronax 22.02.21 в 16:14 |
||
|
Перед тим, як власне вираховувати рух між камерами, оглянемо вхідні дані та наявні інструменти для виконання цієї операції. По-перше, маємо два зображення сцени з різних (аби лише не занадто) точок у просторі. Це дуже важливий матеріал, і ми його обов'язково використаємо. Що ж до інструментів, зупинимось на математичних об'єктах, які формують обмеження для зображень, камер і сцени. Atronax 23.02.21 в 10:39 |
||
|
Двома дуже важливими об'єктами є фундаментальна матриця F та базова E. Вони практично подібні, якщо не враховувати, що базова припускає використання каліброваних камер; нам потрібен саме цей варіант, тому обираємо його. Бібліотека OpenCV дозволяє знаходити лише фундаментальну матрицю за допомогою функції findFundamentalMat; однак, з неї дуже легко отримати базову, якщо застосувати матрицю калібрування K таким чином: Atronax 23.02.21 в 10:48 |
||
|
Базова матриця розмірності 3х3 встановлює обмеження між двома зображеннями згідно формули x'Ex=0, де x - це точка на першому, а x' - відповідна їй на другому кадрі. Такий підхід дуже корисний, як виявиться дещо пізніше. Крім цього, використаємо ще один важливий факт: нам достатньо лише базової матриці для того, щоб відновити обидві камери із зображень, хоч і залежні від зміни розмірів. Але про це поговоримо пізніше. Отримавши базову матрицю, ми дізнаємось, де розміщені камери та як вони напрямлені. Можна легко вирахувати матрицю на основі певної кількості рівнянь обмежень, адже вирішення кожного з них формує в результаті невелику частину матриці. Насправді, OpenCV дозволяє обчислити її на основі 7 пар точок, але чим їх більше, тим точніший результат. Atronax 23.02.21 в 11:22 |
||
|
Порівнюємо точки на співпадіння з використанням розширених дескрипторів Atronax 23.02.21 в 11:25 |
||
|
Використаємо рівняння обмежень для обрахунку базової матриці. Щоб знайти їх, для кожної точки зображення A маємо знайти відповідну точку на кадрі B. Як отримати такі співпадіння? Просто використавши розширений фреймворк OpenCV для порівняння особливих точок, який набув значного розвитку за декілька останніх років. Atronax 23.02.21 в 11:35 |
||
|
Пошук особливих точок та перевірка дескрипторів на співпадіння - це базова процедура комп'ютерного зору. ЇЇ можна застосувати багатьма способами для реалізації будь-яких операцій, наприклад, розпізнавання позиції та орієнтації об'єкта або пошуку у великій базі даних зображень, подібних до запитуваного. Взагалі кажучи, процес виокремлення означає підбір достатньо якісних особливих точок та обрахунок відповідних дескрипторів. Це вектор значень, що описують середовище навколо обраного елемента. Різні методи формують неоднакові розміри та тип даних для дескрипторів. Перевірка на співпадіння - це процес порівняння особливих точок у двох наборах з використанням цих векторів. OpenCV пропонує дуже легкі та потужні методи для підтримки виокремлення та перевірки на співпадіння. Більше інформації щодо даної теми знаходиться в розділі 3 "Безмаркерна доповнена реальність". Atronax 23.02.21 в 12:11 |
||
|
Розглянемо дуже простий спосіб пошуку та порівняння особливих точок: Atronax 24.02.21 в 08:54 |
||
|
Можливо, ви вже бачили подібний код OpenCV раніше, але переглянемо його ще раз. Маємо отримати три елементи: особливі точки для двох зображень, відповідні їм дескриптори та список співпадінь між наборами. Бібліотека OpenCV пропонує різноманітні детектори ключових точок, видобувачі дескрипторів та алгоритми порівняння. У цьому простому прикладі використаємо функцію SurfFeatureDetector, щоб отримати двовимірне положення SURF-точок, та SurfDescriptorExtractor, щоб знайти дескриптори SURF. Для перевірки використаємо алгоритм повного перебору, який вважається найпростішим способом знайти співпадіння шляхом порівняння кожної особливої точки першого набору з кожною другого (звідси й назва) та знайти накраще співпадіння. Atronax 24.02.21 в 09:09 |
||
|
Далі зображено співпадіння ключових точок на звох зображеннях послідовності Fountain-P11, що зберігається за адресою http://cvlab.epfl.ch/~strecha/multiview/denseMVS.html. Atronax 24.02.21 в 09:11 |
||
|
Фактично, проведена груба перевірка підходить лише за певних умов, а значна кількість співпадінь вірогідно помилкові. З цієї причини більшість методів SfM виконують певного виду відсіювання зайвих особливих точок, щоб забезпечити коректність та знизити рівень похибки. Однією з форм фільтрування, вбудованою в алгоритм повного перебору OpenCV, є перехресне. Згідно нього, співпадіння вважається дійсним, якщо особлива точка першого зображення співпадає з відповідною їй на другому, а зворотня перевірка також вказує на їх співпадіння. Ще одним поширеним механізмом фільтрування, використаним у даному коді, є відсіювання зайвих точок на основі того факту, що два зображення вказують на одну сцену та мають певні відношення стереовиду між ними. На практиці, фільтр намагається грубо обчислити фундаментальну матрицю, про яку можна дізнатися в частині "Пошук матриць камери", та залишити лише ті точки, які відповідають обчисленням з незначною похибкою. Atronax 24.02.21 в 09:24 |
||
|
Перевіряємо точки на співпадіння на основі оптичного руху Atronax 24.02.21 в 09:24 |
||
|
Альтернативою розширеним особливим точкам, як-от SURF, є оптичний потік (OF). Наступна примітка присвячена короткому огляду цього поняття. Нещодавно OpenCV розширила програмний інтерфейс для отримання поля потоку з двох зображень, тепер він значно швидший та потужніший. Спробуємо застосувати його замість порівняння особливих точок. Atronax 24.02.21 в 11:21 |
||
|
Примітка Atronax 24.02.21 в 11:36 |
||
|
Окрім перевірки фрагментів на співпадіння, нові методи оптичного руху застосовують інші додаткові способи, щоб досягнути кращих результатів. До них відносять й використання пірамід зображень, які є все меншими версіями початкового, що дозволяє працювати за методикою "від грубого до тонкого", - поширеною в комп'ютерному зорі. Інший метод потребує визначення глобальних обмежень для поля потоку з урахуванням припущення, що близькі точки "рухаються разом" у тому ж напрямі. Поглиблений огляд оптичного потоку можна знайти в розділі "Developing Fluid Wall Using the Microsoft Kinect", доступного на вебсайті Packt. Atronax 24.02.21 в 12:10 |
||
|
Щоб застосувати оптичний потік OpenCV, достатньо лише викликати функцію calcOpticalFlowPyrLK. Разом з тим, варто було б зберегти результат перевірок на співпадіння методом оптичного потоку таким же чином, як і при використанні розширених особливих точок, задля подальшої можливості змінювати один підхід іншим. Для цього маємо встановити особливий метод перевірки на співпадіння, взаємозамінній з попереднім. Він описаний у такому фрагменті коду: Atronax 24.02.21 в 12:37 |
||
|
Vector<KeyPoint>left_keypoints,right_keypoints; Atronax 24.02.21 в 12:38 |
||
|
// Обчислюємо поле оптичного потоку: Atronax 24.02.21 в 12:41 |
||
|
} else { Atronax 24.02.21 в 12:45 |
||
|
BFMatchermatcher(CV_L2); Atronax 24.02.21 в 12:47 |
||
|
// перевіряємо, наскільки близько розміщена пара точок Atronax 25.02.21 в 08:58 |
||
|
Функції KeyPointsToPoints та PointsToKeyPoints - це просто зручні інструменти для перетворень між структурами даних cv::Point2f та cv::KeyPoint. Atronax 25.02.21 в 09:12 |
||
|
Ще однією особливістю є реалізація тесту відношення для kNN, поширена практика в SfM для зменшення кількості похибок. В дійсності, це фільтр, який видаляє дивні співпадіння, тобто такі, при яких одній особливій точці на лівому зображенні відповідає дві на правому. Якщо вони розміщені надто близько або відношення між ними досить значне (приблизно 1.0), вважатимемо їх дивними та не використовуватимемо. Також приєднаємо фільтр запобігання дублюванням, щоб надалі скоротити ці співпадіння. Atronax 25.02.21 в 09:17 |
||
|
Наступний малюнок присвячений полю потоку з одного зображення до іншого. Рожеві стрілки на лівому кадрі вказують на рух фрагментів. На другому зображенні зліва можна бачити приближення до невеликої зони поля потоку. Знову ж таки, рожеві стрілки вказують на рух особливих точок. Поглянувши на пару початкових сегментів на правому зображенні, бачимо, що це має певний сенс. Особливі точки рухаються в лівий бік у напрямі рожевих стрілок, як показано на малюнку: Atronax 25.02.21 в 09:35 |
||
|
Перевага оптичного руху над розширеними особливими точками полягає в тому, що в більшості випадків процес відбувається швидше та здатний обробити більшу кількість точок, що у свою чергу покращує якість реконструкції. Багатьом методам оптичного руху притаманна також монолітна модель загального руху фрагментів, при якому порівняння розширених точок не береться до уваги. Є також підводний камінь: краще за все цей процес підходить для послідовних кадрів з однієї камери, розширені особливі точки не потребують цього обмеження. Відмінність полягає в тому, що методи оптичного руху зазвичай користуються простими особливими точками, наприклад фрагментами зображення, у той час як розширені (наприклад, SURF) приймають до уваги інформацію більш вищого рівня. Вибір оптичного руху чи розширених особливих точок розробник застосунку має робити залежно від характеристик вхідних даних. Atronax 25.02.21 в 09:58 |
||
|
Шукаємо матриці камери Atronax 25.02.21 в 09:58 |
||
|
Маючи співпадіння між ключовими точками, можемо вирахувати фундаментальну та відповідну їй базову матриці. Але в першу чергу мусимо вирівняти масиви співпадінь таким чином, щоб індекс у першому відповідав тому ж індексу в другому. Цього вимагає функція findFundamentalMat. Також треба конвертувати структуру KeyPoint в Point2f. Особливу увагу приділимо внутрішнім змінним класу DMatch, queryIdx та trainIdx, що зберігають дані про співпадіння між двома ключовими точками, оскільки вони мають бути обрані тим же шляхом, яким використана функція matcher.match(). Наступний фрагмент коду показує, як вирівняти співпадіння у двох відповідних наборах двовимірних точок та як використати їх для пошуку фундаментальної матриці: Atronax 25.02.21 в 10:17 |
||
|
vector<Point2f>imgpts1,imgpts2; Atronax 25.02.21 в 10:18 |
||
|
Пізніше можна застосувати бінарний вектор статусіу для скорочення точок, які відповідають відновленій фундаментальній матриці. Наступний малюнок є ілюстрацією результату цього процесу. Червоні стрілки позначають співпадіння особливих точок, видалених у процесі пошуку матриці F, а зелені - ті з них, що залишилися. Atronax 25.02.21 в 10:25 |
||
|
Тепер ми готові знайти матриці камери. Процес вичерпно описаний в розділі 9 книги Х. та З.; але ми застосуємо пряму та спрощену реалізацію, а бібліотека OpenCV допоможе нам в цьому. Але спершу розглянемо спосіб побудови матриці камери. Atronax 25.02.21 в 10:27 |
||
|
Модель камери складається з двох елементів, компоненти повороту R та перенесення t. Цікавим фактом є те, що вона задовольняє базовому рівнянню x=PX, де x - це двовимірна точка на зображенні, а X - тривимірна у просторі. Звісно, є й інші корисні особливості, але матриця фактично встановлює важливі відношення між точками кадру й сцени. Отримавши мотивацію вирахувати її, поглянемо, як саме це зробити. Наступний фрагмент коду показує, як декомпонувати базову матрицю на елементи повороту та перенесення: Atronax 25.02.21 в 10:36 |
||
|
SVD svd(E); Atronax 25.02.21 в 10:37 |
||
|
Це дуже просто. Достатньо застосувати декомпозицію єдиного значення отриманої базової матриці та помножити її на іншу, W. Не надто поглиблюючись в математичні пояснення, скажімо так: ця операція декомпонувала матрицю E на дві частини, поворот та перенесення. Власне кажучи, базову матрицю й було сформовано їх добутком. Щоб задовольнити цікавість, можна поглянути на таке рівняння, що трапляється в літературі: E=[t]xR. Вочевидь, вона складається з певного виду компоненти перенесення t та повороту R. Atronax 25.02.21 в 10:46 |
||
|
В результаті отримуємо лише одну матрицю камери. Але ж де інша? Фактично, ми здійснюємо ці операції із тим припущенням, що одна з них є фіксованою та канонічною (не має поворотів чи перенесення). Канонічною є також така матриця камери: Atronax 25.02.21 в 10:54 |
||
|
Однак, це не повне рішення. Х. та З. у своїй книзі показують чому і навіщо декомпозиція має 4 можливі матриці, але лише одна з них є справжньою. Коректною матрицею є та, що продукує реконструйовані точки з додатковим значенням Z (знаходяться перед камерою). Але ми побачимо це лише після знайомства з триангуляцією та 3D реконструкцією, що описані в наступній частині. Atronax 25.02.21 в 10:59 |
||
|
До методу варто також додати перевірку помилок. У багатьох випадках обчислення фундаментальної матриці з урахуванням співпадінь формують похибки, а це, у свою чергу, негативно впливає на матриці. Продовжувати триангуляцію з використанням недійсних не має жодного сенсу. Можна, наприклад, перевірити, чи є компонента повороту дійсною матрицею. Враховуючи, що значення детермінанту повинно бути рівним 1 (або -1), діємо так: Atronax 25.02.21 в 11:07 |
||
|
bool CheckCoherentRotation(cv::Mat_<double>& R) { Atronax 25.02.21 в 11:09 |
||
|
//Знаходимо матриці камери Atronax 25.02.21 в 11:12 |
||
|
На даному етапі маємо дві камери, необхідні для реконструкції сцени. Канонічна перша, що зберігається в змінній P, та обрахована друга формують фундаментальну матрицю P1. Далі пояснимо, як скористатися цими камерами для отримання 3D структури сцени. Atronax 25.02.21 в 11:16 |
