Працюємо з нейромережами: як ми навчили камеру розпізнавати обличчя, щоб обійтися без перепусток в офіс

Привіт, мене звати Микола Гашевський. Я ІТ-консультант та інженер з цифрової трансформації із 15-річним досвідом. Одне з моїх хобі — робити невеликі корисні штучки у стилі DIY.

У статті спробую поділитися власним досвідом використання штучного інтелекту для поліпшення офісного життя. Головна ідея проєкту — вдосконалити систему контролю доступу в офіс. Тема може бути цікавою для всіх поціновувачів DIY, які хотіли б використовувати штучний інтелект, а саме нейронні мережі, у своїй роботі.

Потреба автоматизації офісу

У нашому офісі застосовують систему з картками доступу. Тобто часто ми маємо вирішувати й традиційну проблему цього формату — як потрапити на роботу, якщо картка залишилася вдома. Найпопулярніший варіант — з допомогою колеги. Дзвінок другу, прохання відчинити — і ти потрапляєш всередину або чуєш щось на кшталт «чекай, я ще не в офісі». У колі інженерів ми просто мали щось вигадати.

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

На щастя, щоб вийти з офісу, достатньо натиснути одну кнопку біля дверей. Так у мене виникла ідея використати мікроконтролер із реле, щоб замикати цей контакт командою з корпоративного сервера. Для цього я придбав готову плату ESP01, побудовану на чипі ESP8266 із Wі-Fi, і плату реле. З’єднав і запрограмував Web Server із HTTPS та microDNS на С++ під Arduino.

Архітектура рішення

Після розгляду кількох потенційно робочих варіантів ми вирішили зробити кнопку «Відчини двері» на корпоративному порталі. Клік на неї, і сервер посилає JSON із паролем на мікроконтролер. Попри те, що дані передаються по внутрішньому Wі-Fi, протокол HTTPS обрали, щоб запобігти перехопленню пароля. Додаткове обмеження: отримати доступ до сторінки корпоративного порталу, щоб керувати замком, можна тільки з під’єднанням до офісної мережі Wi-Fi. Це знижує ризик випадкового віддаленого відчинення дверей «з дому». Звісно, щоб скористатися системою, ви маєте зайти під своїм іменем і паролем, а всі епізоди відкриття записуються.

Код програми можна побачити тут.

Розробка додаткових сервісів із використанням нейронних мереж

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

Ми подумали, що круто було б розпізнавати людину і відчиняти «правильні» двері прямо перед нею автоматично. До того ж на той момент я якраз закінчив декілька курсів зі штучного інтелекту від SAP та Hasso Plattner Institute. Буду відвертим: мені кортіло використати нові знання на практиці. З нуля таку систему підняти важко, тому я вирушив на пошуки натренованих нейромереж для transfer learning, які могли підійти нам, і на AliExpress — за камерами. Докладніше про це далі.

Архітектура системи

Загалом структура системи схожа на попередню, але додалися відеокамери та сервер розпізнавання облич. Постійне розпізнавання облич — важке завдання для сервера, тому для зниження навантаження на нього вирішив розпізнавати обличчя у два етапи. На першому визначати, чи є людина перед камерою і якщо є, то наскільки близько. Для спрощення масштабування системи використав Docker-контейнер. Якщо потужність наявного відеосервера буде недостатньою, можна швидко підняти ще один і перенести або створити нові контейнери для додаткових камер.

Вибір моделі для розпізнавання

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

Експерименти

OpenCV. Перша спроба — написати код з колегами на С# з використанням бібліотеки OpenCV та готових моделей EigenFaceRecognizer і Caffe Models.res10_300×300_ssd_iter_140000.caffemodel. Вона була частково вдалою, але точність розпізнавання виявилася недостатньою для практичного використання в офісі. Водночас помилки системи були дивними, адже вона плутала деяких людей між собою, а виявити закономірність ми так і не змогли. Були спроби змінювати коефіцієнти або варіанти тренування, але точність тільки погіршувалася. Код цього рішення можна знайти тут.

Крім того, я переконався, що вибір мови програмування C# був радше неправильним, тому що сьогодні спільнота розробників C# досить невелика. Більша частина відкритого коду в галузі штучного інтелекту написана на Python, і можна використовувати готові приклади та бібліотеки для швидкого створення прототипів в AI. Тому я змінив підхід і засів за вивчення Python і пов’язаних з AI бібліотек на кшталт TensorFlow, Keras, Sklearn, NumPy тощо.

