Detecção Facial com Deep Learning
Detecção facial com deep learning é uma das aplicações mais importantes de visão computacional. Ela consiste em detectar a presença de rostos em imagens ou vídeos. Após ser detectada, a face localizada pode ser usada em tarefas de reconhecimento de identidade, análise de emoções, identificação de gênero, pose, etc.
A detecção facial tem inúmeras aplicações. Obviamente, muitas delas são na área de segurança, mas outros campos também podem se beneficiar bastante dessa técnica.
Desenvolver um modelo de detecção facial do zero pode ser uma tarefa difícil. Ela envolve acesso a dados e recursos computacionais caros. Para contornar esse problema, uma solução simples e barata é o uso de modelos pré-treinados.
Existem vários modelos classificadores pré-treinados disponíveis para detecção facial. Em posts anteriores, usamos o classificador Haar Cascade e o excelente YOLO Faces. Neste post, apresentaremos outra opção: a rede neural do tipo deep learning MTCNN (Multi-Task Cascaded Convolutional Neural Network).
Bibliotecas
pip install mtcnn numpy opencv-python Pillow
O MTCNN roda em cima do Keras. Portanto, na primeira vez que você o usar, é provável que precise instalar o Keras ou TensorFlow se eles não estiverem em seu sistema.
Detecção Facial em Código
Para usar o MTCNN, primeiro fazemos as importações necessárias e iniciamos o classificador.
import cv2
from mtcnn.mtcnn import MTCNN
import numpy as np
from PIL import Image
detector = MTCNN()
Faremos a detecção em imagens primeiro e depois em vídeo. Para realizar a detecção em uma imagem, basta abri-la com Pillow. Ela deve ser convertida para RGB para garantir bons resultados. O classificador também funciona melhor se elas estiverem no formato de NumPy array.
file = 'LOCAL DA SUA IMAGEM'
image = Image.open(file)
image = image.convert('RGB')
img = np.asarray(image)
Em seguida, aplicamos o classificador.
faces = detector.detect_faces(img)
Quando o classificador detecta rostos, ele retorna uma lista com várias informações, como mostrado no exemplo abaixo:
[{'box': [557, 161, 35, 50], 'confidence': 0.9327843189239502, 'keypoints': {'left_eye': (564, 179), 'right_eye': (581, 181), 'nose': (567, 189), 'mouth_left': (562, 199), 'mouth_right': (577, 202)}}]
Essa lista contém os dados para definir caixas delimitadoras localizando os rostos na imagem, o intervalo de confiança da classificação feita e dados adicionais indicando a posição de pontos-chave dos rostos (boca, nariz e olhos). Usaremos essas informações a seguir.
Caixas Delimitadoras
Para adicionar as caixas delimitadoras numa imagem com rostos, usamos um for loop.
if faces:
for face in faces:
x1, y1, width, height = face['box'] # pega as coordenadas das caixas delimitadoras
prob = round(face['confidence'], 3)
if prob > 0.8:
x1, y1 = abs(x1), abs(y1)
x2, y2 = x1 + abs(width), y1 + abs(height)
cv2.rectangle(img, (x1, y1), (x2, y2), (255, 255, 255), 2) # usa as coordenadas para desenhar caixas
cv2.putText(img, str(
prob), (x1, y2), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
img = Image.fromarray(np.uint8(img)).convert('RGB') # reconverte imagem
img.save('nova_imagem.jpg') # salva imagem
Basicamente, o loop parte dos dados encontrados pelo classificador e usa o OpenCV para desenhar uma caixa delimitadora nas coordenadas onde cada rosto foi localizado. No trecho de código acima, também adicionamos os intervalos de confiança para cada rosto detectado. Após a execução do loop, salvamos a imagem com as caixas delimitadoras. Veja alguns exemplos de resultados abaixo.
Pontos-Chave Faciais
Para adicionar outros dados retornados pelo classificador (localização de olhos, nariz e boca), precisamos expandir um pouco nosso for loop como mostrado a seguir. As expansões estão com as linhas marcadas:
if faces:
for face in faces:
print(face)
x1, y1, width, height = face['box']
nose = face['keypoints']['nose'] # nariz
mouth_right = face['keypoints']['mouth_right'] # ponto boca direita
mouth_left = face['keypoints']['mouth_left'] # ponto boca esquerda
right_eye = face['keypoints']['right_eye'] # olho direito
left_eye = face['keypoints']['left_eye'] # olho esquerdo
prob = round(face['confidence'], 3)
if prob > 0.8:
x1, y1 = abs(x1), abs(y1)
x2, y2 = x1 + abs(width), y1 + abs(height)
cv2.rectangle(img, (x1, y1), (x2, y2), (255, 255, 255), 2)
cv2.circle(img, mouth_right, 5, (255, 255, 255), -1)
cv2.circle(img, mouth_left, 5, (255, 255, 255), -1)
cv2.circle(img, nose, 5, (255, 255, 255), -1)
cv2.circle(img, right_eye, 5, (255, 255, 255), -1)
cv2.circle(img, left_eye, 5, (255, 255, 255), -1)
cv2.putText(img, str(
prob), (x1, y2), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
img = Image.fromarray(np.uint8(img)).convert('RGB')
img.save('nova_imagem.jpg') # salva imagem
E aqui estão alguns resultados com caixas delimitadoras e pontos-chave marcando olhos, nariz e pontos laterais da boca de cada rosto detectado.
Detecção Facial em Video
Evidentemente, além de fazer detecção facial em imagens, podemos fazê-las em vídeos. Para isso, passamos o código definido anteriormente para dentro de uma função. Ela tem algumas modificações (linha 4) no início para converter os frames do vídeo para o formato apropriado.
def detecta_faces(frame):
"""Detecta faces com deep learning"""
image = Image.fromarray(np.uint8(frame)).convert('RGB')
img = np.asarray(image)
faces = detector.detect_faces(img)
if faces:
for face in faces:
print(face)
x1, y1, width, height = face['box']
nose = face['keypoints']['nose']
mouth_right = face['keypoints']['mouth_right']
mouth_left = face['keypoints']['mouth_left']
right_eye = face['keypoints']['right_eye']
left_eye = face['keypoints']['left_eye']
prob = round(face['confidence'], 3)
if prob > 0.8:
x1, y1 = abs(x1), abs(y1)
x2, y2 = x1 + abs(width), y1 + abs(height)
cv2.rectangle(img, (x1, y1), (x2, y2), (255, 255, 255), 2)
cv2.circle(img, mouth_right, 5, (255, 255, 255), -1)
cv2.circle(img, mouth_left, 5, (255, 255, 255), -1)
cv2.circle(img, nose, 5, (255, 255, 255), -1)
cv2.circle(img, right_eye, 5, (255, 255, 255), -1)
cv2.circle(img, left_eye, 5, (255, 255, 255), -1)
cv2.putText(img, str(
prob), (x1, y2), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
return img
Depois, precisamos escrever um trecho de código para realizar a leitura do vídeo e aplicar a função.
path_name = 'LOCAL_DO_SEU_VIDEO_AQUI.mp4'
# realiza leitura de vídeo com OpenCV
video_cap = cv2.VideoCapture(path_name)
while True:
ret, frame = video_cap.read()
controlkey = cv2.waitKey(1)
if not ret:
break
detections = detecta_faces(frame) # detecta faces em cada frame
cv2.imshow("Frame", detections) # exibe vídeo
if cv2.waitKey(1) == ord("q"):
break
video_cap.release()
cv2.destroyAllWindows()
Abaixo mostramos um pequeno resultado.