-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrecognize.py
More file actions
107 lines (96 loc) · 5.1 KB
/
recognize.py
File metadata and controls
107 lines (96 loc) · 5.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import dlib
import scipy.misc
import numpy as np
import os
import cv2
# Get Face Detector from dlib
# This allows us to detect faces in images
face_detector = dlib.get_frontal_face_detector()
# Get Pose Predictor from dlib
# This allows us to detect landmark points in faces and understand the pose/angle of the face
shape_predictor = dlib.shape_predictor("model/shape_predictor_68_face_landmarks.dat")
# Get the face recognition model
# This is what gives us the face encodings (numbers that identify the face of a particular person)
face_recognition_model = dlib.face_recognition_model_v1(
"model/dlib_face_recognition_resnet_model_v1.dat"
)
# This is the tolerance for face comparisons
# The lower the number - the stricter the comparison
# To avoid false matches, use lower value
# To avoid false negatives (i.e. faces of the same person doesn't match), use higher value
# 0.5-0.6 works well
TOLERANCE = 0.6
# This function will take an image and return its face encodings using the neural network
def get_face_encodings(path_to_image):
# Load image using scipy
image = cv2.imread(path_to_image)
# Detect faces using the face detector
detected_faces = face_detector(image, 1)
# Get pose/landmarks of those faces
# Will be used as an input to the function that computes face encodings
# This allows the neural network to be able to produce similar numbers for faces of the same people, regardless of camera angle and/or face positioning in the image
shapes_faces = [shape_predictor(image, face) for face in detected_faces]
# For every face detected, compute the face encodings
return [np.array(face_recognition_model.compute_face_descriptor(image, face_pose, 1)) for face_pose in shapes_faces]
# This function takes a list of known faces
def compare_face_encodings(known_faces, face):
# Finds the difference between each known face and the given face (that we are comparing)
# Calculate norm for the differences with each known face
# Return an array with True/Face values based on whether or not a known face matched with the given face
# A match occurs when the (norm) difference between a known face and the given face is less than or equal to the TOLERANCE value
return (np.linalg.norm(known_faces - face, axis=1) <= TOLERANCE)
# This function returns the name of the person whose image matches with the given face (or 'Not Found')
# known_faces is a list of face encodings
# names is a list of the names of people (in the same order as the face encodings - to match the name with an encoding)
# face is the face we are looking for
def find_match(known_faces, names, face):
# Call compare_face_encodings to get a list of True/False values indicating whether or not there's a match
matches = compare_face_encodings(known_faces, face)
# Return the name of the first match
count = 0
for match in matches:
if match:
print(names[count])
#return names[count]
count += 1
# Return not found if no match found
return 'Not Found'
# Get path to all the known images
# Filtering on .jpg extension - so this will only work with JPEG images ending with .jpg
image_filenames = filter(lambda x: x.endswith('.jpg'), os.listdir('photos/'))
# Sort in alphabetical order
image_filenames = sorted(image_filenames)
# Get full paths to images
paths_to_images = ['photos/' + x for x in image_filenames]
# List of face encodings we have
face_encodings = []
# Loop over images to get the encoding one by one
for path_to_image in paths_to_images:
# Get face encodings from the image
face_encodings_in_image = get_face_encodings(path_to_image)
# Make sure there's exactly one face in the image
if len(face_encodings_in_image) != 1:
print("Please change image: " + path_to_image + " - it has " + str(len(face_encodings_in_image)) + " faces; it can only have one")
exit()
# Append the face encoding found in that image to the list of face encodings we have
face_encodings.append(get_face_encodings(path_to_image)[0])
# Get path to all the test images
# Filtering on .jpg extension - so this will only work with JPEG images ending with .jpg
# test_filenames = filter(lambda x: x.endswith('.jpg'), os.listdir('find/'))
test_filenames = os.listdir('find/')
# Get full paths to test images
paths_to_test_images = ['find/' + x for x in test_filenames]
# Get list of names of people by eliminating the .JPG extension from image filenames
names = [x[:-4] for x in image_filenames]
# Iterate over test images to find match one by one
for path_to_image in paths_to_test_images:
# Get face encodings from the test image
face_encodings_in_image = get_face_encodings(path_to_image)
# Make sure there's exactly one face in the image
if len(face_encodings_in_image) != 1:
print("Please change image: " + path_to_image + " - it has " + str(len(face_encodings_in_image)) + " faces; it can only have one")
exit()
# Find match for the face encoding found in this test image
match = find_match(face_encodings, names, face_encodings_in_image[0])
# Print the path of test image and the corresponding match
print(path_to_image, match)