Manual

do

Maker

.

com

Reconhecimento facial com dlib

Reconhecimento facial com dlib

Nesse artigo mostrei como utilizar DNN para fazer face detection com OpenCV. Mas que  tal um reconhecimento facial com dlib usando um model com 99.38% de acurácia agora? Essa é molezinha! Trata-se de um projeto entregue praticamente pronto, só precisamos compilar a dlib, que é a única que tem um macete para quem tem CUDA instalado na máquina.

Essa semana tenho andado bastante empolgado com meus estudos de redes neurais e, não por acaso, acabei me deparando com um projeto fantástico, passível de adaptações. Trata-se do face_recognition, um excelente projeto, cujo repositório do projeto está nesse link.

Esse tutorial é para utilizar com Python3 e estou testando e escrevendo a partir de um Ubuntu 18.04.

Reconhecimento facial com dlib

A dlib é a grande sacada aqui. Claro que tem todo o projeto por trás, mas ela é o motor da coisa toda. Para compilá-la, precisamos cumprir com alguns pré-requisitos, mas tudo se resume ao procedimento abaixo:

sudo su
apt-get install -y --fix-missing \
    build-essential \
    cmake \
    gfortran \
    git \
    wget \
    curl \
    graphicsmagick \
    libgraphicsmagick1-dev \
    libatlas-dev \
    libavcodec-dev \
    libavformat-dev \
    libgtk2.0-dev \
    libjpeg-dev \
    liblapack-dev \
    libswscale-dev \
    pkg-config \
    python3-dev \
    python3-numpy \
    software-properties-common \
    zip \
    && apt-get clean && rm -rf /tmp/* /var/tmp/*

mkdir -p dlib && \
    git clone -b 'v19.9' --single-branch https://github.com/davisking/dlib.git dlib/ && \
    cd  dlib/ && \
python3 setup.py install --yes USE_AVX_INSTRUCTIONS --no DLIB_USE_CUDA

Se a compilação ocorrer sem problemas, já deve ser possível importar a dlib. Teste assim, se não retornar erro, está ok:

python3 -c "import dlib"

Se teve algum problema, meus mais sinceros sentimentos, mas dê um jeito aí porque você não pode ficar sem esse brinquedo! Por fim, instale o pacote pip para Python3 e já instale o programa para reconhecimento facial com dlib:

pip install python3-pip
pip3 install face_recognition

Pronto, a instalação está finalizada. Agora vamos ver como usar os programas e alguns dos recursos da biblioteca.

Face detection por linha de comando

Muitas pessoas ainda fazem confusão em relação a isso. Face detection simplesmente detecta um rosto, mas não sabe quem é.  Esse recurso é útil para economizar processamento (ficará clara a razão no próximo artigo), pois detectar uma face requer bem menos processamento que fazer o reconhecimento.

Para detecção facial, utilize o programa face_detection. Por exemplo, tenho um diretório com imagens e quero separar minhas fotos com a família, mas como são muitas fotos, demoraria horas para classificar. Então:

ls *jpg|while read line; do \
 echo "Detectiong on: $line"; \
 face_detection $line;sleep 2; \
done

O resultado seria algo como:

crop_imagemagick-300x93.webp

O programa devolve a região da face, podendo-se então recortá-la com a utilização do ImageMagick de forma automática, caso fosse de interesse.

convert copa.jpg -gravity northwest -crop 80x180x200x80 -compose over -composite copa_crop.jpg

Coloquei um espaço extra pra não ficar grudado na região da detecção.

O programa também permite a execução sobre um diretório de imagens:

face_recognition ./pictures_of_people_i_know/

As coordenadas são top, direita, base, esquerda.

Acelerando a detecção

Também podemos fazer uso de múltiplas CPUs para acelerar a detecção. Por exemplo:

face_detection --cpus 8 ./diretorio_de_imagens

Face detection com módulo Python

Agora começa a brincadeira para programadores.

Quando terminar a compilação, além de instalar a dlib ainda contaremos com um módulo para programar em Python. Isso facilita muito o uso de visão computacional para quem está iniciando, hum?

Um exemplo simples, fazendo o cropping mais preciso e sem precisar usar shell script:

import sys
from PIL import Image
import face_recognition

if len(sys.argv) == 1:
    print("passe uma imagem como parameto")
    sys.exit(0)

image = face_recognition.load_image_file("biden.jpg")
face_locations = face_recognition.face_locations(image)

print("I found {} face(s) in this photograph.".format(len(face_locations)))

for face_location in face_locations:

    top, right, bottom, left = face_location
    print("A face is located at pixel location Top: {}, Left: {}, Bottom: {}, Right: {}".format(top, left, bottom, right))

    face_image = image[top:bottom, left:right]
    pil_image = Image.fromarray(face_image)
    pil_image.show()

A compilação foi explicada sem a utilização de CUDA. Ainda assim, é possível utilizar uma CNN para fazer a detecção de face e pode valer a pena se distribuir o processamento em vários núcleos. Para linha de comando:

face_detection --cpus 8 --model cnn ./jpg/

E dentro do código Python, basta incluir o parâmetro na respectiva linha:

face_locations = face_recognition.face_locations(image, model="cnn")

Detectando regiões da face

Olha só que incrível. Se quiser fazer montagens ou ocultar uma parte do rosto (por exemplo, esconder os olhos de uma criança), as referências do posicionamento podem ser pegas com uma linha de Python:

import face_recognition

image = face_recognition.load_image_file("perfil_dj.jpg")
face_landmarks_list = face_recognition.face_landmarks(image)

Essa referência foi tirada da imagem desse bonitão aqui:

djames.webp

Se resolver pegar essa imagem, ela foi redimensionada e dará outras dimensões na execução do código agora.

Face recognition por linha de comando

Para fazer reconhecimento facial com dlib por linha de comando é tão simples quanto fazer o face detection. Começando os parâmetros com as opções disponíveis, pode-se (e talvez se deva) passar um número de cpu, da mesma forma que para o face detection.  Outro parâmetro disponível é a tolerância (--tolerance), que é 0.6 por padrão. Pode ser necessário definir um limite para evitar falso-positivo. Uma linha de comando de exemplo seria:

recognition.webp

Simples e indolor.

Face recognition utilizando o módulo Python

A simplicidade para fazer reconhecimento facial com dlib com Python é a mesma. Quando utilizando em tempo-real, a melhor opção sem sombra de dúvidas é utilizar GPU, mas aí a compilação da dlib muda. Fora isso, podemos também utilizar Python 2.7, que também é outra configuração de compilação.

Para fazer um reconhecimento facial a partir de imagens, utiliza-se algo como isto:

import face_recognition

its_me      = face_recognition.load_image_file("djames.jpg")
me_encoding = face_recognition.face_encodings(its_me)[0]

unknown_picture       = face_recognition.load_image_file("another_picture.jpg")
unknown_face_encoding = face_recognition.face_encodings(unknown_picture)[0]

results = face_recognition.compare_faces([my_face_encoding], unknown_face_encoding)

if results[0] == True:
    print("It's me!")
else:
    print("It's not  me!")

Completamente simples; seleciona modelo, codifica, seleciona alvo, codifica, compara. Só isso!

Reconhecimento facial com dlib a partir da webcam

Para uma brincadeira mais interessante, vou dispor o código para receber como parâmetro uma foto sua, então abre-se a webcam e faz-se o reconhecimento. Tem aplicações interessantes, vou fazer outro artigo a respeito só para mostrar uma delas.

Podemos carregar várias fotos de pessoas diferentes, eu coloquei só 2 minhas mesmo e o resultado é a imagem de destaque desse artigo.

import face_recognition
import cv2

video_capture = cv2.VideoCapture(0)

djames     = face_recognition.load_image_file("/home/djames/jpg/perfil_dj.jpg")
djames_enc = face_recognition.face_encodings(djames)[0]

outra_pessoa     = face_recognition.load_image_file("/home/djames/me_again.jpg")
outra_pessoa_enc = face_recognition.face_encodings(outra_pessoa)[0]

known_face_encodings = [
    djames_enc,
    outra_pessoa_enc
]

#usei 2 fotos minhas, portanto:
known_face_names = [
    "djames",
    "djames"
]

face_locations = []
face_encodings = []
face_names = []
process_this_frame = True

while True:
    ret, frame      = video_capture.read()
    small_frame     = cv2.resize(frame, (0, 0), fx=0.25, fy=0.25)
    rgb_small_frame = small_frame[:, :, ::-1]

    if process_this_frame:
        face_locations = face_recognition.face_locations(rgb_small_frame)
        face_encodings = face_recognition.face_encodings(rgb_small_frame, face_locations)

        face_names = []
            matches = face_recognition.compare_faces(known_face_encodings, face_encoding)
            name = "Estranho"

            if True in matches:
                first_match_index = matches.index(True)
                name = known_face_names[first_match_index]

            face_names.append(name)

    process_this_frame = not process_this_frame

    for (top, right, bottom, left), name in zip(face_locations, face_names):
        top *= 4
        right *= 4
        bottom *= 4
        left *= 4

        cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)

        cv2.rectangle(frame, (left, bottom - 35), (right, bottom), (0, 0, 255), cv2.FILLED)
        font = cv2.FONT_HERSHEY_DUPLEX
        cv2.putText(frame, name, (left + 6, bottom - 6), font, 1.0, (255, 255, 255), 1)

    cv2.imshow('Video', frame)

    # letra 'q' para sair
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

video_capture.release()
cv2.destroyAllWindows()

Terei que fazer um vídeo desse material, devo colocar em breve no nosso canal DobitAoByteBrasil no youtube.

Inscreva-se no nosso canal Manual do Maker no YouTube.

Também estamos no Instagram.

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.