Mastering OpenCV with Practical Computer Vision Projects / Опановуюємо OpenCV через практичні проекти комп'ютерного зору: Розділ 8. Розпізнавання обличчя за методами Eigenfaces та Fisherfaces

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

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

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

Atronax 22.03.21 в 14:19

0

У розділі покриємо такі теми:
Пошук обличчя
Попередня обробка обличчя
Тренування алгоритму машинного навчання на основі зібраних облич
Розпізнавання обличчя
Постобробка

Atronax 22.03.21 в 14:19

0

Вступ до пошуку та розпізнавання обличчя
Розпізнавання - це процес встановлення відмітки для відомого обличчя. Аналогічно до того, як люди навчаються розпізнавати власну сім'ю, друзів та знаменитостей за їх обличчями, комп'ютер також може скористатися багатьма техніками навчання для цього. В загальному вони включають чотири основні кроки:

Atronax 22.03.21 в 14:20

0

1. Пошук обличчя - це процес знаходження фрагмента обличчя на зображення (великий прямокутник поряд з центром наступного скріншота). На цьому кроці неважлива особа, а лише її обличчя.
2. Попередня обробка обличчя - це процес налаштування зображення обличчя, щоб воно виглядало більш чітким та схожим на інші (невеликий кадр у відтінках сірого зверху посередині малюнка).
3. Збір та вивчення даних - процес збереження багатьох попередньо оброблених облич (для кожної людини, яку маємо розпізнати) та подальші тренування алгоритму.
4. Розпізнавання обличчя - процес, що перевіряє, які із зібраних даних найбільше схожі на зображення, отримане з камери (малий прямокутник у правій верхній стороні ілюстрації).

Atronax 22.03.21 в 14:20

0

Примітка
Словосполучення "розпізнавання обличчя" часто вживається у значенні пошуку його положення, але ця книга використовуватиме формальне визначення з четвертого етапу, а пошук посилатиметься на перший.

Atronax 22.03.21 в 14:21

0

Далі проілюстровано готовий проєкт WebcamFaceRec, включно з невеликим прямокутником у верхньому правому куті, що виділяє розпізнану особу. Зверніть увагу на індикатор впевненості, що знаходиться поряд з попередньо обробленим обличчям (невеликий фрагмент посередині зверху), у даному випадку вірогідність коректного розпізнавання становить близько 70 відсотків.

Atronax 22.03.21 в 14:21

0

Сучасні техніки пошуку обличчя достатньо надійні в умовах реального світу, а от розпізнавання похизуватися цим не може. Наприклад, легко знайти дослідження зі вказаною точністю розпізнавання обличчя більше 95 відсотків, але якщо протестувати ці алгоритми самостійно, їхня точність становитиме менше 50 відсотків.

Atronax 22.03.21 в 14:21

0

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

Atronax 22.03.21 в 14:21

0

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

Atronax 22.03.21 в 14:21

0

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

Atronax 22.03.21 в 14:23

0

Етап 1. Пошук обличчя
До 2000-го року існувало багато технік для пошуку обличчя, але всі вони були або надто повільними, або дуже ненадійними. Важливі зміни відбулися у 2001 році, коли Віола та Джонс розробили заснований на алгоритмі Хаара каскадний класифікатор для пошуку об'єктів, та у 2002 році, коли його покращили Ліенхарт та Мейдіт. В результаті детектор виявився швидким (може розпізнавати обличчя в режимі реального часу на типовому ПК з вебкамерою) та надійним (коректно знаходить близько 95 відсотків облич у фронтальному ракурсі). Цей детектор спричинив революцію у сфері розпізнавання (робототехніці та комп'ютерному зорі) і врешті-решт дозволив створювати застосунки, що діють у режимі реального часу, особливо коли Ліенхарт заявив, що його детектор постачається вільно з бібліотекою OpenCV! Він здатний виявити не лише фронтальні фрагменти облич, а й профільні, очі, рот, ніс, логотипи компаній та багато інших об'єктів.

Atronax 22.03.21 в 14:23

0

Детектор об'єктів розширено у версії 2.0 бібліотеки заради можливості використовувати характеристики LBP для пошуку, на основі роботи *Агонена, Хадіда та Пайтікейнена* у 2006 році, адже засновані на LBP детектори потенційно в декілька разів швидші за попередні алгоритми, а також не мають проблем з ліцензіями, притаманних багатьом детекторам Хаара. Базовою ідеєю детектора обличчя Хаара полягає в тому, що якщо ви поглянете на більшість фронтальних знімків облич, фрагмент з очима виглядатиме темнішим за лоб і щоки, а частина з ротом має бути темнішою за щоки, і так далі. Алгоритм типово здійснює понад 20 етапів подібних порівнянь для того, щоб класифікувати зображення як обличчя чи не-обличчя, але цей процес має бути здійснено у будь-якій можливій позиції та для будь-якого можливого розміру, тобто фактично необхідні тисячі перевірок. Основна ідея детектора LBP схожа на вище вказану, але для досягнення мети використовує гістограми порівняння інтенсивності пікселів, наприклад меж, кутів та плоских фрагментів.

Atronax 22.03.21 в 14:24

0

Замість того, щоб найчіткіші порівняння для опису обличчя визначала людина, детектори Хаара та LBP можна натренувати автоматично знаходити потрібні дані з великого набору зображень та зберігати результати для пізнішого використання у вигляді файлів XML. Зазвичай, каскадні класифікатори тренують на основі щонайменше 1000 унікальних зображень обличчя та 10000 знімків інших об'єктів (наприклад, фотографій дерев, автомобілів та тексту), а тренування може зайняти довгий час навіть на багатоядерному процесорі (від декількох годин для LBP до тижня для Хаара!). На щастя, бібліотека OpenCV постачається з попередньо натренованити детекторами! Фактично, ви зможете шукати фронтальні та профільні фрагменти з обличчями, очі чи носи, лише завантаживши різні каскадні класифікатори з файлів XML в детектор об'єктів, а також обирати між детекторами Хаара чи LBP.

Atronax 22.03.21 в 14:24

0

Реалізуємо розпізнавання обличчя з використанням OpenCV

Atronax 22.03.21 в 14:24

0

Як вказано раніше, бібліотека OpenCV 2.4 постачається з різними попередньо натренованими детекторами XML, якими можна скористатися для різних цілей. У таблиці перелічено деякі з найпопулярніших файлів:
Тип каскадного класифікатора Файл XML
Детектор обличчя (за замовчуванням) haarcascade_frontalface_default.xml
Детектор обличчя (швидкий алг. Хаара) haarcascade_frontalface_alt2.xml
Детектор обличчя (швидкий алг. LBP) lbpcascade_frontalface.xml
Детектор профільних зображень обличчя haarcascade_profileface.xml
Детектор ока (окремо лівого й правого) haarcascade_lefteye_2splits.xml
Детектор рота haarcascade_mcs_mouth.xml
Детектор носа haarcascade_mcs_nose.xml
Детектор людини haarcascade_fullbody.xml

Atronax 22.03.21 в 14:24

0

Засновані на алгоритмі Хаара детектори зберігаються у теці data\haarcascades, а LBP-детектори - за відносним шляхом data\lbpcascades у кореневій теці бібліотеки OpenCV, наприклад C:\opencv\data\lbpcascades\.

Atronax 22.03.21 в 14:25

0

У нашому проєкті розпізнавання обличчя ми бажаємо знайти фронтальні фрагменти, тому застосуємо детектор LBP, адже він найшвидший та не потребує ліцензії. Враховуйте, заздалегідь натреноватий детектор LBP, що постачається з бібліотекою OpenCV v2.x не настільки добре відрегульований, як попередньо натреновані детектори облич Хаара, тому якщо вам потрібні більш надійні алгоритми, варто створити власний, на основі LBP, чи просто використати детектор Хаара.

Atronax 22.03.21 в 14:25

0

Завантажуємо детектори Хаара або LBP для розпізнавання об'єкта чи обличчя

Atronax 22.03.21 в 14:25

0

Щоб здійснити розпізнавання об'єкта чи обличчя, спершу потрібно завантажити заздалегідь натренований файл XML за допомогою класу CascadeClassifier таким чином:
CascadeClassifier faceDetector;
faceDetector.load(faceCascadeFilename);

Atronax 22.03.21 в 14:25

0

Завдяки цьому можна завантажити детектори Хаара чи LBP, лише вказавши іншу назву файлу. Поширеною помилкою є передавання невірної теки чи назви файлу, але залежно від середовища побудови, метод load() завжди або поверне значення false, або згенерує виняток С++ (та завершить роботу програми помилкою assert). Тому краще оточити метод load() блоком try/catch та показати на екрані повідомлення про помилку. Початківці часто пропускають перевірку на помилки, забуваючи про важливість допоміжних повідомлень, коли щось відбулося не правильно. Але це варто робити, інакше ви витратите дуже багато часу на налагодження інших частин коду перед тим як дізнаєтесь, що файл не завантажено. Код простого повідомлення матиме такий вигляд:

Atronax 22.03.21 в 14:25

0

CascadeClassifier faceDetector;
try {
faceDetector.load(faceCascadeFilename);
} catch (cv::Exception e) {}
if ( faceDetector.empty() ) {
cerr << "ПОМИЛКА: Не вдалося завантажити детектор обличчя (";
cerr << faceCascadeFilename << ")!" << endl;
exit(1);
}

Atronax 22.03.21 в 14:25

0

Отримуємо доступ до вебкамери

Atronax 22.03.21 в 14:25

0

Щоб отримати кадри з вебкамери комп'ютера чи навіть відеофайлу, досить просто викликати функцію VideoCapture::open(), передавши в якості аргументу номер камери чи назву відеофайла, потім здобути кадри за допомогою потокового оператора C++, як показано в частині "Отримуємо доступ до вебкамери" у розділі 1 "Ефект мультиплікації та зміна кольору для Android".

Atronax 22.03.21 в 14:25

0

Знаходимо об'єкт за допомогою класифікатора Хаара чи LBP

Atronax 22.03.21 в 14:26

0

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

Atronax 22.03.21 в 14:26

0

1. Перетворення у відтінки сірого. Розпізнавання обличчя працює лише з такими зображеннями. Ми повинні конвертувати кольорові кадри у відтінки сірого.
2. Зменшення розмірів кадру. Швидкість алгоритму залежить від розмірів вхідного зображення (дуже повільна для великих, але швидка для малих кадрів), а пошук дає пристойні результати навіть для низької розподільної здатності. Тому маємо зменшити зображення з камери до більш прийнятних розмірів (або використати велике значення minFeatureSize у детекторі).
3. Вирівнювання гістограми. Розпізнавання обличчя ненадійне в умовах слабкого освітлення. Тому потрібно здіснити цю процедуру для покращення контрасту та яскравості.

Atronax 22.03.21 в 14:26

0

Перетворення у відтінки сірого

Atronax 22.03.21 в 14:26

0

Кольорове зображення можна легко перетворити у відтінки сірого за допомогою функції cvtColor(). Але це потрібно робити лише тоді, коли ми маємо саме кольоровий знімок (камера не надає сірі зображення), і ми повинні визначити формат вхідного кадру (зазвичай 3-канальний BGR на настільному пристрої чи 4-канальний BGRA на мобільному). Тому варто підримувати три різні формати кольору, як показано в такому фрагменті коду:

Atronax 22.03.21 в 14:26

0

Mat gray;
if (img.channels() == 3) {
cvtColor(img, gray, CV_BGR2GRAY);
}
else if (img.channels() == 4) {
cvtColor(img, gray, CV_BGRA2GRAY);
}
else {
// отримуємо доступ до зображення у відтінках сірого напряму
gray = img;
}

Atronax 22.03.21 в 14:26

0

Зменшуємо розміри кадру камери

Atronax 22.03.21 в 14:26

0

Для зменшення розмірів зображення можна скористатися функцією resize() або множником масштабування. Пошук обличчя зазвичай працює досить добре для кадрів з розмірами, що більші за 240х240 пікселів (якщо обличчя розміщені не занадто далеко від камери), адже алгоритм працюватиме для будь-яких із них, що більші за minFeatureSize (типово 20х20 пікселів). Тому зменшимо ширину отриманих кадрів до 320 пікселів; при цьому неважливо, вхідні дані отримані з вебкамери VGA чи 5-мегапіксельного HD пристрою. Не забудьте збільшити результати пошуку, адже знайдені обличчя також будуть зменшеними.

Atronax 22.03.21 в 14:26

0

Замість зменшення розмірів вхідного зображення можна відрегулювати значення параметра minFeatureSize детектора. Фрагменти не мають стати ширшими або вужчими. Наприклад, зменшивши широке зображення з розмірами 800х400 до 300х200, отримаємо кадр, на якому людина видаватиметься худою. Тому потрібно зберегти відношення сторін (відношення ширини до висоти) вхідних даних. Обчислимо, наскільки потрібно зменшити ширину зображення, а потім застосуємо отриманий множник масштабування і для висоти:

Atronax 22.03.21 в 14:27

0

const int DETECTION_WIDTH = 320;
// за можливості обмежимо розміри зображення, щоб збільшити швидкість алгоритму
Mat smallImg;
float scale = img.cols / (float) DETECTION_WIDTH;
if (img.cols > DETECTION_WIDTH) {
// зменшимо зображення, але залишимо відношення сторін
int scaledHeight = cvRound(img.rows / scale);
resize(img, smallImg, Size(DETECTION_WIDTH, scaledHeight));
}
else {
// отримаємо дані напряму, адже вони вже малі
smallImg = img;
}

Atronax 22.03.21 в 14:28

0

Вирівнювання гістограми

Atronax 22.03.21 в 14:28

0

