0

I'm getting this error on the line that goes encoding = face_recognition.face_encodings(image)[0]. As i am trying to get the first face it identifies. The code runs without the [0] but is stuck on the first image identification.

Here's the code:

import face_recognition
import os
import cv2


KNOWN_FACES_DIR = 'known_faces'
UNKNOWN_FACES_DIR = 'unknown_faces'
TOLERANCE = 0.6
FRAME_THICKNESS = 3
FONT_THICKNESS = 2
MODEL = 'cnn'  # default: 'hog', other one can be 'cnn' - CUDA accelerated (if available) deep-learning pretrained model


# Returns (R, G, B) from name
def name_to_color(name):
    # Take 3 first letters, tolower()
    # lowercased character ord() value rage is 97 to 122, substract 97, multiply by 8
    color = [(ord(c.lower())-97)*8 for c in name[:3]]
    return color


print('Loading known faces...')
known_faces = []
known_names = []

# We oranize known faces as subfolders of KNOWN_FACES_DIR
# Each subfolder's name becomes our label (name)
for name in os.listdir(KNOWN_FACES_DIR):

    # Next we load every file of faces of known person
    for filename in os.listdir(f'{KNOWN_FACES_DIR}/{name}'):

        # Load an image
        image = face_recognition.load_image_file(f'{KNOWN_FACES_DIR}/{name}/{filename}')

        # Get 128-dimension face encoding
        # Always returns a list of found faces, for this purpose we take first face only (assuming one face per image as you can't be twice on one image)
        encoding = face_recognition.face_encodings(image)[0]

        # Append encodings and name
        known_faces.append(encoding)
        known_names.append(name)


print('Processing unknown faces...')
# Now let's loop over a folder of faces we want to label
for filename in os.listdir(UNKNOWN_FACES_DIR):

    # Load image
    print(f'Filename {filename}', end='')
    image = face_recognition.load_image_file(f'{UNKNOWN_FACES_DIR}/{filename}')

    # This time we first grab face locations - we'll need them to draw boxes
    locations = face_recognition.face_locations(image, model=MODEL)

    # Now since we know loctions, we can pass them to face_encodings as second argument
    # Without that it will search for faces once again slowing down whole process
    encodings = face_recognition.face_encodings(image, locations)

    # We passed our image through face_locations and face_encodings, so we can modify it
    # First we need to convert it from RGB to BGR as we are going to work with cv2
    image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

    # But this time we assume that there might be more faces in an image - we can find faces of dirrerent people
    print(f', found {len(encodings)} face(s)')
    for face_encoding, face_location in zip(encodings, locations):

        # We use compare_faces (but might use face_distance as well)
        # Returns array of True/False values in order of passed known_faces
        results = face_recognition.compare_faces(known_faces, face_encoding, TOLERANCE)

        # Since order is being preserved, we check if any face was found then grab index
        # then label (name) of first matching known face withing a tolerance
        match = None
        if True in results:  # If at least one is true, get a name of first of found labels
            match = known_names[results.index(True)]
            print(f' - {match} from {results}')

            # Each location contains positions in order: top, right, bottom, left
            top_left = (face_location[3], face_location[0])
            bottom_right = (face_location[1], face_location[2])

            # Get color by name using our fancy function
            color = name_to_color(match)

            # Paint frame
            cv2.rectangle(image, top_left, bottom_right, color, FRAME_THICKNESS)

            # Now we need smaller, filled grame below for a name
            # This time we use bottom in both corners - to start from bottom and move 50 pixels down
            top_left = (face_location[3], face_location[2])
            bottom_right = (face_location[1], face_location[2] + 22)

            # Paint frame
            cv2.rectangle(image, top_left, bottom_right, color, cv2.FILLED)

            # Wite a name
            cv2.putText(image, match, (face_location[3] + 10, face_location[2] + 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (200, 200, 200), FONT_THICKNESS)

    # Show image
    cv2.imshow(filename, image)
    cv2.waitKey(0)
    cv2.destroyWindow(filename)
Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
  • If `xxx[0]` gives you "list index out of range", then the list is empty. You say "the code runs without the [0]", but are you doing anything with `known_faces`? Would you even know if the list was empty? – Tim Roberts May 08 '21 at 21:39
  • It is fetching the images from the directory Known_faces and using it to detect the face. Any idea what am i supposed to do to get rid of the error? i have images in the folder – Osama Jilani May 08 '21 at 22:07

2 Answers2

0

You need to check the return value of face_recognition.face_encodings(image) and face_recognition.face_locations(image, model=MODEL). Maybe face_recognition was unable to detect any faces in the image.

Your code might look something like this.

encodings = face_recognition.face_encodings(image)
if len(encodings) > 0:

    # Append encodings and name
    known_faces.append(encodings[0])
    known_names.append(name)

locations = face_recognition.face_locations(image, model=MODEL)
if len(locations) == 0:
    # no images found
    continue
Nicholas Hunter
  • 1,791
  • 1
  • 11
  • 14
  • I get error on the last image. I printed out len(encondings) it shows me that there is data there. It stores the facial data for the first face it founds but it gives me an error that the list index is out of range on the last image it is trying to process. Also, i tried to break the loop on the first face it finds but its giving me an error on this line ``` results = face_recognition.compare_faces(known_faces, face_encoding, TOLERANCE) ``` – Osama Jilani May 09 '21 at 21:05
  • the error seen on that line is numpy.AxisError: axis 1 is out of bounds for array of dimension 1 – Osama Jilani May 09 '21 at 21:06
0

mostly its happen when image is too large or image recognition cant find the face for solving the problem resize the input and output image

osman
  • 1
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 12 '23 at 16:18