Переглянути джерело

face alignment classifier

kevin 2 роки тому
батько
коміт
ef54577ff2
4 змінених файлів з 207 додано та 20 видалено
  1. 92 0
      face_align.py
  2. 39 20
      face_recognition_svm.py
  3. 11 0
      requirements.txt
  4. 65 0
      verify_face.py

+ 92 - 0
face_align.py

@@ -0,0 +1,92 @@
+import face_alignment
+from skimage import io
+import joblib
+import os
+from sklearn import svm
+import concurrent.futures
+import numpy as np
+import time
+
+fa = face_alignment.FaceAlignment(face_alignment.LandmarksType._2D, flip_input=False)
+
+# Training the SVC classifier
+
+# The training data would be all the face encodings from all the known images and the labels are their names
+encodings = []
+names = []
+tuples = []
+train_list = []
+lock = None
+
+is_train = False
+
+if not is_train:
+    try:
+        clf = joblib.load('saved_model_fa.pkl')
+    except:
+        clf = None
+    if clf is None:
+        is_train = True
+
+def train_image(image, person):
+    img = io.imread(image)
+    preds = fa.get_landmarks(img)
+
+    # If training image contains exactly one face
+    if len(preds) == 1:
+        tuples.append((preds[0].reshape(136), person))
+    else:
+        print(image + " was skipped and can't be used for training")
+
+if is_train:
+    # Training directory
+    train_str = os.path.join('data', 'peeps', 'anchor')
+    train_dir = os.listdir(os.path.join('data', 'peeps', 'anchor'))
+
+    # Loop through each person in the training directory
+    with concurrent.futures.ThreadPoolExecutor() as executor:
+        for person in train_dir:
+            pix_str = os.path.join(train_str, person)
+            pix = os.listdir(os.path.join(train_str, person))
+
+            # Loop through each training image for the current person
+            for person_img in pix:
+                # Get the face encodings for the face in each image file
+                image = os.path.join(pix_str, person_img)
+                executor.submit(train_image, image, person)
+
+    # Create and train the SVC classifier
+
+    encodings = [x for x, _ in tuples]
+    names = [y for _, y in tuples]
+
+    clf = svm.SVC(gamma='scale', probability=True)
+    clf.fit(encodings, names)
+    joblib.dump(clf, 'saved_model_fa.pkl')
+
+# Load the test image with unknown faces into a numpy array
+test_image = io.imread(os.path.join('application_data', 'input_image', 'input_image4.jpg'))
+
+# Find all the faces in the test image using the default HOG-based model
+face_locations = fa.get_landmarks(test_image)
+no = len(face_locations)
+print("Number of faces detected: ", no)
+
+# Predict all the faces in the test image using the trained classifier
+print("Found:")
+for i in range(no):
+    test_image_enc = face_locations[i].reshape(136)
+    start_time = time.perf_counter_ns()
+    proba = clf.predict_proba([test_image_enc])
+    end_time = time.perf_counter_ns()
+    process_time = end_time - start_time
+    classes = clf.classes_
+    print(classes)
+    i = np.argmax(proba)
+    proba = list(*proba)
+    name = classes[i]
+    print(name, "{:.2f}".format(proba[i]), proba, process_time)
+
+# input = io.imread(os.path.join('application_data','input_image','input_image.jpg'))
+# preds = fa.get_landmarks(input)
+# print(preds)

+ 39 - 20
face_recognition_svm.py

@@ -2,13 +2,18 @@ import face_recognition
 from sklearn import svm
 import joblib
 import os
+import concurrent.futures
+import numpy as np
+import time
 
 # Training the SVC classifier
 
 # The training data would be all the face encodings from all the known images and the labels are their names
 encodings = []
 names = []
+tuples = []
 train_list = []
+lock = None
 
 is_train = False
 
@@ -20,39 +25,46 @@ if not is_train:
     if clf is None:
         is_train = True
 
+def train_image(image, person):
+    face = face_recognition.load_image_file(image)
+    face_bounding_boxes = face_recognition.face_locations(face)
+
+    # If training image contains exactly one face
+    if len(face_bounding_boxes) == 1:
+        face_enc = face_recognition.face_encodings(face)[0]
+        # Add face encoding for current image with corresponding label (name) to the training data
+        tuples.append((face_enc, person))
+    else:
+        print(image + " was skipped and can't be used for training")
+
 if is_train:
     # Training directory
     train_str = os.path.join('data', 'peeps', 'anchor')
     train_dir = os.listdir(os.path.join('data', 'peeps', 'anchor'))
 
     # Loop through each person in the training directory
-    for person in train_dir:
-        pix_str = os.path.join(train_str, person)
-        pix = os.listdir(os.path.join(train_str, person))
+    with concurrent.futures.ThreadPoolExecutor() as executor:
+        for person in train_dir:
+            pix_str = os.path.join(train_str, person)
+            pix = os.listdir(os.path.join(train_str, person))
 
