简体   繁体   中英

Enrollment of new faces into face recognition dataset (opencv, face_recognition)

I have a face recognition code(Entire code given at the end) that works perfectly fine with the existing dataset.

But I wanted it to also add new faces into the dataset(Enrollments), after asking for a user input for the name of the new person in the frame [like this: new_name = print(Who is this?) ]. So then I could create a new folder by the entered name, and store the face inside the frame. This is what I did:

    new_name = input("Who is this?")
    path_2 = os.path.join('Images',new_name)
    os.mkdir(path_2)
    print("Directory '% s' created" % new_name)
    for (x, y, w, h) in faces:
        cv2.rectangle(frame, (x, y), (x + w, y + h), (0,0,255),
        thickness = 2)
        cv2.putText(frame, new_name, (x, y), cv2.FONT_HERSHEY_SIMPLEX,
        0.75, (0, 255, 0), 2)
        sub_face = frame[y:y+h, x:x+w]
        FaceFileName = new_name + str(y+x) + ".jpg"
        cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
    cv2.imshow("Frame",frame)
    #if cv2.waitKey(1) & 0xFF == ord('q'):
    #    break

This worked fine with new people. But now I had to do something for unrecognized faces of known people . In this case, we would already have a folder by the entered name. We must append the image into the existing folder by the entered name. So for this I tried the below code: (Did not work)

else: # To store the unknown new face with name
            new_name = input("Who is this?")
            # If the new_name entered already exists as a folder
            if os.path.isfile(new_name):
                print(new_name,"folder already exists")
                frame = imutils.resize(frame, width = 400)
                rects = detector.detectMultiScale(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY),
                                              scaleFactor=1.1,
                                              minNeighbors=5,
                                              minSize=(30, 30))
                FaceFileName = new_name + str(y+x) + ".jpg"
                for (x, y, w, h) in rects:
                    cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
                cv2.imshow("Frame",frame)
                key = cv2.waitKey(1) & 0xFF
                if key == ord("k"):
                    p = os.path.join([new_name,FaceFileName.format(str(total).zfill(5))])
                    # cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
                    cv2.imwrite(p, orig)
                    total += 1
                    print("Image saved")
                elif key == ord("q"):
                    break 
            # If the new_name does not exist as a folder new folder has to be created
            else: 
                path_2 = os.path.join('Images',new_name)
                os.mkdir(path_2)
                print("Directory '% s' created" % new_name)
                frame = imutils.resize(frame, width = 400)
                rects = detector.detectMultiScale(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY),
                                                scaleFactor=1.1,
                                                minNeighbors=5,
                                                minSize=(30, 30))
                FaceFileName = new_name + str(y+x) + ".jpg"
                for (x, y, w, h) in rects:
                    cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
                    cv2.imshow("Frame",frame)
                    key = cv2.waitKey(1) & 0xFF
                if key == ord("k"):
                    p = os.path.join([path_2,FaceFileName.format(str(total).zfill(5))])
                    # cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
                    cv2.imwrite(p, orig)
                    total += 1
                print("Image saved")

I am getting the error:

Who is this?Vishwesh
Traceback (most recent call last):
  File "C:\Users\Vishw\databs.py", line 117, in <module>
    os.mkdir(path_2)
FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'Images\\Vishwesh'
[ WARN:0] global C:\Users\runneradmin\AppData\Local\Temp\pip-req-build-sgoydvi3\opencv\modules\videoio\src\cap_msmf.cpp (438) `anonymous-namespace'::SourceReaderCB::~SourceReaderCB terminating async callback

Complete code is given below. Let me know what is wrong with the code. Kindly help!

Note : I included the above codes under the # Face recognition on LIVE WEBCAM FEED section and as else statement for the "if True in matches:"

Here is my entire code:

# Extracting features from face
from imutils import paths
import face_recognition
import pickle
import cv2
import os
 
#Get paths of each file in folder named Images
#Images here contains my data(folders of various persons)
imagePaths = list(paths.list_images('Images'))
knownEncodings = []
knownNames = []
# loop over the image paths
for (i, imagePath) in enumerate(imagePaths):
    # extract the person name from the image path
    name = imagePath.split(os.path.sep)[-2]
    # load the input image and convert it from BGR (OpenCV ordering)
    # to dlib ordering (RGB)
    image = cv2.imread(imagePath)
    rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
    #Use Face_recognition to locate faces
    boxes = face_recognition.face_locations(rgb,model='hog')
    # compute the facial embedding for the face
    encodings = face_recognition.face_encodings(rgb, boxes)
    # loop over the encodings
    for encoding in encodings:
        knownEncodings.append(encoding)
        knownNames.append(name)
#save emcodings along with their names in dictionary data
data = {"encodings": knownEncodings, "names": knownNames}
#use pickle to save data into a file for later use
f = open("face_enc", "wb")
f.write(pickle.dumps(data))
f.close()
 
# Face recognition on LIVE WEBCAM FEED
import face_recognition
import pickle
import cv2
import os
#find path of xml file containing haarcascade file 
cascPathface = os.path.dirname(
 cv2.__file__) + "/data/haarcascade_frontalface_default.xml"
# load the harcaascade in the cascade classifier
faceCascade = cv2.CascadeClassifier(cascPathface)
# load the known faces and embeddings saved in last file
data = pickle.loads(open('face_enc', "rb").read())
print("Streaming started")
video_capture = cv2.VideoCapture(0)
# loop over frames from the video file stream
while True:
    # grab the frame from the threaded video stream
    ret, frame = video_capture.read()
    orig = frame.copy()
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    faces = faceCascade.detectMultiScale(gray,
                                         scaleFactor=1.05,
                                         minNeighbors=3,
                                         minSize=(60, 60),
                                         flags=cv2.CASCADE_SCALE_IMAGE)
 
    # convert the input frame from BGR to RGB 
    rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    # the facial embeddings for face in input
    encodings = face_recognition.face_encodings(rgb)
    names = []
    # loop over the facial embeddings incase
    # we have multiple embeddings for multiple fcaes
    for encoding in encodings:
       #Compare encodings with encodings in data["encodings"]
       #Matches contain array with boolean values and True for the embeddings it matches closely
       #and False for rest
        matches = face_recognition.compare_faces(data["encodings"],encoding)
        #set name =unknown if no encoding matches
        name = "Unknown"
        
        # check to see if we have found a match
        if True in matches:
            # Find positions at which we get True and store them
            matchedIdxs = [i for (i, b) in enumerate(matches) if b]
            counts = {}
            # loop over the matched indexes and maintain a count for
            # each recognized face face
            for i in matchedIdxs:
                #Check the names at respective indexes we stored in matchedIdxs
                name = data["names"][i]
                #increase count for the name we got
                counts[name] = counts.get(name, 0) + 1
            #set name which has highest count
            name = max(counts, key=counts.get)
        else: # To store the unknown new face with name
            new_name = input("Who is this?")
            # If the new_name entered already exists as a folder
            if os.path.isfile(new_name):
                print(new_name,"folder already exists")
                frame = imutils.resize(frame, width = 400)
                rects = detector.detectMultiScale(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY),
                                              scaleFactor=1.1,
                                              minNeighbors=5,
                                              minSize=(30, 30))
                FaceFileName = new_name + str(y+x) + ".jpg"
                for (x, y, w, h) in rects:
                    cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
                cv2.imshow("Frame",frame)
                key = cv2.waitKey(1) & 0xFF
                if key == ord("k"):
                    p = os.path.join([new_name,FaceFileName.format(str(total).zfill(5))])
                    # cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
                    cv2.imwrite(p, orig)
                    total += 1
                    print("Image saved")
                elif key == ord("q"):
                    break 
            # If the new_name does not exist as a folder new folder has to be created
            else: 
                path_2 = os.path.join('Images',new_name)
                os.mkdir(path_2)
                print("Directory '% s' created" % new_name)
                frame = imutils.resize(frame, width = 400)
                rects = detector.detectMultiScale(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY),
                                                scaleFactor=1.1,
                                                minNeighbors=5,
                                                minSize=(30, 30))
                FaceFileName = new_name + str(y+x) + ".jpg"
                for (x, y, w, h) in rects:
                    cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
                    cv2.imshow("Frame",frame)
                    key = cv2.waitKey(1) & 0xFF
                if key == ord("k"):
                    p = os.path.join([path_2,FaceFileName.format(str(total).zfill(5))])
                    # cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
                    cv2.imwrite(p, orig)
                    total += 1
                print("Image saved")
            
              
 
        # update the list of names
        names.append(name)
        # loop over the recognized faces
        for ((x, y, w, h), name) in zip(faces, names):
            # rescale the face coordinates
            # draw the predicted face name on the image
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
            cv2.putText(frame, name, (x, y), cv2.FONT_HERSHEY_SIMPLEX,
             0.75, (0, 255, 0), 2)            
    cv2.imshow("Frame", frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
video_capture.release()
cv2.destroyAllWindows()

So, your issue is rather related to file operations then to face recognition... Try to check if folder alreday exists before trying to create it:

path_2 = os.path.join('Images',new_name)
if not os.path.exists(path_2):
    os.mkdir(path_2)

Using the idea given by @Bohdan:

else: # To store the unknown new face with name
            new_name = input("Who is this?")
            path_2 = os.path.join('Images',new_name)
            for (x, y, w, h) in faces:
                    cv2.rectangle(frame, (x, y), (x + w, y + h), (0,0,255),
                    thickness = 2)
                    cv2.putText(frame, new_name, (x, y), cv2.FONT_HERSHEY_SIMPLEX,
                    0.75, (0, 255, 0), 2)
                    sub_face = frame[y:y+h, x:x+w]
                    FaceFileName = new_name + str(y+x) + ".jpg"
            if not os.path.exists(path_2):
                os.mkdir(path_2)
                print("Directory '% s' created" % new_name)
                cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)
            # To store unrecognised faces of known people
            else:
                cv2.imwrite(os.path.join(path_2,FaceFileName),sub_face)

Code works perfectly fine!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM