Хабрахабр

Компьютерное зрение как альтернатива офисным пропускам

Сначала небольшая предыстория. Сегодня я расскажу, как мы делали в офисе пропускную систему на основе сервиса распознавания лиц Vision. Такие системы сейчас делаются на основе машинного обучения, у нас им занимается мощная команда. Как в любом почтовом сервисе, мы создали систему антиспама. Поэтому сервис Vision возник вполне органично и естественно. А где машинное обучение, там и компьютерное зрение.

Со временем у нас появилось «Облако для бизнеса», которое не только хранит файлы, но и позволяет заказывать виртуальные машины. Параллельно с этим несколько лет назад мы запустили Облако — надёжное хранилище файлов с геораспределением по дата-центрам, которым могут пользоваться как частные лица, так и компании. Постепенно это превратилось в MCS — Mail.ru Cloud Solutions, куда в качестве одного из сервисов очень органично вписался Vision.

Наши нейросети способны распознавать далеко не только лица, но и разные предметы, объекты и сцены, в том числе достопримечательности. Сейчас они могут распознавать около 10 тыс. категорий, и машинное зрение иной раз работает лучше человеческого.

Если бы я не знал ее лично, то, наверное, не сразу понял, что это один и тот же человек. Это моя дочь в 2012-м, в 2015-м и 2018-м. А нейронная сеть смогла сопоставить и понять.

Но при этом нейронная сеть точно их распознала, даже несмотря на такие сложные условия. Здесь девочка отвернулась и прищурилась, а мальчик вообще в фуражке с тенью на половину лица. Естественно, что технология, которая развивается внутри компании, не могла не найти поддержку во внутренних сервисах.

Наш интранет называется sys. Это своего рода социальная сеть (у нас же их мало). В ней сотрудники выкладывают фотографии с разных мероприятий.

Поэтому у нас к этим альбомам подключено машинное зрение, которое прямо в интранете, в едином месте показывает фотографии, на которых я изображён. Когда с мероприятия выкладывается несколько сотен фотографий, то найти себя там достаточно сложно. Вот тут система меня увидела на одном из летних корпоративов.

Нейросеть распознала меня даже в полумраке в профиль, и на фотографии ещё множество людей.

Позднее мы сделали стойки для конференций. Я писал софт для iPad, который установлен внутри стойки, но вообще я iOS-разработчик и к компьютерному зрению никакого отношения не имею, просто по-дружески помогаю.

В течение всего мероприятия — митапа, конференции, корпоратива, да хоть дня рождения — вас фотографирует фотограф. В чем суть этой стойки? Вы в любой момент можете подойти к стойке, сфотографироваться и нажать на кнопку «Найти меня». Он время от времени сбрасывает накопившиеся снимки в Облако. И после мероприятия вам на почту придёт ссылка на папку в Облаке со всеми фотографиями, на которых вы есть. И стойка либо сразу выведет все фотографии, на которых вы запечатлены, либо скажет, что пока ничего не найдено, если система еще не успела проиндексировать снимки, и предложит ввести e-mail. Это одно из применений сервиса Vision.

Естественно, такие возможности по распознаванию лиц захотелось использовать не только для поисков своей физиономии на снимках с корпоративов, но и для чего-то более практичного. Например, для автоматической пропускной системы. Прикладывать пропуск при каждом входе на свой этаж не очень удобно: пропуск часто забываешь, а девушкам летом в лёгкой одежде пропуск даже некуда крепить.

Для этого у нас есть все условия: не нужно ни у кого просить разрешения, очень отзывчивый административный отдел, который со вздохом говорит: «Ладно. Поэтому мы решили поэкспериментировать. Только не на дверь. Прикрепляйте свои камеры. Мы такие: «Ну ладно. Двери относятся к пожарной безопасности». А ещё у нас терпеливые коллеги, они от нас натерпелись. Мы сбоку прикрепим».

На первый взгляд, архитектура пропускной системы видится очень простой: камера снимает, отправляет в Vision, а Vision открывает дверь. Но когда мы начали расписывать с коллегами, как же это на самом деле сделать, то получилась вот такая схема:

