Fazendo o seu próprio Sistema de Reconhecimento de Rosto

O reconhecimento facial é a última tendência no que diz respeito à autenticação do usuário. A Apple lançou recentemente o novo iPhone X que usa o Face ID para autenticar usuários. O OnePlus 5 está obtendo o recurso de Desbloqueio de Rosto do OnePlus 5T em breve. E o Baidu está usando reconhecimento facial em vez de cartões de identificação para permitir que seus funcionários entrem em seus escritórios . Essas aplicações podem parecer mágicas para muitas pessoas. Mas neste artigo buscamos desmistificar o assunto, ensinando-lhe como fazer sua própria versão simplificada de um sistema de reconhecimento de rosto em Python.

Github link para aqueles que não gostam de ler e só querem o código

fundo

Antes de entrar nos detalhes da implementação, quero discutir os detalhes do FaceNet. Qual é a rede que usaremos em nosso sistema.

FaceNet

FaceNet é uma rede neural que aprende um mapeamento de imagens de rosto para um espaço Euclidiano compacto onde as distâncias correspondem a uma medida de similaridade de face. Ou seja, as imagens de duas faces similares são menores que a distância entre elas.

Perda de Triplet

O FaceNet usa um método de perda distinto chamado perda de tríplice para calcular a perda. A perda de Triplet minimiza a distância entre uma âncora e uma imagem positiva, que contém a mesma identidade e maximiza a distância entre a âncora e uma imagem negativa, que contém identidades diferentes.

Figura 1: A equação da perda de Triplet

  • f (a) refere-se à codificação de saída da âncora
  • f (p) refere-se à codificação de saída do positivo
  • f (n) refere-se à codificação de saída do negativo
  • Alfa é uma constante usada para garantir que a rede não tente otimizar para f (a) – f (p) = f (a) – f (n) = 0.
  • […] + é igual a max (0, soma)

Redes Siamesas

Figura 2: Um exemplo de uma rede siamesa que usa imagens de faces como entrada e produz uma codificação de 128 números da imagem. Fonte: Coursera

FaceNet é uma rede siamesa. Uma rede siamesa é um tipo de arquitetura de rede neural que aprende como diferenciar entre duas entradas. Isso lhes permite aprender quais imagens são semelhantes e quais não são. Essas imagens podem conter rostos.

As redes síameses consistem em duas redes neurais idênticas, cada uma com os mesmos pesos exatos. Primeiro, cada rede leva uma das duas imagens de entrada como entrada. Então, as saídas das últimas camadas de cada rede são enviadas para uma função que determina se as imagens possuem a mesma identidade.

No FaceNet, isso é feito calculando a distância entre as duas saídas.

Implementação

Agora que esclarecemos a teoria, podemos pular diretamente na implementação.

Em nossa implementação, vamos usar o Keras e o Tensorflow . Além disso, estamos usando dois arquivos de utilitário que recebemos do repo de deeplearning.ai para abstrair todas as interações com a rede FaceNet .:

  • fr_utils.py contém funções para alimentar imagens para a rede e obter a codificação de imagens
  • inception_blocks_v2.py contém funções para preparar e compilar a rede FaceNet

Compilando a rede FaceNet

A primeira coisa que temos a fazer é compilar a rede FaceNet para que possamos usá-la para o nosso sistema de reconhecimento facial.

 importar os 
importar glob
importa numpy como np
importar cv2
Importar fluxo tensor como tf
de importação fr_utils *
de inception_blocks_v2 importar *
do back-up de importação de Keras como K
 K.set_image_data_format ('channels_first') 
 FRmodel = faceRecoModel (input_shape = (3, 96, 96)) 
 def triplet_loss (y_true, y_pred, alpha = 0.3): 
âncora positiva, negativa = y_pred [0], y_pred [1], y_pred [2]

pos_dist = tf.reduce_sum ( tf.square ( tf.subtract (âncora,
positivo)), eixo = -1)
neg_dist = tf.reduce_sum ( tf.square ( tf.subtract (âncora,
negativo)), eixo = -1)
basic_loss = tf.add ( tf.subtract (pos_dist, neg_dist), alfa)
loss = tf.reduce_sum ( tf.maximum (basic_loss, 0.0))

perda de retorno
 FRmodel.compile (optimizer = 'adam', loss = triplet_loss, metrics = ['accuracy']) 
load_weights_from_FaceNet (FRmodel)

Começaremos inicializando nossa rede com uma forma de entrada de (3, 96, 96). Isso significa que os canais Vermelho-Verde-Azul (RGB) são a primeira dimensão do volume de imagens alimentado na rede. E que todas as imagens que são alimentadas na rede devem ser de 96 x 96 pixels.

Em seguida, definiremos a função Triplet Loss. A função no trecho de código acima segue a definição da equação de perda de Triplet que definimos na seção anterior.

Se você não estiver familiarizado com nenhuma das funções Tensorflow usadas para executar o cálculo, recomendaria ler a documentação (para a qual eu adicionei links para cada função), pois melhorará sua compreensão do código. Mas a comparação da função com a equação na Figura 1 deve ser suficiente.

Uma vez que temos a nossa função de perda, podemos compilar o nosso modelo de reconhecimento de rosto usando Keras. E usaremos o otimizador Adam para minimizar a perda calculada pela função Triplet Loss.

Preparando um banco de dados

Agora que compilamos o FaceNet, vamos preparar um banco de dados de indivíduos que queremos que nosso sistema reconheça. Vamos usar todas as imagens contidas em nossas imagens diretório para nosso banco de dados de indivíduos.

NOTA: Nós só vamos usar uma imagem de cada indivíduo em nossa implementação. A razão é que a rede FaceNet é poderosa o suficiente para apenas precisar de uma imagem de um indivíduo para reconhecê-los!

 def prepare_database (): 
banco de dados = {}
 para arquivo em glob.glob ("images / *"): 
identity = os.path.splitext (os.path.basename (arquivo)) [0]
banco de dados [identidade] = img_path_to_encoding (arquivo, FRmodel)
 retornar banco de dados 

Para cada imagem, converteremos os dados da imagem em uma codificação de 128 números de flutuação. Fazemos isso chamando a função img_path_to_encoding . A função leva um caminho para uma imagem e alimenta a imagem para a nossa rede de reconhecimento facial. Em seguida, ele retorna a saída da rede, que é a codificação da imagem.

Uma vez que adicionamos a codificação de cada imagem ao nosso banco de dados, nosso sistema pode finalmente começar a reconhecer indivíduos!

Reconhecendo um rosto

Conforme discutido na seção Antecedentes, o FaceNet é treinado para minimizar a distância entre imagens do mesmo indivíduo e maximizar a distância entre imagens de diferentes indivíduos. Nossa implementação usa essa informação para determinar qual o particular que a nova imagem alimentada em nosso sistema é mais provável.

 def who_is_it (imagem, banco de dados, modelo): 
codificação = img_to_encoding (imagem, modelo)

min_dist = 100
identidade = nenhuma

# Loop sobre os nomes e codificações do dicionário de banco de dados.
para (nome, db_enc) em database.items ():
dist = np.linalg.norm (codificação db_enc)
 print ('distância para% s é% s'% (nome, dist)) 
 se dist <min_dist: 
min_dist = dist
identidade = nome

se min_dist> 0.52:
retorno Nenhum
outro:
retornar identidade

A função acima alimenta a nova imagem em uma função de utilidade chamada img_to_encoding . A função processa uma imagem usando FaceNet e retorna a codificação da imagem. Agora que temos a codificação, podemos encontrar o indivíduo ao qual a imagem provavelmente pertence.

Para encontrar o indivíduo, passamos por nosso banco de dados e calculamos a distância entre nossa nova imagem e cada indivíduo no banco de dados. O indivíduo com a menor distância para a nova imagem é então escolhido como o candidato mais provável.

Finalmente, devemos determinar se a imagem do candidato e a nova imagem contêm a mesma pessoa ou não. Uma vez que, no final do nosso ciclo, apenas determinamos o indivíduo mais provável. Este é o lugar onde o seguinte trecho de código entra em jogo.

 se min_dist> 0.52: 
retorno Nenhum
outro:
retornar identidade
  • Se a distância for superior a 0,52, então determinamos que o indivíduo na nova imagem não existe no nosso banco de dados.
  • Mas, se a distância for igual ou inferior a 0,52, então nós determinamos que eles são o mesmo indivíduo!

Agora, a parte complicada aqui é que o valor 0,52 foi alcançado através de teste e erro em meu nome para o meu conjunto de dados específico. O melhor valor pode ser muito menor ou ligeiramente maior e dependerá da sua implementação e dados. Eu recomendo experimentar diferentes valores e ver o que melhor se adequa ao seu sistema!

Criando um sistema usando reconhecimento de rosto

Agora que conhecemos os detalhes sobre como reconhecemos uma pessoa usando um algoritmo de reconhecimento de rosto, podemos começar a divertir-se com isso.

No repositório Github ligado ao início deste artigo, é uma demo que usa a webcam de um laptop para alimentar quadros de vídeo ao nosso algoritmo de reconhecimento de rosto. Uma vez que o algoritmo reconhece um indivíduo no quadro, a demonstração reproduz uma mensagem de áudio que acolhe o usuário usando o nome da imagem no banco de dados. A Figura 3 mostra um exemplo da demonstração em ação.

Figura 3: Uma imagem capturada no momento exato em que a rede reconheceu o indivíduo na imagem. O nome da imagem no banco de dados foi "skuli.jpg", de modo que a mensagem de áudio reproduzida foi "Bem-vindo skuli, tenha um bom dia!"

Conclusão

Até agora, você deve estar familiarizado com o funcionamento dos sistemas de reconhecimento de rosto e como fazer seu próprio sistema de reconhecimento de rosto simplificado usando uma versão pré-treinada da rede FaceNet em python!

Se você quiser brincar com a demonstração no repositório Github e adicionar imagens de pessoas que você conhece, então vá em frente e garfo o repositório.

Divirta-se com a demonstração e impressione todos os seus amigos com seu incrível conhecimento de reconhecimento facial!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *