верификация OpenCV RFID распознавание лиц

Система верификации пользователей посредством RFID карт с отправкой сообщений в Telegram

Сегодня речь пойдет о системе верификации пользователей, которая в будущем сможет стать (и станет, я надеюсь) полноценной системой двухфакторной верификации пользователей. В качестве первого фактора будем использовать RFID карту, в качестве второго - распознавание лица пользователя с помощью OpenCV. На данный момент второй фактор работает в ручной режиме и фото отправляется в Телеграм оператору. Но автор топика активно работает над адаптацией каскада Хаара для распознавания лиц. И, как знать, может скоро и выйдет еще одна статья. Не будем загадывать. Все равно в одну статью это все не уместить. Поэтому начнем. Кому интересно - добро пожаловать под кат.

1. Схемотехническое проектирование

1.1 Лирическое отступление

Я считаю, что наш ГОСТ вполне имеет право на жизнь. И, если следовать порядку проектирования, описанному в нем, то процесс разработки и поддержки любого реального проекта становится проще и понятнее любому члену команды. По крайней мере это точно касается маленьких проектов вроде этого, особенно если не заниматься занудством до невозможности и не пытаться соблюсти его кругом и всюду.

1.2 Непосредственно проектирование

Проектирование устройства было начато с разработки электрической структурной схемы, представленной ниже. Из схемы видно, что устройство состоит из трёх основных блоков: Raspberry Pi, модуля считывания RFID карт RFID-RC522 и WEB-камеры.

Монитор - не обязательная вещь. На него просто будут выводиться логи вроде "Карта №... Доступ разрешен".

Выбор считывателя ничем не обоснован. Взял тот, что был под рукой.

Процесс работы устройства выглядит следующим образом: пользователь прикладывает RFID карту к считывателю, Raspberry Pi проверяет разрешен ли доступ для владельца карты, если доступ разрешен, то делается фотография web-камерой. Информация о владельце карты (для примера, у нас будет ID карты) и фотография автоматически отправляются оператору устройства на заранее сконфигурированный номер в Telegram. Если пользователю данной карты доступ запрещен, то фотографирования не происходит, выдается сообщение «Доступ запрещен!» и сообщение не отправляется.

В качестве WEB-камеры может использоваться любая WEB-камера совместимая со стандартным классом USB устройств USB Image. Т.е. практически любая USB WEB-камера, за исключением совсем экзотики.

При отправке Telegram-боту сообщения вида /photo в ответ оператор получает последнее фото с камеры.

При отправке Telegram-боту сообщения вида /text в ответ, для примера, будем выводить информацию о том какой пользователь воспользовался системой последним (прошел через турникет, например).

2. Разработка ПО

2.1 Структура ПО

В начале я хотел написать свой модуль ядра для работы с SPI, но про это можно написать целую отдельную статью. Да и зачем?? Если есть готовый. Может когда-нибудь в академических целях...

Поэтому использовать мы будем стандартный драйвер spi_bcm2708.

По умолчанию он занесен в blacklist ввиду не использования его большинством пользователей. Поэтому комментируем соответствующую строчку в соответствующем файле. Это делается так:

sudo nano /etc/modprobe.d/raspi-blacklist.conf

в этом файле комментируем строку

blacklist spi-bcm2708

Модуль активировали.

Хотел написать библиотеку для работы с этим модулем. Но и тут не получилось выпендриться. Уже есть готовая.

Для взаимодействия будем использовать уже написанную библиотеку. Она требует для работы другую - SPI-Py

Следующий набор команд установит все, что нам потребуется (git, разумеется, уже должен быть установлен):

sudo apt-get install python-dev
git clone https://github.com/lthiery/SPI-Py.git
cd SPI-Py
sudo python setup.py install
git clone https://github.com/rasplay/MFRC522-python.git

Писать будем на языке python. Работать будем в директории MFRC522-python.

cd MFRC522-python

Структура нашего проекта представлена на рисунке ниже.

Взаимодействие со считывателем RFID карт осуществляется через стандартный модуль ядра spi_bcm2708. Основные функции работы с SPI из userspace реализованы в библиотеке SPI-Py. По средствам этой библиотеки модуль чтения запускает опрос считывателя. Конфигурация модуля чтения RFID меток (регистры, функции для работы) реализованы в модуле конфигурации. В нем же хранится конфигурация Telegram бота (token). После считывания RFID метки модуль чтения обращается к модулю фото. В ответ получает фото пользователя, которое направляется в модуль отправки сообщений для отправки оператору в Telegram вместе с информацией о пользователе.

Раз уж мы решили использовать OpenCV для распознавания лиц, то осуществлять захват изображения с камеры тоже будем с её помощью. OpenCV ставится на Raspberry Pi ровно также как и на любую другую Linux-машину. Описывать процесс её установки в рамках топика не вижу смысла. Мануал по установке есть на официальном сайте, просто повторяем шаги и всё.

Далее будет описана реализация основного функционала. А полный код проекта будет доступен по ссылке в конце статьи.

Опрос RFID считывателя происходит в бесконечном цикле вида:

while continue_reading:
  (status,TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL) # Опрашиваем RFID считыватель
  if status == MIFAREReader.MI_OK: # Если обнаружена карта
    print "Card detected" 
  (status,backData) = MIFAREReader.MFRC522_Anticoll()
  if status == MIFAREReader.MI_OK: 
    print "Card read UID: "+str(backData[0])+","+str(backData[1])+","+str(backData[2])+","+str(backData[3])+","+str(backData[4])
    if (( backData == cardA ) or ( backData == cardB ) or ( backData == cardC )): # Сравниваем для примера с тремя захардкоженными идентификаторами трёх билетиков московского метро
      print "welcome"
      ### Получаем снимок с камеры через OpenCv ###
      capture = cv.CaptureFromCAM(0)
      frame = cv.QueryFrame(capture)
      cv.SaveImage("../../../Camera/telegram/image/ny.jpg", frame)
      del(capture)
      ### ####
      ### Запись файла с информацией о пользователе ####
      f1 = open("../../../Camera/telegram/text1.txt", 'wb')
      f1.write("The")
      if ( backData == cardB ):
          f1.write("User with cardB is comming")
      elif ( backData == cardA ):
          f1.write("User whith cardA is comming")
      ### ####
      # запуск отправки в Телеграм     
      os.system('python3 telegram.py') 
    else:
      print "wrong Card"

Я постарался максимально закомментировать код дабы исключить пояснения в основном тексте статьи. С остальными фрагментами кода буду поступать аналогично.

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

Требуемый нам функционал реализуем так:

### Отправка текcтовой информации ###
def mes ():
        f = open('../../../Camera/telegram/text1.txt')
        bot.send_message(<тут ваш идентификатор>, f.read())
        return 0
### Отправка фото ###
def photo ():
        photo = open('../../../Camera/telegram/image/ny.jpg', 'rb')
        bot.send_photo(<тут ваш идентификатор>, photo)
        return 0
mes()
photo()

Вместо <тут ваш идентификатор> вписываем идентификатор абонента, которому отсылаем сообщение.

Осталось реализовать ответы бота на сообщения. Для этого надо создать обработчики соответствующих команд /photo и /text:

### Обработка команды /text ###
@bot.message_handler(commands=['text'])
def mes (message):
        f = open('../../../Camera/telegram/text1.txt') # файл с информацией, который сохраняли ранее
        bot.send_message(message.chat.id, f.read()) # отправка
        return 0
### Обработка команды /photo ###
@bot.message_handler(commands=['photo'])
def photo (message):
        photo = open('../../../Camera/telegram/image/ny.jpg', 'rb') # фото, которое сохраняли ранее
        print(message.chat.id)
        bot.send_photo(message.chat.id, photo) # отправка

Реализацию основных частей рассмотрели.

3. Макет

На основании п.1 и п.2 был разработан макет устройства, представленный на фото ниже. В качестве RFID карт использовались билеты для проезда в Московском метрополитене.

К Raspberry Pi подключен RFID считыватель по интерфейсу SPI согласно таблице представленной ниже. WEB-камера подключается к USB-порту, расположенному на плате. Взаимодействие с сетью (API сервера Telegram) осуществляется через Ethernet порт.

Таблица подключения RFID считывателя RC522 к Raspberry Pi

RPi пин	RC522 пин

1	Vcc
6	GND
19	MOSI
21	MISO
22	RST
23	SCK
24	NSS

На этом статья подходит в концу. Полный код проекта доступен в моем репозитории на github . Не забываем вписывать ваш токен для Telegram-бота в файле config.py, а также вписывать свой идентификатор абонента, которому надо посылать фото и информацию.

P.S.

Статья написана для участия в конкурсе т.к. своей Rasberry Pi не имею. Для реализации этого проекта взял у друга на пару месяцев первую Raspberry.

Да, разработка - процесс неспешный. Тем более, что проектом занимаюсь исключительно в свободное время.

Тэги:

 

Автор:

Комментариев: 1

  • PavelLos
    24.10.2018 в 19:28 ответ

    Здравствуйте!  Есть аналогичный вашему проект, может Вы сталкивались со следующей ситуацией:   Платформа – Raspberry Pi 3 , OS Raspbian с графической оболочкой. Скрипт написан на Python 2.7 – Read_sim_QQ.py ( https://github.com/PaulLos/RPi-QQ.git ) Данная программа считывает данные с бесконтактной карты через RFID считыватель подключенный к GPIO через SPI. Аналогично вот этому примеру - https://www.raspberrypi-spy.co.uk/2018/02/rc522-rfid-tag-read-raspberry-pi/ В чикле считывания программа передает данные карты на наш сервер.   Проблема в следующем:   При запуске скрипта командой из терминального окна запуск программы происходит не всегда корректно, а именно программа стартует, но считывание не всегда начинается. Было замечено, что если после включения или рестарта системы проходит достаточно большое время более 5 минут, то скрипт работает стабильно, но если запустить программу сразу после старта системы, например через минуту, то скрипт работает не корректно, но если его прервать CTL>C и запустить заново, то все начинает работать корректно. И далее можно неоднократно останавливать  и запускать данное ПО - все работает.   Проблема обнаружилась, когда я добавил запуск в файл автостарта при запуске системы.  Спасибо.

Ваш комментарий

Авторизуйтесь для отправки комментария

© Сообщество пользователей RaspberryPi 2021