Он состоит из трёх частей. Блок справа мы называем «камерой» — это модуль, который висит на двери. Мы протестировали несколько IP-камер разумного ценового диапазона, и у всех оказалась ощутимая задержка примерно в 0,5 с. Raspberry Pi принимает видеосигнал с USB-камеры, кодирует с помощью FFmpeg и отправляет. Поэтому мы сокращали задержки, где только возможно, и Raspberry Pi c USB-камерой оказалась быстрее, чем многие коммерческие IP-камеры. А поскольку у нас есть задержки и на других этапах, то когда человек подходит, смотрит в камеру и в течение нескольких секунд ничего не происходит, ему уже хочется приложить пропуск. Светодиод по умолчанию светится красным. Также к Raspberry подключена маленькая Arduino с разноцветным светодиодом и пищалкой. Когда человек подходит и распознан, загорается зеленый.

У нас на каждом этаже есть серверная, в которой стоят свичи, коммутирующие кабели к столам сотрудников, и штатная СКУД — система контроля и управления доступом. Итак, Raspberry Pi передаёт видеопоток, который по проводному Ethernet попадает в серверную.

Зачем нам еще OpenCV? Мы поставили в серверной ещё одну Raspberry Pi, которая получает видеопоток в реальном времени и прогоняет его через OpenCV. Нейронная сеть, которая определяет человека на фотографии, работает чуть-чуть дольше, и постоянно скармливать ей поток видеоданных слишком затратно. Нам нужно определить, есть ли на картинке лицо. Сервис либо отвечает, что не нашел этого сотрудника, либо отправляет идентификатор сотрудника в базе данных HR. Поэтому мы через OpenCV определяем наличие лица, и если оно появилось, тогда отправляем в Vision. Дальше этот идентификатор пропуска мы закидываем в Arduino, которая передаёт его в СКУД. С этим идентификатором сотрудника мы идем в интранет, который завязан со СКУД, и он возвращает нам идентификатор пропуска. То есть мы никак не изменяем СКУД, она по-прежнему журналирует вход и выход сотрудников. Для системы контроля доступа это равносильно тому, что человек приложил пропуск.

У нас в офисе применяются устройства Bolid C2000-2. Как мы интегрировали свою систему со СКУД?

К этим приборам, скорее всего, можно подключаться через 485-й интерфейс, но мы подключились через протокол Wiegand. Это отечественная система контроля доступа.

К считывателю пропусков, установленному рядом с дверью, мы подключили Arduino, который выступает в роли прокси.

Колодка используется для более удобного подключения. На фото показано подключение питания и двух линий данных от считывателя пропусков.

СКУД даже не знает, откуда получен номер пропуска. Arduino получает номер пропуска либо от считывателя, либо от Raspberry Pi по USB, и отдаёт его в СКУД.

Это стандартный протокол для СКУД, он поддерживается большинством считывателей. Протокол очень простой: две линии данных, одна линия нулей и одна линия единиц. Как только вы подключаете к земле нулевую линию, считывающее устройство понимает, что передан ноль, тоже самое с единицами. То есть у протокола нет стандартизированных таймингов, и номер пропуска легко считывать через прерывание на Arduino, легко представлять в виде последовательности данных. А поскольку для записи нужен какой-то тайминг, я ориентировался на эти значения:

Она умеет считывать разные форматы Wiegand, но этим её возможности ограничиваются. Для Arduino уже есть готовая библиотека. Поэтому я написал свою библиотеку, которая работает только с форматом Wiegand-26. А мне нужно было еще передавать. Причем во всех документациях и статьях написано, что, вероятнее всего, ваш современный контроллер будет игнорировать биты чётности, поэтому я ленюсь и их не считаю, а всегда отправляю ноль. 26 — это количество бит: 3 байта номера пропуска и 2 бита чётности. СКУД это нормально воспринимает.

Если кто-то сначала показался перед камерой, а затем, не дождавшись срабатывания, приложил пропуск, то возникала ситуация гонки: одновременно приходил номер пропуска от считывателя и от распознавания. У была такая проблема. Поэтому пришлось добавить в библиотеку кольцевой буфер на 4 кода. СКУД с этим не справлялась и не пускала человека. С тех пор коллеги перестали жаловаться на то, что их не пускают. Откуда бы коды ни пришли, они помещаются в буфер, а затем с таймаутом в 0,5 с передаются в СКУД.

На какой-то нелепой стойке висела Raspberry Pi в коробке, а сверху на двухсторонний скотч приклеена камера. Первый прототип был собран из чего попало. В общем, всё, как мы любим, очень DIYненько. Сбоку на стяжках висит Arduino.

Мы переговорили с несколькими подрядчиками, они нам пообещали заказать образцы в Китае, но потом все оговоренные сроки прошли, а нам так никто ничего и не предложил. Конечно, в таком виде оставлять было нельзя, нужно было оформить красиво.

Во-первых, мы становимся зависимыми от поставщика. У кастомными продуктов есть одна проблема — все решения узкоспециализированные, они делались бы специально под нас. В-третьих, достаточно большой срок изготовления, и если какой-то экземпляр выйдет из строя, мы не сможем быстро купить в магазине замену, придётся ждать изготовления следующего тиража, а если сразу делать с запасом, то оставшиеся экземпляры будут пылиться на складе. Во-вторых, получается уникальная схемотехника с малым тиражом, а значит, стоимость одной штуки будет высокой.

Он вздохнул и сказал: «Ну давай. После того, как все потенциальные партнёры нас подвели, я пришёл к коллеге из Vision и говорю: «Володя, давай я тебе на 3D-принтере напечатаю корпус, чтобы это красиво выглядело». Что делать?»

В углу должна была размещаться Raspberry Pi со входом под Ethernet-кабель. Я во Fusion нарисовал вот такое чудовище Франкенштейна. «Вторым этажом» ставилась камера. Сбоку вход под питание. Выглядело ужасно, и вешать это было ещё более стыдно. Получилась крупная конструкция, и я её даже напечатал тонким слоем, чтобы не тратить много пластика.

Я ответил, что не смогу так сделать, но решил спроектировать другой корпус. К тому же коллега прислал мне вот такой референс, мол, нам бы такое.

Размещение начинки тоже двухслойное. Новый корпус был диаметром 11 см, меньше компакт-диска. Разобрал её аккуратно, и оказалось, что у нее есть 4 посадочных отверстия на лицевой панели. Ещё напечатав первую версию, я понял, что нет никакого смысла ставить USB-камеру целиком в родном корпусе. Эту панель с камерой я объединил в общую сборку с пищалкой и светодиодом.

Получилось крайне плохо. Сначала мы попробовали сгенерировать писк на Raspberry Pi через gpio. Поэтому решили вынести эту функцию отдельно от Raspberry Pi, подключив маленькую ардуино (на самом деле Iskra mini), к которой были припаяны пищалка и светодиод, через TTL прямо к колодке.

Вот так это выглядело в бою:

Мы повесили устройство на этаже. В таком виде оно прожило достаточно долго. Пищало, красиво светилось, открывало дверь, правда, не каждый раз. Коллеги, правда, жаловались, что светодиод слишком яркий. Пришлось его ослабить раза в 4.
Затем сделали такой вариант:

Очень красиво выглядит. Он был навеян дизайном хаба Xiaomi, со светящимся кольцом по периметру. Вот модель: Логотип Vision сделан отдельными деталями, напечатанными пластиками разного цвета.

Декор почти сразу провалился внутрь, потому что изначально был просто вставлен на трении, и пришлось сажать его на клей. В этот раз я убрал пищалку на заднюю стенку, вмонтировал светодиод в прозрачное колечко по периметру, напечатанное из прозрачного PLA.

У нас была мысль растиражировать это решение по всему зданию. Но есть проблема: почти на всех этажах по две двери, и у каждой должно быть две камеры, всего 96 камер только для одной из наших башен, а сейчас идет активное освоение второй. Распечатать столько корпусов можно, но уже кажется сложным. Кроме того, у нас достаточно много компонентов в устройстве, а значит, много точек отказа. Если масштабировать решение на всё здание, мы будем постоянно обслуживать эти камеры. Опять же, сложность быстрой замены, ведь каждая камера — это штучное устройство. И нужно либо распечатать их много, с запасом, либо, если что-то случилось, то сразу бежать, печатать и собирать новую. Мы поняли, что DIY-решения — это классно, но нужно что-то более удобное в тиражировании. И возникла идея перенести всё на iPad.

Айпад

У iPad есть несколько преимуществ. Во-первых, экран. Коллеги жаловались на отсутствие обратной связи, они подходят и не понимают, началось распознавание или нет, ждать им или не ждать.

Функцию, которую выполняла OpenCV, мы передали iPad. Во-вторых, в iOS есть встроенная функция распознавания лица. После этого система начинает автоматически его распознавать, ничего нажимать не надо. На экране отображается рамка, и человек должен подойти на такое расстояние, чтобы лицо помещалось в эту рамку.

Если он вышел из строя, мы ставим другой. В-третьих, iPad — это массовый продукт. рублей, то это всё равно дешевле кастомных камер, которые нам предлагали партнеры. Хотя сам планшет стоит около 20 тыс. К тому же быстрее и надёжнее.

