Mastering OpenCV with Practical Computer Vision Projects / Опановуюємо OpenCV через практичні проекти комп'ютерного зору: Розділ 7. Оцінка 3D пози голови за допомогою AAM та POSIT

← →
Английский оригинал Перевод на украинский

Сожалеем, но текст оригинала доступен только зарегистрированным пользователям.

Якісний алгоритм комп'ютерного зору не може обійтися без корисних та надійних можливостей, узагальненості та твердої математичної основи. Всі ці особливості описані в праці Тіма Кута під назвою "Моделі активного вигляду" (Active Appearance Models, AAM). Цей розділ навчить вас створювати власну модель за допомогою бібліотеки OpenCV, а також використовувати її для пошуку найближчого положення на заданому кадрі. Крім цього, ви зрозумієте, як застосувати алгоритм POSIT та як розмістити тривимірну модель на зображенні зі встановленою позою. За допомогою цих інструментів ви зможете відслідкувати 3D модель на відео в реальному часу; хіба це не чудово? Хоча приклади фокусуються на позі голови, практично будь-яка модель з деформаціями може скористатися подібним підходом.

Atronax 22.03.21 в 13:21

0

Читаючи подальший матеріал, ви познайомитесь з такими темами:
Огляд моделей активного вигляду
Огляд моделей активних форм
Інстанціювання моделі - граємо з моделями активного вигляду
Пошук AAM і розміщення на зображенні
Алгоритм POSIT

Atronax 22.03.21 в 13:21

0

Наступний список пояснює терміни, які ми використаємо у розділі:
Моделі активного вигляду (AAM) - це модель об'єкта, яка містить статистичні дані про його форму та текстуру. Це потужний спосіб отримати відомості про варіативність форм та текстур об'єкта.
Модель активної форми (ASM) - це статистична модель форми об'єкта, дуже корисна для вивчення варіантів форм.

Atronax 22.03.21 в 13:21

0

Аналіз головних компонент (Principal Component Analysis, PCA) - ортогональне лінійне перетворення, що трансформує дані в нову координатну систему, для якої найбільша дисперсія будь-якої проєкції даних лежить на першій координаті (що зветься першим головним компонентом), друга найбільша дисперсія - на другій координаті, і так далі. Цю процедуру часто називають зменшенням розмірності. Знижуючи це значення, ми зможемо створити більш швидкий алгоритм.

Atronax 22.03.21 в 13:21

0

Триангуляція Делоне - це така триангуляція набору точок P на площині, для якої жодна точка P не лежить всередині кола, описаного навколо будь-якого трикутника триангуляції. Алгоритм не опрацьовує малі трикутники. Триангуляція необхідна для накладання текстури.
Афінні перетворення - будь-яке перетворення, що може бути виражене у формі добутку матриць та додавання вектора. Застосовується для накладання текстури.
Поза з орфографічної проєкції та ітеративне масштабування (Pose from Orthography and Scaling with Iterations, POSIT): алгоритм комп'ютерного зору, що здійснює обчислення 3D пози.

Atronax 22.03.21 в 13:21

0

Огляд моделей активного вигляду

Atronax 22.03.21 в 13:21

0

Коротко кажучи, моделі активного вигляду - це якісна модель, параметризована комбінацією текстури та форми, що пов'язана з ефективним алгоритмом пошуку, який може знайти точне положення та позу моделі на зображенні кадру. Для цього ми почнемо з огляду і побачимо, що вони тісно пов'язані з позиціями орієнтирів. Аналіз головних компонентів та досвід практики детальніше опишемо у наступних частинах. Тоді ж скористаємось допомогою функцій Делоне та дізнаємось дещо про триангуляцію. Далі, здобувши дані з текстури об'єкта, застосуємо пофрагментні афінні викривлення у частині про перетворення текстурних трикутників.

Atronax 22.03.21 в 13:22

0

Здобувши достатню кількість даних для побудови якісної моделі, можна погратися з техніками в частині інстанціювання моделі. Потім ми зможемо знайти рішення зворотньої проблеми за рахунок пошуку AAM та розміщення 3D моделі.

Atronax 22.03.21 в 13:22

0