Python. Після десятка експериментів і невдалих спроб зупинився на facenet_keras.h5 моделі. Вона вже залита на GitHub, має багато прикладів використання і є корисною для початківців у сфері штучного інтелекту. Щиро кажучи, я не дуже вірив в успіх цього проєкту, тому додатково спробував Docker для швидкого розгортання системи в майбутньому. Тепер думаю, що комбінація нової технології та мови — це ідеальний варіант для пет-проєкту.

«Залізо»

Основа — домашній не дуже новий Athlon FX8300 із 32GB RAM та NVIDIA RTX2060 6GB як прискорювач. Можна обійтися і менш потужною картою, але бажано мати не менше як 6GB пам’яті. Інакше ви будете обмежені у виборі претренованих моделей, вони просто не помістяться у пам’яті.

Камера — Hikvison DS-2CD2143G0-I 4Mp IP camera відеопотік, з якої можна забирати за протоколом RTSP у форматі H264/265. І хоча це не найпопулярніший протокол, FFmpeg разом з OpenCV з ним чудово справляються.

Інструменти розробки

Тут нічого особливого (як для старого розробника під Microsoft .NET): редактор Visual Studio Code із розширеннями для роботи з Python та Docker-контейнерами.

Оскільки я вирішив кодити під Windows із використанням GPU-прискорення, на етапі розробки довелося відмовитися від Docker-контейнера через відсутність його підтримки. Однак Microsoft обіцяє зробити її в майбутньому. Також у планах запустити все із прискоренням під Linux.

Архітектура і програмне забезпечення проєкту

Програмна частина, а саме Python із GPU-прискоренням TensorFlow у Windows, була вже встановлена після проходження навчального курсу, тому я почав із налаштування конфігурацій камери.

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

Така конфігурація Hikvision добре працює із ffdshow без додаткових налаштувань із рядком rtsp://admin: Данный адрес e-mail защищен от спам-ботов, Вам необходимо включить Javascript для его просмотра. :554

Для тестування захоплення потоку підходить VLC player.

Під’єднання до китайської камери no name

Перевірка параметрів відеопотоку у VLC player

Головна перевага в тому, що URL-з’єднання потім можна використовувати без змін у коді Python.

Загалом робота із розпізнаванням образів складна з погляду використання ресурсів процесора та прискорювача. Тому, щоб не гріти атмосферу даремно, я вирішив розпізнавати обличчя у два етапи. На першому — просто детектувати, чи є хтось перед камерою. На другому — виділяти контури обличчя за допомогою готового алгоритму MTCNN; це можна робити зі швидкістю близько 10 разів за секунду навіть тільки за допомогою потужностей CPU. Оскільки готовий пакет відмовився працювати із TensorFlow 2.0, довелося трохи його дописати. Деталі — тут.

Пакування даних облич для розпізнавання

Тут усе стандартно і відбувається поетапно:

  • перебираємо каталоги та файли в них;
  • детектуємо і вирізаємо обличчя;
  • пропускаємо зображення обличчя через нейромережу FaceNet за допомогою метода predict() та отримуємо набір особливостей (embeddings);
  • тренуємо модель Linear Support Vector Machine (SVM) за допомогою .fit(), у результаті обчислення отримуємо натренований класифікатор для FaceNet-мережі;
  • зберігаємо разом з іменами моделей у файл для подальшого використання.

Логіка розпізнавання людини перед камерою

Після пів року неквапливих експериментів у фінальній реалізації для розпізнавання того, хто стоїть перед камерою, використали FaceNet в імплементації tensorflow.keras із трохи модифікованим класифікатором SVC.

Спочатку за допомогою OpenCV під’єднуємося до камери й декодуємо відео в окремому потоці. Навіщо? Під час першої реалізації я зіткнувся з неприємним ефектом затримки кадрів, який міг тривати 5-7 секунд. FFMPEG буферизує відео зсередини і не має можливостей для очищування буфера. Довелося створювати окремий потік і забирати всі кадри максимально швидко, зберігаючи один кадр у внутрішньому буфері.

