ITCooky Recetas

Vamos a cocinar it cositas

Como buscar a una persona en la foto con OpenCV, dlib, face_recognition en Ubuntu 20.4

дата septiembre 8, 2021

En realidad, buscaré al actor español Alvaro Morte, sin razon alguno ¡porque se me antoja! Hay una serie de televisión en español mas de k episodios, hay capturas de pantalla unas 2k: ¡Quiero encontrarlo y necesito optimizarla ese proceso!

Traté de usar este manual Face recognition with OpenCV, Python, and deep learning pero resultó ser incomprensible y era necesario registrarse allí, solo me ayudó con la instalación. Pero el manual de Hussain Mujtaba realmente me ayudó Face Recognition with Python and OpenCV.

Instalar OpenCV
Lo instalaré a través de pip, ya lo tengo instalado.
pip --version

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

Python tambien ya lo tengo instalado
python --version

Python 2.7.18

python3 --version

Python 3.8.10

Tambein es necesario instalar esto
sudo apt-get install python-setuptools
sudo apt-get install python-dev

Instalamos OpenCV
sudo pip install opencv-contrib-python

Instalacion de dlib con uso de CUDA
Sé con certeza que tengo núcleos CUDA en la GeForce RTX 2070; en cualquier tarjeta de video Nvidia que no sea antigua deberían estar

para ensamblaje necesitas cmaker que lo instalo primero
sudo apt-get install cmake

sigo con
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 .

El comando del manual de 2018 ya no funciona, lo ejecutamos así
sudo python setup.py install

Instalar face_recognition
pip install face_recognition

Instalar imutils
Dicen que lo necesitamos
pip install imutils

Entrenamos el modelo de la cara
Cree una carpeta app, y en ella cree una carpeta Images y en ella, cree una carpeta alvaro_morte
Guardamos aca un montón (alrededor de 60) de fotos de Álvaro Morte desde diferentes ángulos.

En el folder app cree un archivo py
vi learn.py
insertamos código en él, aquí está el enlace a las rutas donde están las imágenes

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

crea en la misma carpeta el archivo face_enc aquí la cara digitalizada de Alvaro bajo el nombre de la carpeta en la que estaban sus fotos

Ahora creamos un archivo
vi recog.py

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

coloque el archivo 001.jpg en la carpeta de la app, que contiene el script y el archivo face_enc
el nombre de file está escrito en esta línea

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

Run
python3 recog.py

programa muestra una foto (sin su nombre, lo cual es malo) y delinea la cara si lf reconoce – para cerrarla, debes presionar 0 cuando se muestra la foto

Con La imagen del kit de entrenamiento funcionó.

En la foto nueva tambien

Si hay varias caras en la foto, funciona de forma extraña, pero funciona

¡¡¡Funciona!!! Ahora necesitamos adaptarlo para buscar en muchas fotos, y para que copie estas imágenes a otra carpeta, y para esto necesitamos sumergirnos en python, y ya no me gusta … así que have una parte en bash

Entonces habrá dos archivos, el primer pyhon
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() 
      

Este es un code cortado y ligeramente modificado que vino antes. Toma del exterior el nombre del archivo, que le pasaremos con bash y escribiremos el nombre en el archivo si detecta a Alvaro encuentra

Hacemos

vi facecheck.sh

con 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

aquí solo necesitas cambiar la variable folder, ahora dice la carpeta es test
entonces en la carpeta tenemos tres archivos facecheck.sh nrecog.py face_enc y una carpeta test con fotos para esa prueba (no de entrenamiento)

Run
bash ./facecheck.sh

Miramos el archivo que creó result.txt, y también copia todas las imágenes encontradas en la carpeta test_result.

resultado
28 – fotod totales
9 – detecto cara de Alvaro Morte
4 – de ellos realmente con Alvaro
2 – con cara de Alvera que no detecto, aunque aqui tiene dificultades con la cara – está de perfil, y en el segundo después de la tortura

Supongo que puedo mejorar este resultado mejorando el modelo matematico de cara. Tomo alrededor de 2000 capturas de pantalla más de la entrevista del video con Álvaro.

Tomo una captura de pantalla de cada segundo con el comando
ffmpeg -i video.mp4 -vf fps=1 out%d.jpg

Retrocedo un par de pasos, los pongo en la carpeta correcta y empiezo a entrenar. ¡Ya lleva más tiempo!

Empiezo a reconocer de nuevo
28 – archivos totales
16 – detecto cara de Alvaro Morte
6 – de ellos realmente con Alvaro
0 – todos los Alvars encontrados

Debe haber un ajuste para la precisión del reconocimiento … ¡y lo es!

En archivo nrecog.py encontramos linea

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

la cambiamos con esa

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

añadimos tolerance aca

Todo esta super bien ahora

Resultado
28 – archivos totales
6 – detecto cara de Alvaro Morte
6 – de ellos realmente con Alvaro
0 – todos los Alvars encontrados

Ahora sería bueno verificar a gran escala para que haya 2000 capturas de pantalla y, por lo general, esto es un problema, pero aquí está un strieaming español, espero que no se ofenda, todo lo que hacemos lo hacemos con fines científicos, aquí web el enlace se puede utilizar para extraer alrededor de 2350 capturas de pantalla de una manera facil, una de un capitulo. Y sé con certeza que Álvaro estaba allí (ya lo noté).

Arranco el programa

Con una tolerance 0.4, encontré 26 con Mora, mientras que con mis ojos encontré 34, pero no encontré 4 donde Mora estaba lejos.

Por cierto: el proceso de procesamiento de 2300 imágenes con un tamaño de 1280×720 me lleva 59 minutos:
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

Al mismo tiempo, no hay sobrecarga extrema, los procesador con la tarjeta de video ni siquiera se calientan.

Reinicio con una tolerancia de 1.1 NO ALTO, esto es demasiado, incluso 0.7 lo es. Pongo 0.5
Encontrado 56 de ellos con Álvaro 28. Está bien que confunder a ALvaro con hombres barbudos, ¡pero a veces marca las mujeressin barba como Álvaro!

En Total: El sistema ayuda a encontrar caras, pero la precisión no es muy buena, al parecer depende del modelo entrenado. Mis ojos y mi cerebro están buscando más rápido por ahora, lo que me complace … aunque la PC tiene infinitas oportunidades de mejora, y mi cerebro con cada año mas…


Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *