ageitgey / face_recognition

The world's simplest facial recognition api for Python and the command line
MIT License
52.86k stars 13.43k forks source link

Cannot crop frame based on face_location #579

Open blake-edwards opened 6 years ago

blake-edwards commented 6 years ago

Description

When getting the location of faces in a live webcam feed I have been trying to crop the image to just display the detected face. However, when I used the rectangle coordinates to perform a crop on the image and save it to the disk, the jpg cannot be opened because it is empty.

screen shot 2018-08-05 at 10 06 58 pm

Here is a screenshot to show you that drawing a rectangle is working.

What I Did

import cv2
import face_recognition
import argparse

ap = argparse.ArgumentParser()
ap.add_argument("-d", "--detection-method", type=str, default="hog", help="face detection model to use: either `hog` (light) or `cnn` (heavy)")
args = vars(ap.parse_args())

cap = cv2.VideoCapture(0)

print("[WELCOME] Welcome to the face dataset creator!")
print("[INFO] Attempting to recognize face...")
faces_recognized = 0
while(True):
    ret, frame = cap.read()
    if not ret:
        print("[WARNING] Error retrieving frame from web-cam")
    rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    face_location_array = face_recognition.face_locations(rgb_frame, model=args['detection_method'])
    if face_location_array:     #  prevent manipulation of null variable
        y1 = face_location_array[0][0]
        x1 = face_location_array[0][1]
        end_coordinate_y = face_location_array[0][2]
        end_coordinate_x = face_location_array[0][3]
        faces_recognized += 1
        print("[%i] Face recognized..." % faces_recognized)
        cv2.rectangle(frame, (x1, y1), (end_coordinate_x, end_coordinate_y), (0, 0, 255), 2)
        cropped_face = frame[x1:end_coordinate_y, y1:end_coordinate_x]
        cv2.imwrite("faceimage.jpg", cropped_face)

    cv2.imshow('face detector', frame)
    if cv2.waitKey(20) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
ageitgey commented 6 years ago

I think you've mixed up the order of variables when extracting data from the array. Instead of this:

    face_location_array = face_recognition.face_locations(rgb_frame, model=args['detection_method'])
    if face_location_array:     #  prevent manipulation of null variable
        y1 = face_location_array[0][0]
        x1 = face_location_array[0][1]
        end_coordinate_y = face_location_array[0][2]
        end_coordinate_x = face_location_array[0][3]
        faces_recognized += 1
        print("[%i] Face recognized..." % faces_recognized)
        cv2.rectangle(frame, (x1, y1), (end_coordinate_x, end_coordinate_y), (0, 0, 255), 2)
        cropped_face = frame[x1:end_coordinate_y, y1:end_coordinate_x]

Try this:

    face_location_array = face_recognition.face_locations(rgb_frame, model=args['detection_method'])
    if face_location_array:     #  prevent manipulation of null variable

        top, right, bottom, left = face_location_array[0]

        faces_recognized += 1
        print("[%i] Face recognized..." % faces_recognized)

        cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
        cropped_face = frame[top:bottom, left:right]
blake-edwards commented 6 years ago

@ageitgey Thank you very much, it works perfectly! Saved me from more frustrating, inconclusive Google searches.