sexta-feira, 12 de maio de 2017

Detecção de faces usando OpenCV

A detecção de faces é uma tarefa muito comum em diversas programas de visão computacional. O Facebook, por exemplo, detecta faces para sugerir a identificação de pessoas nas fotos adicionadas por seus usuários. Várias câmeras digitais detectam rostos para melhorar a qualidade da fotografia. Esta câmera, por exemplo, tira fotos quando as pessoas sorriem.

O OpenCV é uma biblioteca muito usada em aplicações de visão computacional, especialmente aquelas que requerem interação em tempo real. Python é uma das linguagens com suporte oficial e possui uma interface bastante prática para trabalhar com detecção de faces.

Antes de tudo, vamos diferenciar duas tarefas muito parecidas a primeira vista: detecçãos e reconhecimento/identificação.

  • Detecção de faces consiste em dizer onde existe uma face em uma imagem. Ou seja, a localização da face na imagem é o resultado final. A entrada é uma imagem ``natural'' que pode ou não conter uma face.
  • Reconhecimento/Identificação consiste em dizer quem está retratado na imagem. Ou seja, o nome de uma pessoa específica é o resultafo final. Normalmente a entrada já é uma imagem contendo somente a face que desejamos identificar.

Detecção de faces em imagens

Nós humanos conseguimos reconhecer faces instintivamente. Podemos descrever uma face, listar quais são as partes (olhos, nariz, boca, ect) de uma face e mesmo reconhecer a mesma pessoa em presença de objetos externos (óculos, chapéu, etc). Apesar de existir, aparentemente, uma programação ``natural'' para que possamos identificar rostos, conseguimos fazer o mesmo tipo de reconhecimento com qualquer objeto que observamos. Ou seja, aprendemos a reconhecer objetos baseado em exemplos e conseguimos descrevê-los internamente de modo a reconhecer variações dos objetos.

A primeira etapa de um sistema de detecção de faces consiste em extrair um conjunto de características que possam diferenciar imagens com faces de imagens sem faces. Dois métodos muito populares estão presentes no OpenCV: Haar Cascades e LBP. Como as faces podem ter vários tamanho, é feita uma análise multi-escala da imagem, ou seja, executamos o mesmo algoritmo de detecção de faces em versões redimensionadas da imagem. Desta maneira, mesmo que um objeto seja muito pequeno ou muito grande, ele será detectado em alguma escala.

Para ``aprendermos'' um objeto precisamos observar alguns exemplos positivos (variações do objeto de interesse), e exemplos negativos (outros objetos diferentes, incluindo alguns que possam ser confundidos com o de interesse). No caso da detecção de faces, precisamos então de conjuntos de imagens que contenham faces e de imagens sem faces. Esta etapa, chamada de treinamento, é uma das mais importantes de um sistema de detecção de faces. O resultado final desta etapa é um classificador que diz se uma imagem possui ou não uma face. Este classificador é aplicado em todos os pontos da imagem para podermos dizer onde estão localizadas as faces.

Por fim, carregamos o classificador treinado na etapa anterior e usamos para encontrar faces. Esta etapa é a única que ocorre durante a execução do sistema de reconhecimento em si. O treinamento sempre é feito em um momento anterior, de preferência supervisionado por um especialista.

Resumindo, um detecção de faces ocorre em dois momentos. No primeiro, o treinamento, usamos exemplos de imagens para ``aprender'' o que é uma face. No segundo usamos o modelo aprendido para detectar faces em imagens. Ao invés de usarmos os próprios pixels para representar as faces extraímos um conjunto de características que facilitem decidir se uma imagem é ou não uma face.

Implementação no OpenCV

O treinamento é uma etapa muito custosa, tanto devido à construção do conjunto de imagens exemplo quanto à determinação do melhor classificador e extrator de características. Felizmente o OpenCV já possui alguns classificadores treinados e prontos para uso. A classe CascadeClassifier é usada para detecção de faces. Suas duas principais funções são load, que carrega um modelo treinado, e detectMultiScale, que faz a detecção e devolve uma lista de retângulos que contém faces.

Os modelos treinados podem ser baixados do repositório do OpenCV no Github. Existem dois tipos de modelos pré-treinados,haarcascades e lbpcascades, para diversas situações. Estamos interessados em faces vistas de frente, então usaremos o modelo lbpcascades/lbpcascades_frontalface_improved.xml. Poderíamos usar também o equivalente encontrado na pasta haarcascades, porém nos testes que fiz o detector baseado em LBP funcionou melhor.

O código abaixo carrega o modelo já treinado (salvo com o nome faces_lbp.xml), o aplica em uma imagem carregada do disco e desenha quadrados nas faces de todos os presentes.

import cv2

# Carrega imagem
img = cv2.imread('foto.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# Carrega detector de faces usando LBP.
cls = cv2.CascadeClassifier('faces_lbp.xml')
faces = cls.detectMultiScale(img_gray)

for face in faces:
    x, y, w, h = face
    # Argumentos: imagem, topo_esquerdo, baixo_direito, cor(BGR),
espessura
    cv2.rectangle(img, (x, y), (x+w, y+h), (0, 0, 255), 2 )

cv2.imwrite('foto_face.png', img)
Funciona mesmo!

Esta foi uma pequena introdução sobre detecção de faces usando OpenCV. Possivelmente farei novos posts sobre processamento de imagens e visão computacional no futuro, então se gostou compartilhe ou deixe um comentário. Até a próxima.

Mais informações

Os seguintes artigos podem ser ótimas primeiras leituras para maiores detalhes em detecção de faces.

Viola, P., & Jones, M. (2001). "Rapid object detection using a boosted cascade of simple features". In Computer Vision and Pattern Recognition, 2001. CVPR 2001.

Puttemans Steven, Can Ergun and Toon Goedeme, "Improving Open Source Face Detection by Combining an Adapted Cascade Classification Pipeline and Active Learning", VISAPP 2017

Resumo sobre LBP (bom, este não é clássico... mas é uma explicação simples do que é LBP.)

Nenhum comentário:

Postar um comentário