videograbThread = threading.Thread(target=get_video, args=(sharedFrame, lock,"rtsp://admin: Данный адрес e-mail защищен от спам-ботов, Вам необходимо включить Javascript для его просмотра. :554″, cv2.CAP_FFMPEG), daemon=True)

Далі в основному потоці чекаємо, поки з’явиться кадр з обличчям у буфері (тут використовуємо MTCNN-детектор), і, якщо детектор виявив обличчя перед камерою, намагаємося його розпізнати. Для підвищення точності нормалізуємо вхідне зображення і пропускаємо дані через попередньо треновану модель FaceNet (’facenet_keras.h5′), отримуючи на виході набір особливостей (embrddings). Ці особливості завантажуються у класифікатор SVM, який далі буде використовуватися для розпізнавання особи.

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

Із цим кодом можна ознайомитися на GitHub.

Встановлення контейнера Docker на Windows WSL2

Отже, розпізнавання облич запрацювало локально у Windows. Час підготувати швидке розгортання системи. Програма загалом крос-платформова, тож переходимо на Linux. Doker тут здається добрим кандидатом.

Після того ж навчального курсу в мене вже був встановлений Linux, Docker із контейнером з TensorFlow і прискоренням на RTX2060 та Jupiter Notebook всередині. Однак трохи не спортивно використовувати готове рішення.

Спроба встановити Docker на персональну Windows Home зазнала краху, адже Docker Desktop більше не працює з Home редакцією Windows. На щастя, я якраз потрапив на конференцію Docker 2020 LIVE. Послухав виступи, встановив Docker Extension у VS Code, налаштував WSL 2, нова версія якої працює у Windows Home Edition після оновлення до версії 2004. Результат:

До речі, рекомендую розширення Docker, якщо ви програмуєте у VSCode. Вам не треба перемикатися між вікнами, а все можна робити в одній програмі.

У фіналі я підняв наявний контейнер прямо із Visual Studio Code через Docker plugin, довстановив бібліотеки через pip, скопіював код у Jupiter Notebook з мінімальними змінами, й програма запрацювала. Проте трохи вилаялася на відсутність доступу до GPU — доведеться чекати, поки Microsoft додасть підтримку прискорення GPU в офіційний реліз Docker, яка вже в розробці.

Підготовка до продакшену

Програма розділена на дві частини. Перша пакує фото й імена користувачів і тренує мережу. Цей процес займає багато часу і ресурсів CPU та GPU, як зазвичай і будь-яке тренування нейромережі. Натренована мережа серіалізується за допомогою бібліотеки Joblib у файл разом з описами. На цій стадії через велику кількість обчислень критичним є використання GPU-прискорювача для швидкості тренування.

Друга частина програми працює у Docker-контейнері. Вона десеріалізує вже натреновану мережу і використовує її для розпізнавання обличчя на відео із відеопотоку IР-камери. Також я додав код, який посилає команду на контролер відчинення дверей, описаний у першій частині статті.

Для збереження фото з IP-камери додав вебсторінку з простим інтерфейсом самообслуговування. Кожен може сфотографувати себе сам. Ім’я користувача підтягується автоматично з логіну і зберігається на сервері. Далі адміністратор має перевірити зображення і вручну перетренувати мережу.

Захоплення фото з IP-камери

Плани

У перспективі — розробка чогось схожого на Continuous Integration. Тобто я планую збирати фото успішних розпізнавань і регулярно тренувати мережу актуальними даними, видаляючи старі фото з набору. Таким чином мережа буде в актуальному стані, а точність розпізнавань не погіршуватиметься з часом.

Похожие статьи:
Стаття написана у спiвавторстві з Мартою Дідич. Якщо ви мали мінімальний досвід створення рекламних діджитал-кампаній, то, мабуть,...
Компания ИКЕА Россия объявила о запуске коллекции мебели со встроенной беспроводной зарядкой для мобильных устройств. Новые...
Не так давно у меня была презентация на тему фейлов и успехов ИТ-рекрутера. Попробую поделиться парой мыслей из доклада...
Компания Lenovo официально анонсировала смартфон Vibe X3, правда, пока только на китайском рынке. Эта модель является...
Сергій Шалаєв — допоміг організувати радіозв’язок, Євген Семенов, будучи в зоні бойових дій, продовжував...
Яндекс.Метрика