Распознавание лица в OpenCV. Python.

Про поиск лиц на фото или в видеопотоке мы уже писали. Теперь давайте займемся распознаванием с помощью библиотеки OpenCV.

Данна задача делиться на две части:

  • Создание базы лица для обучения.
  • Обучение распознавания лиц с помощью OpenCV Recognizer.

База данных.

Что бы распознать лицо надо собрать базу этого лица и обучить алгоритм. Для простоты эксперимента мы напишем код который будет искать лицо в видеопотоке с веб-камеры и сохранять его в папку /face . Скажем наберем 30 штук для начала:

import cv2
import os
cam = cv2.VideoCapture(0)
face_detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
# Вводим id лица которое добавляется в имя и потом будет использовать в распознавание.
face_id = input('\n enter user id end press  ==>  ')
print("\n [INFO] Initializing face capture. Look the camera and wait …")
count = 0
while(True):
     ret, img = cam.read()  
     gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
     faces = face_detector.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)
          count += 1     
          # Сохраняем лицо
          cv2.imwrite('face/user.' + str(face_id) + '.' + str(count) + '.jpg', gray[y:y+h,x:x+w])
     cv2.imshow('image', img) k = cv2.waitKey(100) & 0xff #  'ESC'  
     if k == 27:
         break 
     elif count >= 30: # Если сохранили 30 изображений выход.
         break
 print("\n [INFO] Exiting Program and cleanup stuff")
 cam.release()
 cv2.destroyAllWindows()

Обучение…

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

Создаем объект FaceRecognizer . Алгоритм обучения LBPH ( Histograms Local Binary Patterns ). Если честно я не очень разобрался что это за алгоритм и т.д. Документация OpenCV очень муторная. Если есть у кого хорошая ссылка пишите в комментах )))

import cv2
import numpy as np
import os

recognizer = cv2.face.LBPHFaceRecognizer_create()

Теперь мы открываем все картинки и передаем их в тренер:

 def getImagesAndLabels(path):
    # Создаем список файлов в папке patch
    imagePaths = [os.path.join(path,f) for f in os.listdir(path)]
    face=[] # Тут храним масив картинок
    ids = [] # Храним id лица
    for imagePath in imagePaths:
        img = cv2.imread(imagePath)
        # Переводим изображение в серый, тренер понимает только одноканальное изображение
        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        face.append(img)
        # Получаем id из названия
        id = int(os.path.split(imagePath)[-1].split(".")[1])
        ids.append(id)
    return face,ids 
faces,ids = getImagesAndLabels(path)
# Тренируем train(данные, id)
recognizer.train(faces, np.array(ids))
# Сохраняем результат
recognizer.write('face.yml')

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

Итог…

Все вроде готов, давайте распознавать. Алгоритм тут достаточно просто : Ищем лицо — распознаем — рисуем рамку и пишем id или unknown.

С начало нам надо загрузить наш файл индификации, как с признаками для поиска лица :

recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('face/face.yml')

Для распознания используем метод predict(массив картинки) который вернет два параметра: идентификатор и степень достоверности. Обратите внимание, что степень достоверности вернет «zero», если будет достигнут идеальный результат.

import cv2
import numpy as np
import os

recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('face/face.yml')
cascadePath = "haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(cascadePath);
# Тип шрифта
font = cv2.FONT_HERSHEY_SIMPLEX

# iniciate id counter
id = 0

# Список имен для id
names = ['None', 'Keanu  Reeves']

cam = cv2.VideoCapture(0)
cam.set(3, 640)  # set video width
cam.set(4, 480)  # set video height

while True:
    ret, img = cam.read()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    faces = faceCascade.detectMultiScale(
        gray,
        scaleFactor=1.2,
        minNeighbors=5,
        minSize=(10, 10),
    )

    for (x, y, w, h) in faces:
        cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
        id, confidence = recognizer.predict(gray[y:y + h, x:x + w])

        # Проверяем что лицо распознано
        if (confidence < 100):
            id = names[id]
            confidence = "  {0}%".format(round(100 - confidence))
        else:
            id = "unknown"
            confidence = "  {0}%".format(round(100 - confidence))

        cv2.putText(img, str(id), (x + 5, y - 5), font, 1, (255, 255, 255), 2)
        cv2.putText(img, str(confidence), (x + 5, y + h - 5), font, 1, (255, 255, 0), 1)

    cv2.imshow('camera', img)

    k = cv2.waitKey(10) & 0xff  # 'ESC' для Выхода
    if k == 27:
        break

cam.release()
cv2.destroyAllWindows()