Этот проект был выполнен с помощью этой фантастической Библиотеки компьютерного зрения с открытым исходным кодом, OpenCV. В этом руководстве мы сосредоточимся на Raspberry Pi (то есть Raspbian в качестве ОС) и Python, но я также протестировал код в своих окнах, и он также отлично работает. OpenCV был разработан для вычислительной эффективности и с упором на приложения реального времени. Таким образом, он идеально подходит для распознавания лиц в реальном времени с помощью камеры.

Чтобы создать законченный проект по распознаванию лиц, мы должны работать над 3 очень разными фазами:

  1. Обнаружение лиц и сбор данных
  2. Обучить распознаватель
  3. Распознавание лица

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

Я предполагаю, что в вашей системе уже установлена ​​веб-камера.

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

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

Шаг 1. Сбор данных

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

Создайте подкаталог, в котором мы будем хранить образцы наших лиц, и назовите его «набор данных»:

import cv2
import os

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

face_detector = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

# For each person, enter one numeric face id
face_id = input('\n enter user id end press <return> ==>  ')

print("\n [INFO] Initializing face capture. Look the camera and wait ...")
# Initialize individual sampling face count
count = 0

while(True):
    ret, img = cam.read()
    img = cv2.flip(img, -1) # flip video image vertically
    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

        # Save the captured image into the datasets folder
        cv2.imwrite("dataset/User." + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+h,x:x+w])

        cv2.imshow('image', img)

    k = cv2.waitKey(100) & 0xff # Press 'ESC' for exiting video
    if k == 27:
        break
    elif count >= 30: # Take 30 face sample and stop video
         break

# Do a bit of cleanup
print("\n [INFO] Exiting Program and cleanup stuff")
cam.release()
cv2.destroyAllWindows()

Код очень похож на код, который мы видели для распознавания лиц. Мы добавили «команду ввода» для захвата идентификатора пользователя, который должен быть целым числом (1, 2, 3 и т. Д.).

face_id = input('\n enter user id end press  ==>  ')

И для каждого из захваченных кадров мы должны сохранить его как файл в каталоге «набора данных»:

cv2.imwrite("dataset/User." + str(face_id) + '.' + str(count) + ".jpg", gray[y:y+h,x:x+w])

Например, для пользователя с face_id = 1 четвертый образец файла в каталоге dataset / будет выглядеть примерно так:

User.1.4.jpg

Вы должны запускать сценарий каждый раз, когда хотите объединить нового пользователя (или изменить фотографии для уже существующего).

Шаг 2: Создание Trainer.yml

Мы должны взять все пользовательские данные из нашего набора данных и «обучить» OpenCV Recognizer. Это делается напрямую с помощью конкретной функции OpenCV. Результатом будет файл .yml, который будет сохранен в каталоге «trainer /».

import cv2
import numpy as np
from PIL import Image
import os

# Path for face image database
path = 'dataset'

recognizer = cv2.face.LBPHFaceRecognizer_create()
detector = cv2.CascadeClassifier("haarcascade_frontalface_default.xml");

# function to get the images and label data
def getImagesAndLabels(path):
    imagePaths = [os.path.join(path,f) for f in os.listdir(path)]     
    faceSamples=[]
    ids = []
    for imagePath in imagePaths:
        PIL_img = Image.open(imagePath).convert('L') # convert it to grayscale
        img_numpy = np.array(PIL_img,'uint8')
        id = int(os.path.split(imagePath)[-1].split(".")[1])
        faces = detector.detectMultiScale(img_numpy)
        for (x,y,w,h) in faces:
            faceSamples.append(img_numpy[y:y+h,x:x+w])
            ids.append(id)
    return faceSamples,ids

print ("\n [INFO] Training faces. It will take a few seconds. Wait ...")
faces,ids = getImagesAndLabels(path)
recognizer.train(faces, np.array(ids))

# Save the model into trainer/trainer.yml
recognizer.write('trainer/trainer.yml') # recognizer.save() worked on Mac, but not on Pi

# Print the numer of faces trained and end program
print("\n [INFO] {0} faces trained. Exiting Program".format(len(np.unique(ids))))

В качестве распознавателя мы будем использовать распознаватель лиц LBPH (LOCAL BINARY PATTERNS HISTOGRAMS), включенный в пакет OpenCV. Делаем это в следующей строке:

recognizer = cv2.face.LBPHFaceRecognizer_create()

Функция getImagesAndLabels (path) возьмет все фотографии в каталоге: «dataset /», вернув 2 массива: «Ids» и «faces». Используя эти массивы в качестве входных данных, мы «обучим наш распознаватель».

В результате файл с именем «trainer.yml» будет сохранен в каталоге трейнера, который был ранее создан нами.

Шаг 3: распознаватель

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

import cv2
import numpy as np
import os 

recognizer = cv2.face.LBPHFaceRecognizer_create()
recognizer.read('trainer/trainer.yml')
cascadePath = "haarcascade_frontalface_default.xml"
faceCascade = cv2.CascadeClassifier(cascadePath);

font = cv2.FONT_HERSHEY_SIMPLEX

#iniciate id counter
id = 0

# names related to ids: example ==> Marcelo: id=1,  etc
names = ['None', 'Marcelo', 'Paula', 'Ilza', 'Z', 'W'] 

# Initialize and start realtime video capture
cam = cv2.VideoCapture(0)
cam.set(3, 640) # set video widht
cam.set(4, 480) # set video height

# Define min window size to be recognized as a face
minW = 0.1*cam.get(3)
minH = 0.1*cam.get(4)

while True:
    ret, img =cam.read()
    img = cv2.flip(img, -1) # Flip vertically
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    
    faces = faceCascade.detectMultiScale( 
        gray,
        scaleFactor = 1.2,
        minNeighbors = 5,
        minSize = (int(minW), int(minH)),
       )

    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])

        # Check if confidence is less them 100 ==> "0" is match 
        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 # Press 'ESC' for exiting video
    if k == 27:
        break

# Do a bit of cleanup
print("\n [INFO] Exiting Program and cleanup stuff")
cam.release()
cv2.destroyAllWindows()

Мы включаем сюда новый массив, поэтому мы будем отображать «имена» вместо пронумерованных идентификаторов:

names = ['None', 'Devi', 'Gopinath', 'Jayalalitha', 'Z', 'W']

Так, например: Devi будет пользователем с id = 1; Гопинатх: id = 2 и т. Д.

Затем мы обнаружим лицо, как мы делали это раньше с классификатором haarCascade. Обнаружив лицо, мы можем вызвать самую важную функцию в приведенном выше коде:

id, confidence = recognizer.predict(gray portion of the face)

Распознаватель.predict () примет в качестве параметра захваченную часть лица для анализа и вернет его вероятного владельца, указав его идентификатор и степень уверенности распознавателя в отношении этого совпадения.

Обратите внимание, что индекс достоверности вернет «ноль», если он будет сочтен идеальным совпадением

И, наконец, если распознаватель мог предсказать лицо, мы помещаем текст поверх изображения с вероятным идентификатором и какой «вероятностью» в% того, что совпадение будет правильным («вероятность» = 100 - индекс достоверности). В противном случае на лицо ставится метка «неизвестно».

Для получения подробной информации и окончательного кода посетите мой репозиторий GitHub: www.github.com/@gopinath2018

Спасибо за чтение.

Гопинатх С