
Биометрия везде. Современные мегаполисы в России и мире окутаны сетями камер, подключенными к различным системам распознавания лиц. Насколько это правильно с точки зрения этики — каждый решает сам, но факт в том, что такие методы не только помогают раскрывать преступления, но и предотвращать их совершение.
С каждым годом расширяется область применения таких систем. Например, пользователи могут приобрести у Google систему Nest — Nest Cam IQ Indoor, стоимостью 349 долларов с интеграцией в умный дом и возможностью распознавания лиц по подписке (за 10 долларов в месяц). И отечественных аналогов для частного пользования немало. Различные СКУД (системы контроля и управления доступом) от Ростелекома, HikVision, VisionLabs и других фирм. Описание зачастую мутное, опыт работы в реальных условиях можно найти на YouTube по запросу «Умный домофон не пускает мужчину домой».

Да, назначение систем с технологиями распознавания лиц может быть разным, но все они имеют два главных недостатка: завышенная цена и отсутствие приватности. Разберем подробнее второй пункт.
Существует несколько методов реализации системы определения биометрических данных в реальном времени: анализ видеопотока на удаленном сервере, на камере с передачей данных на сервер, на локальном устройстве с подключенной камерой.
Наиболее распространена первая схема реализации. Работает она так: камера передает видеопоток на сервер, там специализированное ПО в реальном времени выполняет анализ видеопотока и сравнивает полученные изображения лиц с базой лиц эталонов. Недостатки такой системы — высокая нагрузка на сеть, ограничение по количеству подключенных камер на один сервер.
При применении 2 технологии, анализ изображения будет производится на самом устройстве — камере, а на сервер будут передаваться обработанные метаданные. Недостаток такой системы — очень высокая стоимость камер, способных обработать изображение. Зато можно подключить практически неограниченное количество устройств к удаленному серверу.
Третий метод лучше всего подходит для личного пользования. Именно он будет рассмотрен в этой статье. Он отличается от первого локальным использованием. Из этого вытекает большое преимущество – данные биометрии не передаются третьим лицам, хранятся на локальном устройстве пользователя. Основной недостаток – таких систем почти нет в продаже.
Обычно в качестве базы для локальной системы распознавания лиц используется компьютер или ноутбук с мощным графическим ускорителем. Предпочтительны видеокарты Nvidia из-за архитектуры CUDA, позволяющей существенно увеличить вычислительную производительность системы.
Вопреки расхожему мнению, алгоритмы распознавания лиц могут работать и на системах с небольшой вычислительной мощностью. Как например одноплатный микрокомпьютер Raspberry PI 4B с производительностью старого андройд смартфона. Именно такой микрокомпьютер с 4гб оперативной памяти и 4-ядерным процессором частотой 1.5 ГГц был использован в данном проекте.

В качестве алгоритма распознавания лиц была использована библиотека face-recognition для python. Эта библиотека работает с моделью распознавания лиц от dlib. Устанавливается достаточно просто (cv2 для отображения картинки с камеры):
pip install face-recognition, opencv-python
Помимо простоты установки, данный модуль не требует от устройства высокой производительности и по его использованию написано огромное количество гайдов. Основная часть заключена всего в нескольких строчках, а часть распознавания лиц из кода системы выглядит следующим образом:
import face_recognition import numpy as np import cv2 # векторные представления лиц, имена, user_id в БД known_face_encodings, known_face_names, known_face_uids = [], [], [] def run_rec(): video_capture = cv2.VideoCapture(0, cv2.CAP_DSHOW) while video_capture.isOpened(): # чтение кадра с камеры ret, frame = video_capture.read() # уменьшение разрешения (для быстродействия) divideint = 2 small_frame = cv2.resize(frame, (0, 0), fx=1 / divideint, fy=1 / divideint) # уменьшение размерности матрицы изображения, аналог [:, :, ::-1] rgb_small_frame = cv2.cvtColor(small_frame, cv2.COLOR_BGR2RGB) # обрабатывается каждый 3й кадр (для быстродействия) if process_this_frame % 3 == 0: # расположение лиц face_locations = face_recognition.face_locations(rgb_small_frame) # преобразование лиц в векторы face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations) # сравнение обнаруженных лиц с лицами в базе for face_encoding in face_encodings: name = "Unknown" # вычисление векторного расстояния (мера схожести векторов) # known_face_encodings - face_distances = face_recognition.face_distance(known_face_encodings, face_encoding) # определение индекса максимально похожего лица best_match_index = np.argmin(face_distances) # проверка на степень похожести # похожи если векторное расстояние расстояние меньше 0.6 if face_distances[best_match_index] < 0.6: # имя обнаруженного лица для пользователя name = known_face_names[best_match_index] # user_id лица для внутреннего использования uid = known_face_uids[best_match_index]
Тестирование системы производилось на базе данных ORL, содержащей изображения лиц с небольшими изменениями освещения, масштаба, пространственных поворотов, положения и различными эмоциями. База представляет собой 400 фотографий 40 разных людей. Все фото представлены в градации серого.