На Raspberry Pi, который стоит в серверной, фактически остается только HTTP-хост, который принимает GET-запрос с ID пропуска. iPad взял на себя большую часть функций. Он тут же проксирует код в Arduino, а та проксирует в СКУД.

К ней было уже не подключить вторую камеру, не хватило бы вычислительной мощности. В первом варианте Raspberry Pi была очень нагружена, потому что на ней постоянно работал OpenCV. Но до этого не дошло. Мы уже думали о том, что надо ставить туда честный компьютер, который парсил бы 4 потока от двух дверей. В кроссовой остаются две Arduino, по одной на каждую дверь. Сейчас поиск лица на изображении выполняется независимо на каждом айпаде. Почему важно работать с пропусками на вход и на выход. Обе платы работают с пропусками на вход и на выход. Во-вторых, СКУД логирует входы и выходы. Во-первых, когда лицо распознано и дверь открывается, на считывателе карт загорается зеленая лампочка, и коллегам понятно, что можно выходить. Эмулируя вход и выход раздельно, мы не ломаем схему работы СКУД.

Вот так это выглядит сейчас на одном из этажей нашего офиса: Естественно, подтянулись дизайнеры, которые нарисовали нам красивый интерфейс.

Несмотря на то, что MCS — это бизнес-продукт, его могут использовать и любители. Сервис предлагает каждому 5 тыс. бесплатных транзакций в месяц, то есть 166 в день. Поэтому вы можете применять для своих домашних нужд, если укладываетесь в лимит, конечно же. Как это можно сделать?

python examples/python/smarty.py \
-u "https://smarty.mail.ru/api/v1/persons/recognize
?oauth_provider=mcs&oauth_token=e50b000614a371ce
99c01a80a4558d8ed93b313737363830" \
-p friends1.jpg \
--meta '' \
-v

Возьмём фотографию и отправим в Vision вместе с нашим токеном доступа. Укажем, что работаем с первым спейсом, и зададим create_new — тогда под каждое незнакомое лицо система будет создавать новый идентификатор. Вот что получаем в ответ:

{ "status":200, "body":{ "objects": [ { "status":0, "name":"file_0", "persons":[
{"tag":"person1","coord":[102,30,184,134],"confidence":0.99999,"awesomeness":0.5025},
{"tag":"person2","coord":[393,74,461,166],"confidence":0.99987,"awesomeness":0.548},
{"tag":"person3","coord":[458,48,535,149],"confidence":0.99976,"awesomeness":0.4766},
{"tag":"person4","coord":[273,45,352,147],"confidence":0.99963,"awesomeness":0.504},
{"tag":"person5","coord":[525,81,600,184],"confidence":0.99954,"awesomeness":0.4849},
{"tag":"person6","coord":[194,76,258,167],"confidence":0.9984,"awesomeness":0.5725}
] } ], "aliases_changed":false }, "htmlencoded":false, "last_modified":0 }

Я немного отформатировал JSON. В ответе содержится идентификатор человека, координаты лица на фотографии и два параметра: насколько хорошо распознано лицо и насколько этот человек соответствует эталону. Можете на своём языке программирования отправить POST-запрос с картиной, получить JSON и распарсить ответ.

Тогда система будет на знакомых людей выдавать их идентификаторы, а на незнакомых — undefined. Если у вас большая проходимость, а нужно определять всего десяток человек, вы можете задать их вручную. Людей можно и выборочно удалять, например, если сотрудник уволился.

В каких проектах вы можете использовать распознавание лиц? Если захотите реализовать пропускную систему, придётся озаботиться антиспуфингом. Например, добавив инфракрасную камеру, чтобы определять, фотография это или живой человек. Или поставив две камеры для определения глубины объекта, это можно сделать с помощью OpenCV.

Если это ваши соседи, то всё в порядке, а если кто-то посторонний, то можно отсылать себе оповещение. Можно организовать распознавание людей в подъезде. У нас в доме есть такая проблема, периодически приходят посторонние и оставляют после себя много мусора на лестничной площадке.

Скажем, мне зеркало покажет график встреч на сегодня, а с дочерью весело поздоровается и предложит почистить зубы, причём не быстро, как обычно, а две минуты. Если вы сделаете «умное зеркало», то можно оснастить его и распознаванием членов семьи, чтобы каждому показывать то, что ему интересно.

Чтобы не выходить или не нажимать брелок, можете поставить камеру, которая снимет ваш номер, и ворота откроются автоматически. Ещё идея — распознавание автомобильного номера автоматическими воротами на даче.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть