- PVSM.RU - https://www.pvsm.ru -
Привет! В EastBanc Technologies ведётся большое количество проектов, связанных с мобильной разработкой. В связи с чем необходим целый зоопарк устройств для тестирования на всех этапах. И, что характерно, каждый отдельный девайс постоянно оказывается нужен самым разным людям, а найти его даже в одном отделе мобильной разработки из нескольких десятков человек — это целая история. Не говоря уже о том, что есть тестировщики, дизайнеры, PM’ы, в конце концов!
И чтобы не потерять телефон, а четко знать, где он и с кем, мы используем онлайн-базу, которая распознает сотрудников по лицам. Сейчас расскажем, как мы к этому пришли и реализовали её.
У нас была доска с «карточками» устройств с основной информацией и местом под магнитик, обозначающим сотрудника. Каждый отмечался о взятии устройства.
Эта система имеет свои недостатки — не критичные, но в целом неудобные:
В компании, которая занимается автоматизацией бизнес-процессов, использовать описанное выше «аналоговое» решение — не очень здорово. Естественно, мы решили автоматизировать задачу поиска нужного устройства. Первым шагом стало написание мобильного приложения, которое умеет определять и сообщать о своем местоположении в комнатах по Wi-Fi точкам доступа. Попутно для удобства наделили девайсы умением сообщать на сервер о версии ОС, а также показывать такую важную характеристику, как заряд батареи.
Казалось бы, задача решена. Смотришь на список в базе данных, где последний раз устройство видело Wi-Fi, идёшь туда и…
В эксплуатации оказалось, что не всё так просто. Мы установили приложение на тестовые устройства и поработали с ним несколько месяцев. Оказалось, что такой вариант удобен, но тоже не идеален.
Устройства разряжаются, просто выключаются, точки доступа Wi-Fi переставляются из одного места в другое, а геолокация сама по себе говорит только о том, что устройство находится в офисе. Спасибо, капитан!
Можно, конечно, пытаться оптимизировать существующую систему, но почему не переизобрести её на основе технологий ХХI века? Сказано — сделано.
Мы придумали концепт системы, которая бы распознавала сотрудников по лицам, тестовые устройства — по специальным меткам, запрашивала бы подтверждение смены статуса устройства, а потом вносила изменения в онлайн-базу, которую любой сотрудник может посмотреть, не вставая с кресла.
Распознавание лиц в целом решенная задача в 2018 году. Поэтому мы не стали изобретать велосипед и пытаться обучать собственные модели, а воспользовались готовым решением. Самым удобным вариантом показался модуль FaceRecognition [1], т.к. он не требует дообучения и работает весьма быстро даже без ускорения на GPU.
С помощью функции face_locations на фотографиях сотрудников обнаруживались лица, а с помощью face_encodings из них извлекались признаки лица конкретного сотрудника.
Полученные данные собирались в базу. Для определения конкретного сотрудника с помощью функции face_distance считалась «разница» между кодировкой обнаруженного сотрудника и кодировками из базы.
В целом, на этом этапе можно было пойти дальше и создать классификатор, например, на основе KNN [2], чтобы система была менее чувствительна к динамике лиц сотрудников. Однако на практике это требует значительно больших временных затрат. Да и банального усреднения кодировки лица человека между той, что сейчас в базе, и той, которую система обнаружила для смены статуса устройства, оказалось уже достаточно, чтобы на практике избегать накопления ошибки.
face_locations = face_recognition.face_locations(rgb_small_frame)
face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)
face_names = []
for face_encoding in face_encodings:
matches = face_recognition.face_distance(
known_face_encodings, face_encoding)
name = "Unknown"
if np.min(matches) <= 0.45:
best_match_index = np.argmin(matches)
name = known_face_info[str(best_match_index)]['name']
else:
best_match_index = None
Изначально возникла мысль использовать для распознавания устройств QR-коды [3], в которые вносить заодно и информацию об устройстве. Однако для устойчивого распознавания QR-кода его приходилось подносить очень близко к камере, что неудобно.
В результате возникла мысль об использовании маркеров дополненной реальности. Они несут меньше информации, зато гораздо более устойчиво распознаются. В ходе экспериментов маркер размером в 30 миллиметров распознавался камерой при небольших отклонениях от вертикали (3-5 градусов) на расстоянии до двух с половиной метров.
Такой вариант выглядел уже куда лучше. Из всего множества маркеров дополненной реальности были выбраны ARuco [4], т.к. все необходимые инструменты для работы с ними присутствуют в поставке opencv-contrib-python [5].
self.video_capture = cv2.VideoCapture(0)
ret, frame = self.video_capture.read()
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
markers = cv2.aruco.detectMarkers(gray, self.dictionary)
В итоге, каждому устройству был присвоен числовой индекс, с которым сопоставлялся и маркер с этим индексом.
Казалось бы, мы научились распознавать устройства и лица, работа сделана. Фанфары, овации! Что ещё может быть нужно?
На самом деле, работа только начинается. Теперь все компоненты системы нужно заставить стабильно и быстро работать «на бою».
Нужно оптимизировать затраты ресурсов сервера в idle’е, продумать юзкейсы и понять, как это вообще должно выглядеть графически.
Едва ли не самым важным пунктом в разработке подобных систем является интерфейс. Кто-то возможно будет спорить, но пользователь — центральный элемент в такой ситуации.
Максимально быстро можно реализовать фронтенд-часть с помощью Tkinter [6].
.attributes("-fullscreen", True)
позволяет сделать однооконное приложение, разворачивающееся на весь экран, чтобы не смущать пользователей элементами интерфейса системы.
Интерфейс состоит из карточек с информацией об устройстве и пользователе, использующем в текущий момент это устройство. БОльшую часть экрана занимает каталог карточек — основной инструмент учета. Сверху находится фильтр, с помощью которого можно отфильтровать каталог по платформе или версии операционной системы.
Изображение выводим, чтобы дать пользователю обратную связь — ты точно попал в экран меткой устройства.
Один проход любого компонента системы не занимает слишком много времени. Однако, если запустить распознавание маркеров и лиц одновременно, то попытка распознать все 30 кадров в секунду, предоставляемых камерой, приведет к полному исчерпанию ресурсов компьютера без GPU.
При этом понятно, что 99 % времени система будет производить эту работу вхолостую.
Чтобы этого избежать, были приняты следующие оптимизационные решения:
if self.lastseen + self.rec_threshold > time.time() or self.frame_number != 8:
ret, frame = self.video_capture.read()
self.frame_number += 1
if self.frame_number > 8:
self.frame_number = 8
return frame, None, None, None
Задержка реакции системы повышается примерно до 8/30 секунды, при этом время реакции человека — примерно одна секунда. Соответственно, такая задержка всё ещё не будет заметной для пользователя. А мы уже в восемь раз снизили нагрузку на систему.
face_locations = face_recognition.face_locations(rgb_small_frame, number_of_times_to_upsample=0)
Благодаря этому время обработки кадра, на котором нет лиц, сравнялось со временем обработки кадра, где лица легко обнаруживаются.
На текущий момент, система успешно развернута на подвернувшемся под руку MacMini Late 2009, на двух ядрах Core 2 Duo. В рамках тестирования, она вполне успешно работала даже на одном виртуальном ядре с 1024 мегабайтами оперативной и 4 гигабайтами постоянной памяти в контейнере Docker. К MacMini подключили сенсорный дисплей, чтобы внешний вид стал минималистичным.
Сейчас даже те пользователи, которые не пользовались старой доской, с энтузиазмом и улыбкой регистрируют на себя устройства, а случаев безуспешных поисков стало намного меньше!
В текущей системе, несомненно, ещё много моментов, которые можно и хочется улучшить:
P.S. А вот так это работает
Видео записано на бета-версии GUI
Автор: guility
Источник [7]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/python/295772
Ссылки в тексте:
[1] FaceRecognition: https://github.com/ageitgey/face_recognition
[2] KNN: https://en.wikipedia.org/wiki/K-nearest_neighbors_algorithm
[3] QR-коды: https://ru.wikipedia.org/wiki/QR-%D0%BA%D0%BE%D0%B4
[4] ARuco: https://www.sciencedirect.com/science/article/pii/S0262885618300799
[5] opencv-contrib-python: https://docs.opencv.org/3.1.0/d5/dae/tutorial_aruco_detection.html
[6] Tkinter: https://docs.python.org/3/library/tkinter.html
[7] Источник: https://habr.com/post/426437/?utm_campaign=426437
Нажмите здесь для печати.