Обычно эта база используется для обучения алгоритмов распознавания лиц, но я решил проверить качество работы и быстродействие алгоритма на основе face-recognition. В результате, алгоритм, работающий на Raspberry PI 4B смог обнаружить 376 лиц за 7 секунд.
import os import glob import face_recognition import time start = time.time() faces_folder_path = './orl_faces' cnt = 0 for f in glob.glob(os.path.join(faces_folder_path, "*.jpg")): print("Processing file: {}".format(f)) #загрузка фото img = face_recognition.load_image_file(f) #обнаружение лица на фотро face_locations = face_recognition.face_locations(img) #подсчет # face_locations - список элементов (лиц) # в списке столько элементов, сколько лиц на фото print("Number of myfaces detected: {}".format(len(face_locations))) if len(face_locations) != 0: cnt += 1 print(f'total myfaces detected {cnt}') print(f'total seconds spent {int(time.time() - start)}')
Так, например, компьютер на процессоре Intel Core I5 смог обнаружить те-же 376 лиц примерно за 2 секунды.
Но показатели этого теста можно рассматривать только в контексте скорости обнаружения лица в кадре. Неотъемлемой частью алгоритма распознавания лиц является сравнение лица в кадре с лицами в базе системы. Для этого необходимо преобразовать картинку в векторное представление и сравнить со всеми лицами в базе. К тому же, необходимо было организовать подключение к базе данных с постоянным обновлением данных в ней. Для управления базой данных была использована СУБД SQLite. Она отличается от других СУБД простотой настройки и удобством использования в малопроизводительных платформах, как Raspberry PI. Через постоянные обращения к базе и определяется принадлежность лица в объективе камеры системы к лицам, добавленным в систему как авторизованные пользователи; осуществляется логирование посещений. Эти части алгоритма (векторное преобразование, обращение к базе, сравнение обнаруженного лица с лицами в базе) и представляют собой самую ресурсоемкую его часть. Обращение к базе:
def get_db(): conn = sqlite3.connect("face_db.sqlite3") cursor = conn.cursor() cursor.execute("SELECT * FROM FRS") facecount = cursor.fetchall() known_face_encodings = [] known_face_names = [] known_face_uids = [] face_in_home = [] for i in range(len(facecount)): a = pickle.loads(facecount[i][5]) known_face_encodings.append(a) known_face_names.append(facecount[i][1]) known_face_uids.append(facecount[i][0]) face_in_home.append(facecount[i][10]) return known_face_encodings, known_face_names, known_face_uids, face_in_home, conn
Кроме обнаружения и сравнения лица с находящимися в базе пользователей, есть еще одна часть работы алгоритма. Для проверки работы системы распознавания лиц необходима графическая интерпретация. То есть, для того чтобы увидеть, правильно ли лицо распознается и обнаруживается, необходимо транслировать на экран устройства потоковое видео и обрисовывать в нем границы объекта, распознанного как лицо.
import numpy as np import cv2 # запуск камеры video_capture = cv2.video_capture(0, cx2.CAP_DSHOW) # изменение размеров и имени окна для показа изображения video_capture.set(3, 800) video_capture.set(4, 448) сv2.namedWindow('Video', cv2.WINDOW_NORMAL) cv2.resizeWindow('Video', 800, 448) # расположение краев прямоугольника, обозначающего лицо в кадре; имя for (top, right, bottom, left), name in zip(face_locations, face_names): # рисуем прямоугольник вокруг лица cv2.rectangle(frame, (left, top), (right, bottom), (107, 168, 0), 2) # рисует плашку под текст с именем пользователя cv2.rectangle(frame, (left, bottom - 23), (right, bottom), (107, 168, 0), cv2.FILLED) cv2.putText(frame, name, (left + 6, bottom - 6), cv2.FONT_ITALIC, 0.5, (0, 0, 0), 1) # отображение состояния системы cv2.rectangle(frame, (8, 5), (228, 64), (255, 255, 255), cv2.FILLED) cv2.putText(frame, 'RECOGNITION IN PROGRESS', (10, 20), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 0), 2) cv2.putText(frame, 'Model: face-recognition', (10, 40), cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 0), 2)
В реальных условиях, при работе с потоковым видео, при наличии лица в кадре, данный алгоритм показывал скорость в 1-2 обработанных кадра в секунду (обнаружение лица, сравнение с лицами – эталонами):

Без показа видео количество обработанных кадров поднялось до около-стабильных 2 FPS. Небольшое изменение, но очень важное в такой системе, реализуемой на одноплатном микрокомпьютере.
Поскольку проект позиционировался как домашняя система распознавания лиц, необходимо было реализовать удобный интерфейс управления и добавить некоторый функционал. Разработка любого приложения довольно ресурсоемкое занятие, требующее обширных знаний. Поэтому было принято решение вместо полноценного приложения создать чат-бота в мессенджере Телеграм с использованием библиотеки AioGram.
Бот находится на стадии MVP, но уже имеет достаточно разных функций для обеспечения автономной и относительно стабильной работы системы. В числе функций:
— включение/выключение функции распознавания лиц (для снижения нагрузки);
— создание и занесение в базу лиц через отправку фотографий чат-бота;
— проверка журнала посещения (только для пользователей, вручную добавленных в базу);
— получение фотографии с камеры системы распознавания в любой момент;
— ограничение доступа к функциям чат-бота неавторизованным пользователям.
Работа функций в чат-боте:

Включение, проверка состояния

Добавление лиц в базу

Проверка логов посещения

Получение фото с камеры
В заключении хочется сказать, что функционал системы по большому счету ограничен только воображением. И конечно же, навыками программирования. Несмотря на то, что мощность Raspberry ограничена, у неё очень много возможностей, вплоть до управления системой умного дома. Да, проект на данный момент далек от завершающей стадии, но уже можно с уверенностью сказать – домашняя система распознавания лиц возможна и на одноплатном микрокомпьютере.
ссылка на оригинал статьи https://habr.com/ru/post/653461/
Добавить комментарий