Замок с распознаванием лиц на Orange Pi с OpenCV и Python

Требуется взять видео поток с камеры, идентифицировать человека по лицу, открыть замок если этому человеку предоставлен доступ. Видео поток будем брать с вебки, распознавать лицо с помощью OpenCV. Системник на дверь вешать не будем. Orange Pi вполне справиться.

Устанавливаем OpenCV на Orange Pi

Приведенные ниже инструкции, думаю, будут работать на Raspberry Pi, но в ответственный момент его под рукой не оказалось, поэтому все ниже описанное я тестировал на Orange Pi. Что касается программного обеспечения, мы будем использовать OpenCV, который представляет собой компьютерное зрение и компьютерное обучение в режиме реального времени. Это позволит нам захватывать изображения с веб-камеры, манипулировать ими и применять модели распознавания лиц.

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

sudo apt-get install build-essential
sudo apt-get install cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev
sudo apt-get install python-dev python-numpy libtbb2 libtbb-dev libjpeg-dev libpng-dev libtiff-dev libjasper-dev libdc1394-22-dev

Затем получите OpenCV и дополнительные модули, содержащие библиотеки распознавания лиц:

wget -O opencv-3.3.0.zip https://github.com/opencv/opencv/archive/3.3.0.zip
git clone https://github.com/opencv/opencv_contrib.git
unzip opencv-3.3.0.zip
cd opencv-3.3.0

Создайте каталог сборки:

mkdir build
cd build

Команду для сборки, я брал из руководства для Raspberry Pi, к которой добавил вариант включения дополнительных модулей с функциями распознавания лиц:

cmake -D WITH_FFMPEG=OFF -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D OPENCV_EXTRA_MODULES_PATH=<path to opencv_contrib/modules/> -D BUILD_NEW_PYTHON_SUPPORT=ON -D INSTALL_C_EXAMPLES=ON -D INSTALL_PYTHON_EXAMPLES=ON -D BUILD_EXAMPLES=ON ..

компилируем

make -j4

Этот шаг, на моем устройстве, занял около 1 часа. Если вы получите какую-либо ошибку из дополнительных модулей, просто удалите их. Вам нужен только модуль лица. Далее ставим OpenCV:

sudo make install

Готово. Теперь у вас есть OpenCV в Python на Orange Pi с библиотеками распознавания лиц. Вы можете протестировать его, запустив Python и импортировав cv2.

Захват видео потока с веб-камеры и распознавание лиц

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

Чтобы прочитать поток веб-камеры и сохранить лица, соответствующие человеку, используйте приведенный ниже код. Убедитесь, что у вас есть каскадный файл обнаружения лица XML. Эти каскадные файлы XML обычно лежат в opencv /data/haarcascades/. Скопируйте нужный файл в ту же папку, что и скрипт, или поместите весь put в функцию cv2.CascadeClassifier().

import os
import numpy as np
import cv2
 
# create folder to save pictures of a person
name=raw_input('Enter your name:')
if not os.path.exists('faces'):
    os.mkdir('faces' )
os.mkdir('faces/'+name )
print name+' folder created!'
path='faces/'+name
 
# import face detection cascade
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
 
# create capture object
cap = cv2.VideoCapture(0)
 
# take 10 pictures
for i in range(1,11):
    print ('Take picture '+str(i) + ' and press space') 
    while(True):
        # capture frame-by-frame
        ret, img = cap.read()
 
        # convert image to grayscale
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
 
        # detect face
        faces = face_cascade.detectMultiScale(gray, 1.3, 5)
 
        # for each face draw a rectangle around and copy the face
        for (x,y,w,h) in faces:
            cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
            roi_color = img[y:y+h, x:x+w]
            roi_gray = gray[y:y+h, x:x+w]
 
        # display the resulting frame
        cv2.imshow('frame',img)   
 
        # when pressing space resize face image and save it
        if cv2.waitKey(1) & 0xFF == ord(' '):
            roi_gray=cv2.resize(roi_gray,(100,100))
            cv2.imwrite(path+'/'+str(i)+'.jpg',roi_gray)
            break
     
# when everything done, release the capture
cap.release()
cv2.destroyAllWindows()

Сохраните код выше в сценарии Python input.py. Подключите веб-камеру к Orange Pi и запустите сценарий. Введите свое имя и посмотрите на камеру, нажимая пробел каждый раз, когда вокруг вашего лица появляется прямоугольник. Вы должны сделать 10 снимков, которые будут сохранены в faces/folder.

Чтобы проверить модель, сохраните код ниже в файл output.py. Код создает список лиц (объектов изображений) и ярлыков, что и требует учебная модель. Это делается путем просмотра папок и файлов в каталоге faces/, созданных предыдущим скриптом. Затем мы обучаем модель.

import cv2
import numpy as np
import os
 
faces = []
labels = []
 
path_data='faces/'
 
names=os.listdir(path_data)
i=-1
 
# read each image in the faces folder
for root, dirs, files in os.walk(path_data):
    i=i+1
    # for the recognizer we need an array of images and corresponding labels
    for name in files:
        faces.append(cv2.imread(root+'/'+name,cv2.IMREAD_GRAYSCALE))
        labels.append(i)
 
# create our LBPH face recognizer 
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
 
# import face detection cascade
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
 
# train model
face_recognizer.train(faces, np.array(labels))
 
cap = cv2.VideoCapture(0)
while(True):
    # capture frame-by-frame
    ret, img = cap.read()
 
    # put a rectangle and a label for each recognized face
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.3, 5)
    for (x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
        roi_color = img[y:y+h, x:x+w]
        roi_gray = gray[y:y+h, x:x+w]
        label= face_recognizer.predict(roi_gray)
        cv2.putText(img, names[label[0]-1]+' ts:'+str(label[1]), (x, y), cv2.FONT_HERSHEY_PLAIN, 1.5, (0, 255, 0), 2)
    # display the resulting frame
    cv2.imshow('frame',img)   
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
     
# when everything done, release the capture
cap.release()
cv2.destroyAllWindows()

Чтобы закрыть поток, нажмите клавишу q

Вот и все. Осталось только отправить сигнал на реле для открывания замка.

Распознавания лиц с использованием каскадных классификаторов Хаара

Теория

Обнаружение объектов с использованием каскадных классификаторов Хаара — эффективный метод обнаружения объектов, работающий в реальном времени. Это подход, основанный на механизме обучения. Каскадная функция обучается из множества положительных и отрицательных изображений.

Первоначально алгоритм требует много положительных изображений (изображений лиц) и негативных изображений (изображений без лиц) для обучения классификатора. Затем нам нужно извлечь из него функции. Для этого используются хаарные функции.

Функции применяются на всех обучающих изображениях. Для каждой функции находится лучший порог, который будет относить лица к положительным и отрицательным. Очевидно, что будут ошибки. Мы выбираем функции с минимальной частотой ошибок, которые лучше всего классифицируют изображения лица. Процесс не так прост, как это кажется. Каждому изображению присваивается одинаковый вес в начале. После каждой классификации увеличивается количество ошибочных изображений. Затем снова выполняется тот же процесс, рассчитываются новые коэффициенты ошибок, а также новые веса. Процесс продолжается до тех пор, пока не будет достигнута требуемая точность или частота ошибок.

Конечный классификатор представляет собой взвешенную сумму слабых классификаторов. Слабым классификатор называется, потому что он сам по себе не может классифицировать изображение, но вместе с другими образует сильный классификатор. 200 функций обеспечивают обнаружение с точностью до 95%. Окончательная настройка имеет около 6000 функций.

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

Каскада Хаара в OpenCV

Обучить классификатор можно не только на распознование лиц но и других объектов, таких как автомобиль, самолет и т.д. Для этого Вы можете использовать OpenCV.

OpenCV уже содержит много предварительно подготовленных классификаторов для лица, глаз, улыбки и т.д. Эти файлы XML хранятся в opencv/data/haarcascades/. Давайте создадим детектор лица и глаза с OpenCV.

Сначала нам нужно загрузить требуемые классификаторы XML. Затем загрузите наше входное изображение (или видео).

import numpy as np
import cv2

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')

img = cv2.imread(lico.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

Теперь мы находим грани в изображении. Если грани найдены, они возвращают позиции обнаруженных лиц как Rect (x, y, w, h). Так как на лице всегда есть глаза, будем искать глаза. Как только мы получим регионы лиц, мы можем создать ROI для лица и применить обнаружение глаз в этой ROI.

faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x,y,w,h) in faces:
   img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
   roi_gray = gray[y:y+h, x:x+w]
   roi_color = img[y:y+h, x:x+w]
   eyes = eye_cascade.detectMultiScale(roi_gray)
   for (ex,ey,ew,eh) in eyes:
       cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)

cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Результат выглядит так: