Introdução à Detecção Facial com MTCNN e Flask A detecção de faces é uma tarefa fundamental em visão computacional, com aplicações em segurança, organização de fotos e interação humano-computador. O MTCNN (Multi-task Cascaded Convolutional Networks) é um modelo popular e eficiente para essa finalidade. Este artigo demonstra como integrar o MTCNN em um serviço web usando o framework Flask, permitindo a detecção de faces em imagens locais ou remotas.
Detecção de Faces em Imagens Locais Para começar, vamos exemplificar a detecção de faces em uma imagem armazenada localmente. O MTCNN retorna uma lista de dicionários, onde cada dicionário representa um rosto detectado, incluindo suas coordenadas (box), nível de confiança (confidence) e pontos-chave (keypoints) como olhos, nariz e boca.
import cv2
from mtcnn.mtcnn import MTCNN
# Carrega a imagem e converte para RGB (MTCNN espera RGB)
caminho_imagem = './face.png'
imagem_rgb = cv2.cvtColor(cv2.imread(caminho_imagem), cv2.COLOR_BGR2RGB)
# Inicializa o detector MTCNN
detector_facial = MTCNN()
resultados_detecao = detector_facial.detect_faces(imagem_rgb)
# Imprime os detalhes dos rostos detectados
print(resultados_detecao)
O resultado da detecção é uma estrutura como a seguinte, mostrando as caixas delimitadoras, a confiança e os pontos-chave para cada rosto:
[{'box': [283, 295, 43, 49], 'confidence': 0.9999926090240479, 'keypoints': {'left_eye': (297, 311), 'right_eye': (317, 311), 'nose': (308, 322), 'mouth_left': (299, 332), 'mouth_right': (316, 332)}},
{'box': [748, 436, 49, 54], 'confidence': 0.9999852180480957, 'keypoints': {'left_eye': (765, 456), 'right_eye': (786, 456), 'nose': (776, 467), 'mouth_left': (767, 477), 'mouth_right': (783, 477)}}]
# ... (conteúdo omitido para brevidade)
Visualizando os Resultados da Detecção Para verificar visualmente as detecções, é útil desenhar os retângulos delimitadores e os pontos-chave na imagem original. O OpenCV é empregado para essas operações gráficas e para salvar a imagem processada.
import cv2
from mtcnn.mtcnn import MTCNN
caminho_imagem_entrada = './face.png'
imagem_com_deteccoes = cv2.cvtColor(cv2.imread(caminho_imagem_entrada), cv2.COLOR_BGR2RGB)
detector_rostos = MTCNN()
deteccoes_encontradas = detector_rostos.detect_faces(imagem_com_deteccoes)
for rosto_info in deteccoes_encontradas:
x_pos, y_pos, largura, altura = rosto_info['box']
# Desenha o retângulo delimitador
cv2.rectangle(imagem_com_deteccoes, (x_pos, y_pos), (x_pos + largura, y_pos + altura), (0, 255, 0), 2) # Cor verde
# Adiciona a confiança
cv2.putText(imagem_com_deteccoes, '{:.2f}'.format(rosto_info['confidence']), (x_pos, y_pos - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2) # Cor verde
# Desenha os pontos-chave
for ponto, coordenadas in rosto_info['keypoints'].items():
cv2.circle(imagem_com_deteccoes, (coordenadas[0], coordenadas[1]), 5, (0, 0, 255), -1) # Cor azul, preenchido
# Converte de volta para BGR antes de salvar
imagem_final = cv2.cvtColor(imagem_com_deteccoes, cv2.COLOR_RGB2BGR)
cv2.imwrite('deteccoes_visuais.jpg', imagem_final)
Após executar este script, um arquivo deteccoes_visuais.jpg será gerado, exibindo os retângulos e pontos-chave sobre cada rosto detectado.
Detecção de Faces em Imagens Remotas (URLs) Um cenário comum é a necessidade de detectar faces em imagens acessíveis via URL. Para isso, utilizamos a biblioteca requests para baixar a imagem e numpy juntamente com opencv para processá-la em memória.
import cv2
from mtcnn.mtcnn import MTCNN
import requests
import numpy as np
url_da_imagem_remota = 'http://seu_servidor_de_imagens:8080/exemplo_rosto.jpg' # Substitua pela sua URL
response_imagem = requests.get(url_da_imagem_remota)
# Converte os bytes da imagem em um array numpy e decodifica com OpenCV
array_bytes_img = np.frombuffer(response_imagem.content, np.uint8)
imagem_decodificada = cv2.imdecode(array_bytes_img, cv2.IMREAD_COLOR)
imagem_processada_rgb = cv2.cvtColor(imagem_decodificada, cv2.COLOR_BGR2RGB)
detector_mtcnn_remoto = MTCNN()
rostos_encontrados = detector_mtcnn_remoto.detect_faces(imagem_processada_rgb)
print(rostos_encontrados)
O resultado será uma saída JSON similar à detecção de imagem local, mas para a imagem obtida da URL.
Construindo um Serviço Flask Básico Antes de integrar o MTCNN, vamos criar uma aplicação Flask simples. Isso serve como base para entender como os endpoints são definidos e como a aplicação pode ser executada.
from flask import Flask
# Inicializa a aplicação Flask
app_simples = Flask(__name__)
# Define uma rota padrão
@app_simples.route('/')
def mensagem_inicial():
return 'Bem-vindo ao serviço Flask básico!'
# Inicia o servidor web
if __name__ == '__main__':
app_simples.run(host='0.0.0.0', port=5000, debug=True) # debug=True para desenvolvimento
Ao executar este script, o Flask iniciará um servidor em http://0.0.0.0:5000/ (ou http://127.0.0.1:5000/), e acessar a URL no navegador retornará a mensagem "Bem-vindo ao serviço Flask básico!".
Integrando o MTCNN em um Serviço Flask Agora, combinaremos a funcionalidade de detecção de faces de URL com o framework Flask para criar uma API RESTful. Esta API receberá o nome de uma imagem (servida por um servidor de arquivos externo, como Nginx ou Apache) e retornará os resultados da detecção facial em formato JSON. from flask import Flask, jsonifyimport requestsimport osimport cv2import numpy as npfrom mtcnn.mtcnn import MTCNNapp_detector_facial = Flask(__name__)# O modelo MTCNN pode ser inicializado uma única vez para otimizar o desempenhomodelo_detector = MTCNN()# Define a URL base onde as imagens estão hospedadasURL_BASE_IMAGENS = 'http://seu_servidor_de_imagens:8080/' # Substitua pela sua URL basedef realizar_deteccao(nome_da_imagem: str): """ Realiza a detecção facial em uma imagem remota. """ url_completa_imagem = os.path.join(URL_BASE_IMAGENS, nome_da_imagem) try: resposta_get = requests.get(url_completa_imagem, timeout=10) # Adiciona timeout resposta_get.raise_for_status() # Lança exceções para status de erro HTTP dados_imagem_binarios = np.frombuffer(resposta_get.content, np.uint8) imagem_cv = cv2.imdecode(dados_imagem_binarios, cv2.IMREAD_COLOR) if imagem_cv is None: return None, "Não foi possível decodificar a imagem." imagem_rgb = cv2.cvtColor(imagem_cv, cv2.COLOR_BGR2RGB) rostos_identificados = modelo_detector.detect_faces(imagem_rgb) return rostos_identificados, None except requests.exceptions.RequestException as e: return None, f"Erro ao acessar a imagem: {e}" except Exception as e: return None, f"Erro interno de processamento: {e}"@app_detector_facial.route('/detectar_face/<nome_imagem_arquivo>')def endpoint_detecao_face(nome_imagem_arquivo): """ Endpoint para detectar faces em uma imagem remota e retornar JSON. """ deteccoes, erro = realizar_deteccao(nome_imagem_arquivo) if erro: return jsonify({'status': 'erro', 'mensagem': erro}), 500 return jsonify({'status': 'sucesso', 'deteccoes': deteccoes})if __name__ == '__main__': app_detector_facial.run(host='0.0.0.0', port=5001, debug=True)```<p>Neste código, o modelo MTCNN é instanciado uma única vez globalmente para evitar recargas desnecessárias, o que melhora o desempenho. O endpoint /detectar_face/<nome_imagem_arquivo></p></nome_imagem_arquivo> recebe o nome do arquivo da imagem como parte da URL e invoca a função realizar_deteccao. Os resultados são então retornados em formato JSON.
Consumindo o Serviço Flask com Python Para interagir com o serviço de detecção facial, podemos usar um script Python cliente que faz uma requisição HTTP GET ao endpoint do Flask. O cliente pode então processar os resultados JSON recebidos, por exemplo, desenhando as caixas delimitadoras na imagem original e salvando-a. import requests import numpy as np import cv2 import json
URL do seu serviço Flask de detecção facial
URL_SERVICO_FLASK = 'http://127.0.0.1:5001/detectar_face/exemplo_rosto.jpg' # Substitua pela sua URL
URL da imagem original para visualização local (pode ser a mesma URL base do servidor)
URL_IMAGEM_ORIGINAL = 'http://seu_servidor_de_imagens:8080/exemplo_rosto.jpg'
Faz a requisição ao serviço Flask
response_flask = requests.get(URL_SERVICO_FLASK) dados_deteccao = response_flask.json() # Assume que o Flask retorna JSON
print("Resultados da detecção recebidos do Flask:") print(json.dumps(dados_deteccao, indent=2))
--- Visualização local dos resultados ---
if dados_deteccao['status'] == 'sucesso':
Baixa a imagem original para desenhar as detecções
response_original = requests.get(URL_IMAGEM_ORIGINAL) array_bytes_img_original = np.frombuffer(response_original.content, np.uint8) imagem_para_desenhar = cv2.imdecode(array_bytes_img_original, cv2.IMREAD_COLOR)
if imagem_para_desenhar is not None: for info_rosto in dados_deteccao['deteccoes']: x, y, w, h = info_rosto['box'] cv2.rectangle(imagem_para_desenhar, (x, y), (x + w, y + h), (0, 255, 0), 2) # Verde cv2.putText(imagem_para_desenhar, '{:.2f}'.format(info_rosto['confidence']), (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2) # Verde for ponto_chave, coords in info_rosto['keypoints'].items(): cv2.circle(imagem_para_desenhar, (coords[0], coords[1]), 5, (0, 0, 255), -1) # Azul
cv2.imwrite('imagem_com_deteccoes_remotas.jpg', imagem_para_desenhar) print("Imagem com detecções salvas como 'imagem_com_deteccoes_remotas.jpg'") else: print("Erro: Não foi possível carregar a imagem original para visualização.") else: print(f"Erro no serviço Flask: {dados_deteccao['mensagem']}")
Este script cliente primeiro consulta a API do Flask e depois, usando os dados de detecção retornados, carrega novamente a imagem original para desenhar as caixas delimitadoras e os pontos-chave, salvando a imagem resultante localmente.