Iām trying to create an application to recognize any of the known faces from a video stream. I have a directory ātraining_imagesā which contains one image for each known face. Iām following the example code given by you and slightly modified it to add multiple known faces.
In the response of face_recognition .compare_faces(), I was expecting a list of matched results, containing a set of 128 boolean values for each training image. Instead of that it returns only one set of 128 boolean values. While which training_image_encoding was matched is still unknown.
Can you help me, where Iām doing wrong?
import face_recognition
import cv2
import numpy
import os
video_capture = cv2.VideoCapture(0)
files= os.listdir("training_images")
print files
training_face_encoding=[]
for file in files:
print file
training_image = face_recognition.load_image_file('training_images/'+file)
training_face_encoding.append(face_recognition.face_encodings(training_image)[0])
face_locations = []
face_encodings = []
face_names = []
process_this_frame = True
i =0
while True:
ret, frame = video_capture.read()
frame=cv2.flip(frame,1)
small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
if i < 4:
process_this_frame=False
i +=1
else:
i=0
if process_this_frame:
face_locations = face_recognition.face_locations(small_frame)
face_encodings = face_recognition.face_encodings(small_frame, face_locations)
face_names = []
for face_encoding in face_encodings:
match = face_recognition.compare_faces([training_face_encoding], face_encoding)
name = "Unknown"
print match[0]
print files
i =0
for m in match[0]:
# print m
# print i
if m.all():
name = files[i]
face_names.append(name)
i +=1
process_this_frame = not process_this_frame
for (top, right, bottom, left), name in zip(face_locations, face_names):
top *= 4
right *= 4
bottom *= 4
left *= 4
cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
cv2.imshow('Video', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
cv2.destroyAllWindows()
The application should read all training images from "training_images" directory, then match each frame of video stream to these images and in the end tell the name of most appropriately matched image file.
It will be more suitable if I can add multiple images of same person and application tells the name of the person in video frame.
Instead of that it returns only one set of 128 boolean values.
Isn't this what it should be? Each boolean value, match[i], says if training_face_encoding[i] is within the threshold (default=0.6) of face_encoding.
face_recognition.compare_faces([training_face_encoding], face_encoding)
This should just be face_recognition.compare_faces(training_face_encoding, face_encoding). If you were just copying the example, the obama_face_encoding is a lone encoding and needed to be placed in a list for the function, you don't have to do that.
With that change you should just be able to iterate over match looking for the True values.
Here's a fixed version of your code. However I only tested it in Python 3 (not Python 2):
import face_recognition
import cv2
import numpy
import os
video_capture = cv2.VideoCapture(0)
files = os.listdir("training_images")
print(files)
training_face_encoding=[]
for file in files:
print(file)
training_image = face_recognition.load_image_file('training_images/'+file)
training_face_encoding.append(face_recognition.face_encodings(training_image)[0])
face_locations = []
face_encodings = []
face_names = []
process_this_frame = True
i = 0
while True:
ret, frame = video_capture.read()
frame=cv2.flip(frame, 1)
small_frame = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
if i < 4:
process_this_frame=False
i += 1
else:
i = 0
if process_this_frame:
face_locations = face_recognition.face_locations(small_frame)
face_encodings = face_recognition.face_encodings(small_frame, face_locations)
face_names = []
for face_encoding in face_encodings:
match = face_recognition.compare_faces(training_face_encoding, face_encoding)
name = "Unknown"
print(match)
print(files)
i = 0
for m in match:
if m:
name = files[i]
i += 1
face_names.append(name)
process_this_frame = not process_this_frame
for (top, right, bottom, left), name in zip(face_locations, face_names):
top *= 4
right *= 4
bottom *= 4
left *= 4
cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
cv2.imshow('Video', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
cv2.destroyAllWindows()
Output:
$ python3 test.py
['Adam.jpg', 'biden.jpg', 'obama.jpg', 'obama2.jpg', 'obama_small.jpg']
Adam.jpg
biden.jpg
obama.jpg
obama2.jpg
obama_small.jpg
[True, False, False, False, False]
['Adam.jpg', 'biden.jpg', 'obama.jpg', 'obama2.jpg', 'obama_small.jpg']
The biggest issue was that you are were accidentally passing in an array of an array to face_recognition.compare_faces() instead of just passing in a normal array like @hellopatrick said.
Thank you for this wonderful model.
I am using
face_recognition version:
Python version: 2.7.5
Operating System: ubuntu(16.04)
I had collected few faces and created my dataset .
Does the accuracy of recognizing people reduce if we increase the size of the dataset by any chance?
@31893 No, the accuracy isn't based on the number of photos you are testing against (if I understand your question correctly)