ITCooky Recipes

Lets cooky it yammy things!

How to search for a person in the photo with OpenCV, dlib, face_recognition in Ubuntu 20.4

дата September 8, 2021

Actually, I will search for the Spanish actor Alvaro Morte, for no reason, because! There is a television series in Spanish with more than 2k episodes, and there are screenshots about 2k: I want to find it and I need to optimize that process!

I tried to use this manual Face recognition with OpenCV, Python, and deep learning but it turned out to be incomprehensible and it was necessary to register there, it just helped me with the installation. But Hussain Mujtaba’s manual really helped me Face Recognition with Python and OpenCV.

Install OpenCV
I will install it through pip, I already have it installed.
pip --version

pip 20.0.2 from /usr/lib/python3/dist-packages/pip (python 3.8)

Python I also already have it installed
python --version

Python 2.7.18

python3 --version

Python 3.8.10

You also need to install this
sudo apt-get install python-setuptools
sudo apt-get install python-dev

Install OpenCV
sudo pip install opencv-contrib-python

Installation of dlib with use of CUDA
I know for a fact that I have CUDA cores in the GeForce RTX 2070; on any non-old Nvidia video card they should be

for assembly you need cmaker that I install it first
sudo apt-get install cmake

next
git clone https://github.com/davisking/dlib.git
cd dlib
mkdir build
cd build
cmake .. -DDLIB_USE_CUDA=1 -DUSE_AVX_INSTRUCTIONS=1
cmake --build .

The 2018 manual command no longer works, we run it like this
sudo python setup.py install

Install face_recognition
pip install face_recognition

Install imutils
They say we need it
pip install imutils

Let’s train the face model
Create an app folder, in it create a folder Images and in it, create a folder alvaro_morte
We keep here a lot (around 60) of photos of Álvaro Morte from different angles.

In the app folder create a py file
vi learn.py
we insert code in it, here is the link to the routes where the images are

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))

Run
python3 learn.py

it will create in the same folder the file face_enc here the digitized face of Alvaro under the name of the folder where his photos were

Now we create a file
vi recog.py

code

import face_recognition
import imutils
import pickle
import time
import cv2
import os
 
#find path of xml file containing haarcascade file
cascPathface = os.path.dirname(
 cv2.__file__) + "/data/haarcascade_frontalface_alt2.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())
#Find path to the image you want to detect face and pass it here
image = cv2.imread('./001.jpg')
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
#convert image to Greyscale for haarcascade
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(gray,
                                     scaleFactor=1.1,
                                     minNeighbors=5,
                                     minSize=(60, 60),
                                     flags=cv2.CASCADE_SCALE_IMAGE)
 
# 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 =inknown 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)
 
 
        # 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(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
            cv2.putText(image, name, (x, y), cv2.FONT_HERSHEY_SIMPLEX,
             0.75, (0, 255, 0), 2)
    cv2.imshow("Frame", image)
    cv2.waitKey(0)

put the 001.jpg file in the app folder, which contains the script and the face_enc file
the filename is written on this line

image = cv2.imread('./001.jpg')

Run
python3 recog.py

program shows a photo (without its name, which is bad) and outlines the face if lf recognizes – to close it, you have to press 0 when the photo is displayed

With the image of the training kit it worked.

In the new photo too

If there are multiple faces in the photo, it works weird, but it works

It works!!! Now we need to adapt it to search in many photos, and to copy these images to another folder, and for this we need to dive into python, and I don’t like it allready … so I have a part in bash

Then there will be two files, the first python
vi nrecog.py
code

import sys
import face_recognition
import imutils
import pickle
import time
import cv2
import os

#find path of xml file containing haarcascade file
cascPathface = os.path.dirname(
 cv2.__file__) + "/data/haarcascade_frontalface_alt2.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())
#Find path to the image you want to detect face and pass it here
image = cv2.imread(sys.argv[1])
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
#convert image to Greyscale for haarcascade
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(gray,
                                     scaleFactor=1.1,
                                     minNeighbors=5,
                                     minSize=(60, 60),
                                     flags=cv2.CASCADE_SCALE_IMAGE)
 
# 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, tolerance=0.5)
    #set name =inknown if no encoding matches
    name = "Unknown"
    # check to see if we have found a match
    if True in matches:
        f = open("result.txt", "a")
        f.write(sys.argv[1] + '\n')
        f.close()
        sys.exit() 
      

This is a slightly modified and cuted code that came before. It takes the name of the file from the outside, which we will pass to it with bash and it will write the name in the file if it detects Alvaro face

make

vi facecheck.sh

code

#!/bin/bash
IFS=$'\n'
folder="test" 
rm result.txt
mkdir "./"$folder"_result" 
echo $folder
for a in $( ls ./$folder ); do
python3 nrecog.py $folder/$a
echo "./"$folder"/"$a
done
for a in $( cat ./result.txt | awk -F/ '{print $2}' ); do
cp "./"$folder"/"$a "./"$folder"_result/"$a
done

here you only need to change the variable folder , now it says the folder is test
then in the folder we have three files facecheck.sh nrecog.py face_enc and a folder test with photos for that test (not training)

Run
bash ./facecheck.sh

Lets look at the file that created result.txt, and it also copies all the images found in the folder test_result.

Outcome
28 – total photos
9 – detect the face of Alvaro Morte
4 – of them really with Alvaro
2 – with an Alvera face that it cannot detect, although here he has difficulties with his face – he is in profile, and in the second after the torture

I suppose I can improve this result by improving the mathematical model of face. I take about 2000 more screenshots of the video interview with Álvaro.

I take a screenshot of every second with the command
ffmpeg -i video.mp4 -vf fps=1 out%d.jpg

I take a couple of steps back, put them in the correct folder, and start training. It takes longer!

I begin to recognize again
28 – total files
16 – detect Alvaro Morte’s face
6 – of them really with Alvaro
0 – all Alvars found

There must be an adjustment for recognition accuracy … and it is!

In file nrecog.py we find line

matches = face_recognition.compare_faces(data["encodings"], encoding)

changed it with that

matches = face_recognition.compare_faces(data["encodings"], encoding, tolerance=0.4)

we add tolerance aca

Everything is super good now

Outcome
28 – total files
6 – detect the face of Alvaro Morte
6 – of them really with Alvaro
0 – all Alvars found

Now it would be nice to check on a large scale, to finde around 2000 screenshots usually this is a problem, but here is a Spanish strieaming, hope they dont get angry, everything we do we do for scientific purposes, here web the link can be used to extract around 2350 screenshots in an easy way, one from a chapter. And I know for sure that Álvaro was there (I already noticed).

Run the soft againe

With a tolerance 0.4 , I found 26 with Mora, while with my eyes I found 34, but I did not find 4 where Mora was far away.

By the way: the process of processing 2300 images with a size of 1280×720 takes me 59 minutes
OS: Ubuntu 20.04.3 LTS
CPU: AMD® Ryzen 7 3700x 8-core processor × 16
Mem: 62,8 GiB
GPU: Nvidia GeForce RTX 2070
Disk: Samsung SSD 970 EVO Plus 500GB
At the same time, there is no extreme overload, the processors with the video card do not even get hot.

Restart with a tolerance of 1.1 NOT SROP, this is too much, even 0.7 is. I put 0.5
Found 56 of them with Álvaro 28. It’s okay to confuse ALvaro with bearded men, but sometimes he marks women without a beard as Álvaro!

In total: The system helps to find faces, but the precision is not very good, apparently it depends on the trained model. My eyes and my brain are searching faster for now, which pleases me … although the PC has endless opportunities for improvement, and my brain with each year is …


Leave a Reply

Your email address will not be published. Required fields are marked *