-        # Loop through each training image for the current person
-        for person_img in pix:
-            # Get the face encodings for the face in each image file
-            face = face_recognition.load_image_file(pix_str + "/" + person_img)
-            face_bounding_boxes = face_recognition.face_locations(face)
-
-            # If training image contains exactly one face
-            if len(face_bounding_boxes) == 1:
-                face_enc = face_recognition.face_encodings(face)[0]
-                # Add face encoding for current image with corresponding label (name) to the training data
-                encodings.append(face_enc)
-                names.append(person)
-            else:
-                print(person + "/" + person_img + " was skipped and can't be used for training")
+            # Loop through each training image for the current person
+            for person_img in pix:
+                # Get the face encodings for the face in each image file
+                image = os.path.join(pix_str, person_img)
+                executor.submit(train_image, image, person)
 
     # Create and train the SVC classifier
 
+    encodings = [x for x, _ in tuples]
+    names = [y for _, y in tuples]
+
     clf = svm.SVC(gamma='scale', probability=True)
     clf.fit(encodings, names)
     joblib.dump(clf, 'saved_model.pkl')
 
 # Load the test image with unknown faces into a numpy array
-test_image = face_recognition.load_image_file(os.path.join('application_data', 'input_image', 'input_image.jpg'))
+test_image = face_recognition.load_image_file(os.path.join('application_data', 'input_image', 'input_image3.jpg'))
 
 # Find all the faces in the test image using the default HOG-based model
 face_locations = face_recognition.face_locations(test_image)
@@ -63,5 +75,12 @@ print("Number of faces detected: ", no)
 print("Found:")
 for i in range(no):
     test_image_enc = face_recognition.face_encodings(test_image)[i]
-    name = clf.predict([test_image_enc])
-    print(*name)
+    start_time = time.perf_counter_ns()
+    proba = clf.predict_proba([test_image_enc])
+    end_time = time.perf_counter_ns()
+    process_time = end_time - start_time
+    classes = clf.classes_
+    i = np.argmax(proba)
+    proba = list(*proba)
+    name = classes[i]
+    print(name, "{:.2f}".format(proba[i]), proba, process_time)

+ 11 - 0
requirements.txt

@@ -0,0 +1,11 @@
+click==8.1.3
+dlib==19.24.0
+face-recognition==1.3.0
+face-recognition-models==0.3.0
+joblib==1.1.0
+numpy==1.23.3
+opencv-python==4.6.0.66
+Pillow==9.2.0
+scikit-learn==1.1.2
+scipy==1.9.1
+threadpoolctl==3.1.0

+ 65 - 0
verify_face.py

@@ -0,0 +1,65 @@
+import face_recognition
+import cv2
+import numpy as np
+import joblib
+import time
+
+# This is a super simple (but slow) example of running face recognition on live video from your webcam.
+# There's a second example that's a little more complicated but runs faster.
+
+# PLEASE NOTE: This example requires OpenCV (the `cv2` library) to be installed only to read from your webcam.
+# OpenCV is *not* required to use the face_recognition library. It's only required if you want to run this
+# specific demo. If you have trouble installing it, try any of the other demos that don't require it instead.
+
+# Get a reference to webcam #0 (the default one)
+video_capture = cv2.VideoCapture(0)
+
+clf = joblib.load('saved_model.pkl')
+classes = clf.classes_
+
+threshold = 0.65
+
+while True:
+    # Grab a single frame of video
+    ret, frame = video_capture.read()
+
+    # Convert the image from BGR color (which OpenCV uses) to RGB color (which face_recognition uses)
+    rgb_frame = frame[:, :, ::-1]
+
+    # Find all the faces and face enqcodings in the frame of video
+    face_locations = face_recognition.face_locations(rgb_frame)
+    no = len(face_locations)
+    print("Number of faces detected: ", no)
+    face_encodings = face_recognition.face_encodings(rgb_frame, face_locations)
+
+    # Loop through each face in this frame of video
+    for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
+        start_time = time.perf_counter_ns()
+        proba_list = clf.predict_proba([face_encoding])
+        end_time = time.perf_counter_ns()
+        process_time = end_time - start_time
+        i = np.argmax(proba_list)
+        proba = list(*proba_list)[i]
+        name = classes[i]
+        print(name, "{:.2f}".format(proba), proba_list, process_time)
+
+        # Draw a box around the face
+        cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
+
+        # Draw a label with a name below the face
+        cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
+        if(proba > threshold):
+            font = cv2.FONT_HERSHEY_DUPLEX
+            cv2.putText(frame, "{} {:.2f}".format(name, proba), (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)
+
+
+    # Display the resulting image
+    cv2.imshow('Video', frame)
+
+    # Hit 'q' on the keyboard to quit!
+    if cv2.waitKey(1) & 0xFF == ord('q'):
+        break
+
+# Release handle to the webcam
+video_capture.release()
+cv2.destroyAllWindows()