Em visão computacional, detecção facial se refere ao problema de detectar rostos humanos em imagens ou vídeos. Esse foi o tema que tratamos aqui. Já o reconhecimento facial se refere à identificação de um indivíduo usando seu rosto.
Com os avanços em inteligência artificial, a criação de aplicações com reconhecimento facial se tornaram muito intuitivas e de fácil implementação. Neste post, usaremos o Python para reconhecimento facial com o auxílio de algumas bibliotecas e modelos de deep learning pré-trenados.
Reconhecimento facial com Python
O processo de reconhecimento facial geralmente envolve três etapas.
- Detecção de rostos: detecta a presença de rostos e obtém suas coordenadas/localizações exatas.
- Extração de recursos: extrai características específicas das faces localizadas. Quando isso é feito com deep learning, a rede usa a imagem do rosto da pessoa como entrada e gera um vetor representacional de suas características mais importantes. Esse vetor é chamado de face embedding (incorporação de face). Durante seu treinamento, a rede aprende a gerar vetores semelhantes para faces semelhantes. Consequentemente, os vetores que ela associa às faces semelhantes estão próximos no espaço vetorial.
Comparação de rostos: A partir da criação de embeddings para os rostos na fase de treinamento da rede, o próximo passo é reconhecer uma nova imagem. Para isso, a rede já treinada é usada para calcular o face embedding de uma nova imagem e então comparar seu resultado com os embeddings que ela possui. Um rosto é reconhecido quando seu embedding é próximo a um dos embeddings da rede.
Pré-requisitos
Usaremos as seguintes bibliotecas:
- openCV
- imutils
- face_recognition
Para instalações:
pip install opencv-python face_recognition imutils
OpenCV, como mencionado anteriormente, é uma biblioteca de processamento de imagem e vídeo que contém vários algoritmos que podem ser usados para múltiplas tarefas, incluindo detecção facial. Imutils contém algumas funções para o openCV.
A biblioteca face_recognition, como o nome indica, é apropriada para reconhecimento facial. Ela já tem modelos pré-treinados e facilita imensamente o processo.
Para saber mais sobre essas bibliotecas, clique aqui.
Reconhecimento facial com Python na prática
Crie um arquivo do Python com o nome que desejar (p. ex: reconhecimento_facial.py). No início do arquivo, é preciso importar as bibliotecas e alguns módulos como mostrado abaixo.
import cv2
import face_recognition
from imutils import paths
import os
import pickle
O reconhecimento facial que faremos parte de modelos pré-treinados disponíveis através das bibliotecas openCV e facial_recognition. Porém, é necessário expandi-los com dados sobre pessoas que desejamos reconhecer.
Para cada pessoa, é preciso criar uma pasta com seu nome e, dentro da pasta, guardas algumas imagens dela. Apenas 1 imagem é suficiente, mas nós usaremos 5. Todas as pastas com imagens de pessoas que queremos reconhecer devem ser postas numa pasta chamada Image.
Estrutura das pastas com imagens para treinar a rede. Dentro da pasta Image existem duas pastas: dede e didi, cada uma com 5 imagens.
No nosso exemplo, dentro da pasta Image temos duas pastas: didi e dede, como mostrado acima. Na pasta didi existem 5 imagens do Renato Aragão e, na pasta dede, 5 do Dedé Santana. As imagens são mostradas abaixo.
Extração de recursos
Em seguida, é preciso extrair os recursos de cada imagem. Para isso, definimos a localização das pastas e criamos duas listas, uma para armazenar seus embeddings (encodings) e outra para os nomes.
imagePaths = list(paths.list_images('Images'))
knownEncodings = []
knownNames = []
Depois, usamos um loop e, com auxílio da biblioteca face_recognition, localizamos um rosto em cada imagem e calculamos seus embeddings (linhas em destaque). Após isso, os novos dados são armazenados num arquivo pickle para serem usados posteriormente.
for (i, imagePath) in enumerate(imagePaths):
name = imagePath.split(os.path.sep)[-2]
image = cv2.imread(imagePath)
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
boxes = face_recognition.face_locations(rgb,model='hog')
encodings = face_recognition.face_encodings(rgb, boxes)
for encoding in encodings:
knownEncodings.append(encoding)
knownNames.append(name)
#salva emcodings com seus nomes
data = {"encodings": knownEncodings, "names": knownNames}
#salva dados com pickle para uso posteriormente
f = open("face_enc", "wb")
f.write(pickle.dumps(data))
f.close()
Reconhecimento Facial
Após a escrita dos comandos para o treinamento da rede e criação dos novos embeddings, é preciso escrever os comandos para o reconhecimento facial. O reconhecimento é feito usando novas imagens das pessoas que a rede aprende na fase de treinamento. Esse processo usa um classificador Haar Cascade como descrito aqui. O arquivo do classificador pode ser baixado aqui.
É preciso selecionar o classificador e carregá-lo no openCV (cv2).
classifier = "haarcascade_frontalface_alt2.xml"
faceCascade = cv2.CascadeClassifier(classifier)
Em seguida, abrimos o arquivo pickle definido anteriormente. Também é preciso selecionar uma nova imagem para reconhecimento. No nosso exemplo, ela foi salva numa pasta chamada Images_test.
data = pickle.loads(open('face_enc', "rb").read())
image = cv2.imread("Images_test/img1.jpeg")
Depois, a imagem precisa ser convertida para uma escala de cinzas. O passo seguinte é a aplicação do classificador de detecção de rostos como descrito aqui.
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
faces = faceCascade.detectMultiScale(gray,
scaleFactor=1.1,
minNeighbors=5,
minSize=(60, 60),
flags=cv2.CASCADE_SCALE_IMAGE)
A última etapa é a localização de embeddings (encodings) próximos do embedding calculado para a nova imagem. O código é mostrado abaixo comentado. A sua execução salva uma nova imagem com o nome reconhecido. Essa imagem também tem um retângulo indicando a posição do rosto reconhecido. Em caso de falha no reconhecimento, a imagem aparece com nome “Desconhecido”.
encodings = face_recognition.face_encodings(rgb)
names = []
for encoding in encodings:
#Compara encoding with encodings no dicionário data["encodings"] e salva Matches como True
matches = face_recognition.compare_faces(data["encodings"], encoding)
# salva nome como desconhecido para caso de não encontrar rosto correspondente
name = "Desconhecido"
# verifica se achou rostos correspondentes
if True in matches:
# acha posições dos rostos correspondentes
matchedIdxs = [i for (i, b) in enumerate(matches) if b]
counts = {}
# acha o nome do rosto com correspondência maior
for i in matchedIdxs:
name = data["names"][i]
counts[name] = counts.get(name, 0) + 1
name = max(counts, key=counts.get)
# salva nome encontrado
names.append(name)
# cria um retângulo no rosto encontrado
for ((x, y, w, h), name) in zip(faces, names):
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)
# salva a imagem testada com o retângulo indicando a posição do rosto.
cv2.imwrite(f'{name}.jpeg', image)
Essas são as imagens que testamos. Adicionamos propositalmente uma imagem do Zacarias para verificar se a rede seria capaz de classificá-la como desconhecida.
Aqui estão os resultados obtidos. A rede reconheceu corretamente o Didi e Dedé e classificou o Zacarias como Desconhecido.
Conclusões
Neste post, mostramos um exemplo de reconhecimento facial com Python. O desenvolvimento de várias bibliotecas poderosas na área de computação visual tornaram esse processo bastante simples. Para quem tiver interesse, uma expansão viável para esse código é modificá-lo para reconhecer pessoas em vídeos.
O desenvolvimento deste post se baseou em posts anteriores que podem ser encontrados aqui e aqui.