Бібліотека OpenCV дозволяє легко здійснити вирівнювання гістограми для покращення контрасту та яскравості зображення за допомогою функції equalizeHist() (як пояснено в праці "Computer Vision with the OpenCV Library". Іноді це призводить до дивного вигляду зображення, але в загальному яскравість і контраст покращуються, і це допомагає швидше та надійніше знаходити обличчя. Функція equalizeHist() застосовується таким чином:

Atronax 22.03.21 в 14:28

0

// стандартизуємо яскравість та контраст, щоб
// покращити темні зображення
Mat equalizedImg;
equalizeHist(inputImg, equalizedImg);

Atronax 22.03.21 в 14:29

0

Пошук обличчя

Atronax 22.03.21 в 14:29

0

Сконвертувавши зображення у відтінки сірого, зменшивши його розміри та вирівнявши гістограми, ми готові визначити обличчя за допомогою функції CascadeClassifier::detectMultiScale()! Вона має такі параметри:

Atronax 22.03.21 в 14:29

0

minFeatureSize - визначає мінімальний розмір обличчя, типово становить 20х20 чи 30х30 пікселів, але залежить від конкретного випадку та розміру зображення. Якщо ви здійснюєте пошук обличчя на кадрі з вебкамери чи мобільного пристрою, коли воно знаходиться поряд із камерою, можна збільшити це значення до 80х80, щоб отримати результат швидше, а якщо потрібно знайти обличчя на відстані, наприклад серед осіб на пляжі, залиште 20х20.
searchScaleFactor - визначає кількість різних розмірів облич, які маємо знайти; типово становить 1.1 для якісного пошуку та 1.2 для швидкого, але не настільки надійного.

Atronax 22.03.21 в 14:29

0

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

Atronax 22.03.21 в 14:29

0

flags - дозволяє визначити пошук усіх облич (за замовчуванням) або лише найбільшого (CASCADE_FIND_BIGGEST_OBJECT). Якщо потрібне лише найбільше, алгоритм знайде результат швидше. Існують також й інші параметри, які можуть пришвидшити процес, наприклад CASCADE_DO_ROUGH_SEARCH чи CASCADE_SCALE_IMAGE.

Atronax 22.03.21 в 14:29

0

Результат функції detectMultiScale() матиме тип std::vector<cv::Rect>. Наприклад, якщо вона знайде два обличчя, в масиві буде збережено два прямокутники. Функція діє таким чином:

Atronax 22.03.21 в 14:29

0

int flags = CASCADE_SCALE_IMAGE; // пошук багатьох облич
Size minFeatureSize(20, 20); // найменший розмір обличчя
float searchScaleFactor = 1.1f; // кількість розмірів для пошуку
int minNeighbors = 4; // надійність проти кількості
// шукаємо об'єкти на малому зображенні у відтінках сірого
std::vector<Rect> faces;
faceDetector.detectMultiScale(img, faces, searchScaleFactor,
minNeighbors, flags, minFeatureSize);

Atronax 22.03.21 в 14:30

0

Щоб перевірити, чи були взагалі знайдені обличчя, можна оглянути кількість елементів, що зберігаються у векторі прямокутників, за допомогою функції objects.size().

Atronax 22.03.21 в 14:30

0

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

Atronax 22.03.21 в 14:30

0

// Збільшуємо результати, якщо зображення було тимчасово зменшене.
if (img.cols > scaledWidth) {
for (int i = 0; i < (int)objects.size(); i++ ) {
objects[i].x = cvRound(objects[i].x * scale);
objects[i].y = cvRound(objects[i].y * scale);
objects[i].width = cvRound(objects[i].width * scale);
objects[i].height = cvRound(objects[i].height * scale);
}
}
// Якщо об'єкт розміщений на границі, залишити його на зображенні.
for (int i = 0; i < (int)objects.size(); i++ ) {
if (objects[i].x < 0)
objects[i].x = 0;
if (objects[i].y < 0)
objects[i].y = 0;
if (objects[i].x + objects[i].width > img.cols)
objects[i].x = img.cols - objects[i].width;
if (objects[i].y + objects[i].height > img.rows)
objects[i].y = img.rows - objects[i].height;
}

Atronax 22.03.21 в 14:31

0

Попередній код шукатиме всі обличчя на зображенні, але якщо вам потрібне якесь конкретне, змінну флагу можна вказати таким чином:
int flags = CASCADE_FIND_BIGGEST_OBJECT | CASCADE_DO_ROUGH_SEARCH;

Atronax 22.03.21 в 14:31

0

Проєкт WebcamFaceRec включає клас-обгортку навколо детектора Хаара чи LBP, аби мати можливість легше знаходити обличчя чи око на зображенні. Наприклад:
Rect faceRect; // зберігає результати пошуку, або повертає -1
int scaledWidth = 320; // зменшуємо зображення перед пошуком
detectLargestObject(cameraImg, faceDetector, faceRect,
scaledWidth);
if (faceRect.width > 0)
cout << "Обличчя знайдено!" << endl;

Atronax 22.03.21 в 14:32

0

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

Atronax 22.03.21 в 14:32

0

// Виокремимо фрагмент обличчя із кадру камери.
Mat faceImg = cameraImg(faceRect);
Далі проілюстровано типовий прямокутний фрагмент, знайдений детектором обличчя:

Atronax 22.03.21 в 14:33

0
Минутку...

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