ageitgey / face_recognition

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

How do I train multiple images per person in Python library? #217

Closed jatinkrmalik closed 6 years ago

jatinkrmalik commented 6 years ago

Description

I want to train multiple images per person in my python code. This can be in 2 parts:

  1. I provide the initial seed data, let us say, a folder for each person with his images.
  2. I want it to be kind of dynamic so that whenever I match a face, I will crop the face and add it to training data. (This I can do as soon as I am able to accomplish #1).

What I Did

The above thing is easy to do via CLI as there is a dedicated command for that, I looked into code but couldn't understand how to get it done natively in Python as how it works in python is that I feed it an array of images named with person-name.jpg, train it, pickle both imageName array and trainedData array and just load it with pickle in my code whenever I want to start recognising face via my web camera (using opencv3).

I am sorry if my question feels too noobish, please point me in right direction then.

AlainPilon commented 6 years ago

This question has been posted almost weekly for a while now. Look in the closed issues.

The quick answer is that it is not the way this lib works but you can fake it with multiple entries per human, but it would not improve the results that much, contrary to a neural network which improves with more data.

jatinkrmalik commented 6 years ago

Ah well, I tried adding multiples faces with the same name but that confuses the system as it keeps redrawing the box and name thinking each same name as a different name linked to a specific encoding.

Anyway, thank you, @AlainPilon. I will check the code further unless someone else can reply me here.

AlainPilon commented 6 years ago

A quick solution is to have all the keys of your encodings following a similar pattern, ex: {"alain-1: [...], "alain-2": [..]} and when you get the list of matching encodings, split the keys on "-", put them in a set to remove duplicates and you will have a single record per individual.

jatinkrmalik commented 6 years ago

@AlainPilon not a good solution, because I am playing an audio as soon as a face is detected like "Hello Jatin" and throwing a call back to basically authenticate entry of that person. Doing above approach isn't different than training multiple images with same name. The problem here would be when based on angle it will start switching to "Jatin-1", "Jatin-2" and "Jatin-3", eventually confusing the authentication system, also it would be a problem for detecting 2 people with same names. 😞

AlainPilon commented 6 years ago

I think you misunderstood. Once you have a match, you get the key then remove the number part. So all the matches are going to be the same "Jatin" which you can then use to authenticate against your system.

ageitgey commented 6 years ago

@jatinkrmalik There's a million ways to do this and there isn't a single right answer.

Here are some approaches you could use:

  1. Simplest: If you have a separate folder of images for each known user, you could call compare_faces(known_images_for_one_user, unknown_image) once for each folder of known images. If any of the results are True for a single call are true, then you know the face matches that known person.
  2. More complex: You could build a classifier with scikit-learn that predicts a user name for a face encoding. The training data would be all the face encodings from all your known images (and the associated user name). You could use a support vector classifier (SVC), for example. The downside of this approach is that you have to re-train the classifier when you add more known pictures and that it will always try to say an unknown picture is one of your known users.
  3. More complex / Scaling to larger data sets: You could use a clustering algorithm to put all the known face encodings into clusters and test an unknown user by seeing which cluster point it's closest to (and then verifying it using compare_faces but only against the faces in that cluster. I've been meaning to write an example program doing this, maybe using Spotify's Annoy library but I haven't had time yet.

Those are just some ideas. The first one would probably work fine for what it sounds like you want to do.