Це вже досить корисні алгоритми для 2D або навіть 3D співпадінь зображень. Але коли вдасться змусити їх працювати, чому б не удосконалити їх за рахунок POSIT, ще одного потужного алгоритму для розміщення моделі? Занурившись в матеріали частини POSIT, дізнаємось про особливості роботи з ним в OpenCV, а потім розглянемо, як приєднати до неї модель голови. Таким чином ми зможемо розмістити 3D модель на знайденому 2D кадрі. А якщо зацікавлений читач хоче дізнатися, куди це приведе нас, об'єднавши AAM та POSIT для послідовних кадрів, ми зможемо отримати 3D відслідковування моделей з деформаціями в режимі реального часу! Деталі пояснимо у частині про процедуру обробки даних з камери чи файлу.

Atronax 22.03.21 в 13:22

0

Кажуть, що одне зображення варте тисячі слів; уявіть, що ми маємо N кадрів. Пояснений раніше процес можна побачити на наступній ілюстрації:

Atronax 22.03.21 в 13:22

0

Огляд алгоритмів розділу. Маючи зображення (у верхній лівій частині попереднього малюнка), можемо застосувати алгоритм пошуку активного вигляду для розпізнавання двовимірної пози людської голови. Ілюстрація у верхній правій частині скріншоту зображає заздалегідь натреновану модель активного вигляду, що використовується алгоритмом пошуку. Коли буде знайдено 2D позу, POSIT можна пристосувати для розширення результатів на 3D. Якщо процедуру виконати для послідовності відеокадрів, в результаті отримаємо 3D розпізнавання.

Atronax 22.03.21 в 13:22

0

Моделі активних форм

Atronax 22.03.21 в 13:22

0

Як зазначено раніше, AAM потребує модель активної форми (Active Shape Model, ASM). У наступних частинах ми створимо ASM, що є статистичною моделлю варіативності форм. Модель генерується на основі комбінації різних форм. Для цього потрібен тренувальний набір анотованих зображень, описаний у статті "Active Shape Models - Their Training and Application" Тімоті Кута. Щоб побудувати модель форми обличчя, декілька зображень з точками, визначеними на ключових позиціях, мають вказувати на головні характеристики. Наступний скріншот показує такий приклад:

Atronax 22.03.21 в 13:22

0

Існує 76 орієнтирів обличчя, завантажених з набору даних MUCT. Вони, звичайно, відмічені вручну та описують декілька характеристик, наприклад контур рота, ніс, очі, брови та форму обличчя, оскільки їх легше відслідкувати.

Atronax 22.03.21 в 13:22

0

Примітка

Atronax 22.03.21 в 13:22

0

Аналіз Прокруста - це вид статистичного аналізу форми, що використовується для вивчення розподілу набору форм. У результаті отримаємо оптимальні значення перенесення, повороту та масштабування об'єктів.

Atronax 22.03.21 в 13:23

0

Маючи попередньо вказаний набір зображень, можемо згенерувати статистичну модель варіативності форм. Оскільки позначені точки на об'єкті описують форму, спершу маємо вирівняти всі набори точок в певні рамки координат за допомогою аналізу Прокруста та представити кожну з форм у вигляді вектора x. Далі застосуємо аналіз головних компонентів (Principal Component Analysis, PCA) до даних. Потім апроксимуємо будь-який приклад такою формулою:
x = x + Ps*bs

Atronax 22.03.21 в 13:23

0

У попередній формулі, x - це середня форма, Ps - набір ортогональних режимів варіативності, а bs - набір параметрів форми. Щоб зрозуміти це краще, створимо простий застосунок у подальшому матеріалі частини, що дозволить працювати з PCA та моделями форми.

Atronax 22.03.21 в 13:23

0

Навіщо взагалі використовувати PCA? Він дуже важливий, коли потрібно зменшити кількість параметрів моделі. Пізніше у розділі ми також побачимо користь цього процесу для пошуку на заданому зображенні. Детальніше з темою можна ознайомитися на ресурсі http://en.wikipedia.org/wiki/Principal_component_analysis :

Atronax 22.03.21 в 13:23

0

PCA дозволяє представити користувачу зображення меншої розмірності, своєрідну "тінь" об'єкта, якщо подивитися на нього з найбільш інформативної точки зору. Це робиться лише за рахунок перших декількох головних компоненів для того, щоб зменшити розмірність трансформованих даних.

Atronax 22.03.21 в 13:23

0

Все стає зрозумілим, якщо розглянути таке зображення:
Джерело: http://en.wikipedia.org/wiki/File:GaussianScatterPCA.png

Atronax 22.03.21 в 13:23

0

Попередній скріншот зображає PCA багатовимірного розподілу Гауса з центром у позиції (2,3). Показалі вектори - це власні вектори матриці коваріації, зміщені таким чином, що їхні хвости мають середнє значення. Тобто, якщо ми бажаємо представити модель єдиним параметром, варто взяти напрямок з власного вектора, що вказує на верхню праву частину зображення. Крім цього, дещо змінюючи параметр, можемо екстраполювати дані та отримати значення, подібні до розшукуваних.

Atronax 22.03.21 в 13:23

0

Перші кроки з PCA

Atronax 22.03.21 в 13:23

0

Щоб відчути, як PCA здатне допомогти нам з моделлю обличчя, почнемо з активної моделі форми та протестуємо декілька параметрів.
Оскільки розпізнавання обличчя та відслідковування має історію вивчення, декілька баз даних облич доступні у відкритій форми для дослідження. Ми використаємо примірники з бази даних IMM. По-перше, спробуємо зрозуміти, як діє клас PCA в бібліотеці OpenCV. З документації можна зробити висновок, що клас PCA використовується для обчислення особливого базису для набору векторів, що складається з власних відповідників матриці коваріації, обрахованої для вхідного набору векторів. Цей клас також переносить вектори між старою та новою координатними системами за допомогою методів project та backproject. Цю нову координатну систему можна точно апроксимувати за рахунок лише декількох перших її компонентів. Це значить, що ми можемо представити початковий вектор високорозмірного простору значно коротшим вектором, що складається із спроєктованих координат на підпростір.

Atronax 22.03.21 в 13:24

0

Оскільки нам потрібна параметризація в термінах декількох скалярних значень, частіше використовуватимемо метод backproject. Він дає на основі координат головних компонентів проєктованих векторів та реконструює початкові. Ми можемо отримати початкові, якщо здобудемо усі компоненти, але різниця буде надто малою, якщо врахуємо лише декілька компонентів; це одна із причин використання PCA. Оскільки потрібна певна варіативність оригінальних векторів, наші параметризовані скаляри зможуть екстраполювати початкові дані.

Atronax 22.03.21 в 13:24

0

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

Atronax 22.03.21 в 13:24

0

У нашому підході анотуватимемо зображення обличчя орієнтирами, необхідними для моделі розподілення точок (Point Distribution Model, PDM). Якщо ми маємо k вирівнених орієнтирів у двох розмірностях, описа форми набуває такого вигляду:
X = { x1, y1, x2, y2, …, xk, yk}

Atronax 22.03.21 в 13:24

0

Варто зауважити, що для цього потрібні стабільні анотування на всіх примірниках. Наприклад, якщо ліва частина рота відмічена орієнтиром 3 на першому кадрі, це ж значення має бути використано для решти зображень.

Atronax 22.03.21 в 13:24

0

Такі послідовності орієнтирів формують контури форми, яку можна визначити у вигляді вектора. Припустимо, що їх значення мають розподіл Гауса у цьому просторі, і ми можемо застосувати PCA для обчислення нормованих власних векторів та власних значень матриці коваріації для всіх тренувальних форм. Використавши верхні центральні власні вектори, створимо матрицю розмірності 2k * m, яку назвемо P. Таким чином кожен вектор описує головний режим змін вздовж набору.

Atronax 22.03.21 в 13:24

0

Тепер можна визначити нову форму таким рівнянням:
X' = X' + Pb
Тут X' позначає середню форму серед усіх тренувальних зображень, ми лише усереднюємо кожен з орієнтирів, а b - це вектор масштабованих значень для кожного головного компонента. Це дає змогу створювати нові форми за рахунок модифікації значення b. На практиці b обирають в межах трьох стандарних дисперсій для того, щоб згенерована форма мала змогу потрапити в тренувальний набір.

Atronax 22.03.21 в 13:24

0

Наступний скріншот зображає анотовані орієнтири рота для трьох різних кадрів:
Як можна бачити на попередньому малюнку, форми описані послідовністю орієнтирів. Для анотування тренувальних зображень можна скористатися GIMP чи ImageJ або створити просту програму на OpenCV. Припустимо, що користувач здійснив цей процес і зберіг точки як послідовності (x, y) позицій орієнтирів для всіх тренувальних зображень у текстовому файлі, який потім використаємо для аналізу PCA. Потім до першої стрічки файлу додамо два параметри, які позначатимуть кількість тренувальних кадрів та колонок для зчитування. Для k двовимірних точок це значення дорівнюватиме 2*k.

Atronax 22.03.21 в 13:25

0

Наступні дані позначають екземпляр цього файлу, отриманий шляхом анотування трох зображень з бази даних IMM, значення k обрано рівним 5:
3 10
265 311 303 321 337 310 302 298 265 311
255 315 305 337 346 316 305 309 255 315
262 316 303 342 332 315 298 299 262 316

Atronax 22.03.21 в 13:25

0

Маючи анотовані зображення, перетворимо ці дані в модель форми. Спочатку завантажимо їх у матрицю. Це можна зробити за рахунок функції loadPCA. Далі покажемо фрагмент коду, який її використовує:

Atronax 22.03.21 в 13:25

0

PCA loadPCA(char* fileName, int& rows, int& cols,Mat& pcaset){
FILE* in = fopen(fileName,"r");
int a;
fscanf(in,"%d%d",&rows,&cols);
pcaset = Mat::eye(rows,cols,CV_64F);
int i,j;
for(i=0;i<rows;i++){
for(j=0;j<cols;j++){
fscanf(in,"%d",&a);
pcaset.at<double>(i,j) = a;
}
}
PCA pca(pcaset, // передаємо дані
Mat(), // ми не маємо заздалегідь обчисленого середнього вектора
// тому дозволимо PCA вирахувати його
CV_PCA_DATA_AS_ROW, // вказує на те, що вектори
// зберігаються у вигляді рядів матриці
// використовуємо CV_PCA_DATA_AS_COL, якщо вектори є
// колонками матриці)
pcaset.cols// визначаємо, скільки головних компонентів зберегти
);
return pca;
}

Atronax 22.03.21 в 13:27

0

Зауважте, ми створюємо матрицю у стрічці pcaset = Mat::eye(rows,cols,CV_64F), виділивши достатньо місця для 2*k значень. Після двох циклів for, що формують матрицю, викличемо конструктор PCA з даними, які за необхідності можуть бути заздалегідь обчисленими середніми векторами. Ми також вказуємо, що вектори збережені у вигляді рядів матриці, і що ми бажаємо зберегти ту ж їх кількість, скільки маємо компонентів, хоч і використаємо лише декілька.

Atronax 22.03.21 в 13:27

0

Заповнивши об'єкт PCA тренувальними даними, матимемо все, що потрібно для зворотньої проєкції форми згідно із заданими параметрами. Це можна зробити за рахунок виклику функції PCA.backproject, передавши у першому з них вектор ряду та отримавши спроєктований результат у другому.

Atronax 22.03.21 в 13:27

0

Два попередні скріншоти показують різні конфігурації форми залежно від обраних значень параметрів. Жовті та зелені відповідають даним, а червоні - формі зі вказаними характеристиками.

Atronax 22.03.21 в 13:27

0

Прикладом програми можна скористатися для експериментів з моделями активних форм, адже він дозволяє користувачу змінювати різні параметри моделі. Справедливо зазначити, що регулювання лише перших двох скалярів (які відповідають першому та другому режимам дисперсії) дозволяє отримати форму, дуже близьку до натренованих. Така варіативність допоможе нам у процесі побудови моделі AAM, оскільки дає змогу отримати інтерпольовані форми. Далі ми обговоримо триангуляцію, текстурування, AAM та пошук AAM.

Atronax 22.03.21 в 13:27

0

Триангуляція

Atronax 22.03.21 в 13:27

0

Оскільки спостережена форма може бути викривлена (наприклад, відкритий рот), потрібно повторно відобразити нормовану текстуру на середню форму та застосувати PCA до неї. Для цього необхідна триангуляція. Концепція дуже проста: ми створимо трикутники, що міститимуть анотовані точки, а потім відобразимо один трикутник на інший. Бібліотека OpenCV постачається зі зручною функцією cvCreateSubdivDelaunay2D, яка формує пусту триангуляцію Делоне. Це доволі ефективний алгоритм, що не враховуватиме малі трикутники.

Atronax 22.03.21 в 13:28

0

Примітка

Atronax 22.03.21 в 13:28

0

В математиці та обчислювальній геометрії триангуляція Делоне для набору P точок на площині - це така триангуляція DT(P), для якої жодна точка P не лежить всередині кола, описаного навколо кожного трикутника DT(P). Триангуляції Делоне максимізують мінімальне значення серед усіх кутів; вони не діють на малі трикутники. Алгоритм названо за ім'ям Бориса Делоне у праці 1934 року.

Atronax 22.03.21 в 13:28

0

Після налаштування сітки Делоне можна скористатися функцією cvSubdivDelaunay2DInsert для вміщення точок. Подальший фрагмент коду вкаже, яким саме чином можна застосувати триангуляцію:

Atronax 22.03.21 в 13:28

0

CvMemStorage* storage;
CvSubdiv2D* subdiv;
CvRect rect = { 0, 0, 640, 480 };
storage = cvCreateMemStorage(0);
subdiv = cvCreateSubdivDelaunay2D(rect,storage);
std::vector<CvPoint> points;
// налаштовуємо точки певним чином
...
// ітеруємо по точкам та додаємо їх у сітку Делоне
for(int i=0;i<points.size();i++){
float x = points.at(i).x;
float y = points.at(i).y;
CvPoint2D32f floatingPoint = cvPoint2D32f(x, y);
cvSubdivDelaunay2DInsert( subdiv, floatingPoint );
}

Atronax 22.03.21 в 13:28

0

Враховуйте, що наші точки лежатимуть всередині прямокутної зони, що передається у вигляді параметра функції cvCreateSubdivDelaunay2D. Щоб сформувати сітку, маємо створити та налаштувати структуру для зберігання даних у пам'яті. Це показано в перших п'ятьох стрічках попереднього фрагмента коду. Потім, щоб створити триангуляцію, додамо точки за допомогою функції cvSubdivDelaunay2DInsert. Це відбувається у циклі for. Точки вже повинні бути налаштовані, оскільки саме вони відіграють роль вхідних даних. Наступний малюнок ілюструє, якою може бути триангуляція:

Atronax 22.03.21 в 13:28

0

Цей знімок є результатом виводу попереднього коду для набору точок, що формують триангуляцію за допомогою алгоритму Делоне. Хоча створювати сітку методами OpenCV дуже зручно, ітерувати по трикутникам не так легко. Далі покажемо код, який ітерує по ребрам сітки:

Atronax 22.03.21 в 13:29

0

void iterate(CvSubdiv2D* subdiv, CvNextEdgeType triangleDirection){
CvSeqReader reader;
CvPoint buf[3];
int i, j, total = subdiv->edges->total;
int elem_size = subdiv->edges->elem_size;
cvStartReadSeq((CvSeq*)(subdiv->edges), &reader, 0);
for(i = 0; i < total; i++){
CvQuadEdge2D* edge = (CvQuadEdge2D*)(reader.ptr);
if(CV_IS_SET_ELEM(edge)){
CvSubdiv2DEdge t = (CvSubdiv2DEdge)edge;
for(j=0;j<3;j++){
CvSubdiv2DPoint* pt = cvSubdiv2DEdgeOrg(t);
if(!pt) break;
buf[j] = cvPoint(cvRound(pt->pt.x), cvRound(pt->pt.y));
t = cvSubdiv2DGetEdge(t, triangleDirection);
}
}
CV_NEXT_SEQ_ELEM(elem_size, reader);
}
}

Atronax 22.03.21 в 13:29

0

Маючи сітку, викличемо функцію cvStartReadSeq для налаштування об'єкта для зчитування ребер. Згідно з документацією OpenCV ми маємо таке визначення:
Фукнція налащтовує стан зчитувача. Після цього всі елементи від першого до останнього можна зчитати за допомогою послідовних викликів макроса CV_READ_SEQ_ELEM(read_elem, reader) у випадку прямого зчитування чи CV_REV_READ_SEQ_ELEM(read_elem, reader) - зворотнього. Обидва макроси розміщують фрагмент послідовності у змінній read_elem та переміщують вказівник зчитування на наступний елемент.

Atronax 22.03.21 в 13:29

0

До альтернативних способів отримати наступний елемент відносять використання макросу CV_NEXT_SEQ_ELEM(elem_size, reader), це кращий вибір, якщо елементи послідовності мають великі розміри. У даному випадку використаємо CvQuadEdge2D* edge = (CvQuadEdge2D*) reader.ptr, щоб перетворити вказівник зчитування у вказівник на об'єкт типу CvQuadEdge2D. Макрос CV_IS_SET_ELEM перевіряє лише, встановлені окремі ребра чи ні. Маючи ребро, відшукаємо вихідну точку шляхом виклику функції cvSubdiv2DEdgeOrg. Щоб обробити регіони навколо трикутника, повторно викличемо cvSubdiv2DGetEdge та передамо напрям, наприклад CV_NEXT_AROUND_LEFT чи CV_NEXT_AROUND_RIGHT.

Atronax 22.03.21 в 13:29

0

Викривлення текстури трикутника

Atronax 22.03.21 в 13:29

0
Минутку...

Следующая страница →