Índice:

Reconhecimento facial em tempo real: um projeto de ponta a ponta: 8 etapas (com imagens)
Reconhecimento facial em tempo real: um projeto de ponta a ponta: 8 etapas (com imagens)

Vídeo: Reconhecimento facial em tempo real: um projeto de ponta a ponta: 8 etapas (com imagens)

Vídeo: Reconhecimento facial em tempo real: um projeto de ponta a ponta: 8 etapas (com imagens)
Vídeo: [PASSO A PASSO] Projeto prático de Machine Learning | Sistema de Reconhecimento Facial 2024, Julho
Anonim
Reconhecimento facial em tempo real: um projeto de ponta a ponta
Reconhecimento facial em tempo real: um projeto de ponta a ponta

Em meu último tutorial explorando OpenCV, aprendemos RASTREAMENTO AUTOMÁTICO DE OBJETOS DE VISÃO. Agora usaremos nosso PiCam para reconhecer rostos em tempo real, como você pode ver abaixo:

Imagem
Imagem

Este projeto foi feito com esta fantástica "Biblioteca Open Source Computer Vision", a OpenCV. Neste tutorial, vamos nos concentrar no Raspberry Pi (portanto, Raspbian como OS) e Python, mas também testei o código no Meu Mac e também funciona bem. O OpenCV foi projetado para eficiência computacional e com um forte foco em aplicativos de tempo real. Portanto, é perfeito para reconhecimento de rosto em tempo real usando uma câmera.

Para criar um projeto completo de Reconhecimento Facial, devemos trabalhar em 3 fases bem distintas:

  1. Detecção de rosto e coleta de dados
  2. Treine o reconhecedor
  3. Reconhecimento facial

O diagrama de blocos abaixo resume essas fases:

Imagem
Imagem

Etapa 1: BoM - Lista de materiais

Partes principais:

  1. Raspberry Pi V3 - US $ 32,00
  2. Módulo de vídeo da mini câmera OV5647 com sensor 1080p de 5 megapixels - US $ 13,00

Etapa 2: Instalando o Pacote OpenCV 3

Instalando o Pacote OpenCV 3
Instalando o Pacote OpenCV 3

Estou usando um Raspberry Pi V3 atualizado para a última versão do Raspbian (Stretch), então a melhor maneira de instalar o OpenCV é seguir o excelente tutorial desenvolvido por Adrian Rosebrock: Raspbian Stretch: Instale OpenCV 3 + Python em seu Raspberry Pi.

Tentei vários guias diferentes para instalar o OpenCV no meu Pi. O tutorial de Adrian é o melhor. Aconselho você a fazer o mesmo, seguindo passo a passo sua orientação.

Depois de terminar o tutorial de Adrian, você deve ter um ambiente virtual OpenCV pronto para executar nossos experimentos em seu Pi.

Vamos ao nosso ambiente virtual e confirmar se o OpenCV 3 está instalado corretamente.

Adrian recomenda executar o comando "source" cada vez que você abrir um novo terminal para garantir que suas variáveis de sistema foram configuradas corretamente.

fonte ~ /.profile

A seguir, vamos entrar em nosso ambiente virtual:

workon cv

Se vir o texto (cv) antes do prompt, você está no ambiente virtual cv:

(cv) pi @ framboesa: ~ $Adrian chama a atenção de que o ambiente virtual cv Python é totalmente independente e sequestrado da versão padrão do Python incluída no download do Raspbian Stretch. Portanto, quaisquer pacotes Python no diretório global de pacotes de sites não estarão disponíveis para o ambiente virtual cv. Da mesma forma, quaisquer pacotes Python instalados em pacotes de sites de cv não estarão disponíveis para a instalação global de Python

Agora, digite seu interpretador Python:

Pitão

e confirme se você está executando a versão 3.5 (ou superior)

Dentro do interpretador (o ">>>" aparecerá), importe a biblioteca OpenCV:

import cv2

Se nenhuma mensagem de erro for exibida, o OpenCV está instalado corretamente NO SEU AMBIENTE VIRTUAL PYTHON.

Você também pode verificar a versão do OpenCV instalada:

cv2._ version_

O 3.3.0 deve aparecer (ou uma versão superior que pode ser lançada no futuro). O Terminal PrintScreen acima mostra as etapas anteriores.

Etapa 3: Testar sua câmera

Testando sua câmera
Testando sua câmera

Depois de instalar o OpenCV em seu RPi, vamos testar para confirmar se sua câmera está funcionando corretamente.

Presumo que você já tenha uma PiCam instalada em seu Raspberry Pi.

Insira o código Python abaixo em seu IDE:

importar numpy como np

import cv2 cap = cv2. VideoCapture (0) cap.set (3, 640) # set Width cap.set (4, 480) # set Height while (True): ret, frame = cap.read () frame = cv2. flip (frame, -1) # Flip camera verticalmente gray = cv2.cvtColor (frame, cv2. COLOR_BGR2GRAY) cv2.imshow ('frame', frame) cv2.imshow ('gray', gray) k = cv2.waitKey (30) & 0xff if k == 27: # pressione 'ESC' para sair do break cap.release () cv2.destroyAllWindows ()

O código acima irá capturar o stream de vídeo que será gerado pela sua PiCam, exibindo ambos, na cor BGR e no modo Cinza.

Observe que girei minha câmera verticalmente devido à forma como ela foi montada. Se não for o seu caso, comente ou exclua a linha de comando "flip".

Como alternativa, você pode baixar o código do meu GitHub: simpleCamTest.py

Para executar, digite o comando:

python simpleCamTest.py

Para finalizar o programa, deve-se pressionar a tecla [ESC] do teclado.

Clique com o mouse na janela do vídeo, antes de pressionar [ESC]

A imagem acima mostra o resultado.

Alguns fabricantes encontraram problemas ao tentar abrir a câmera (mensagens de erro "Falha na declaração"). Isso poderia acontecer se a câmera não fosse habilitada durante a instalação do OpenCv e, portanto, os drivers da câmera não fossem instalados corretamente. Para corrigir, use o comando:

sudo modprobe bcm2835-v4l2

Você também pode adicionar bcm2835-v4l2 à última linha do arquivo / etc / modules para que o driver carregue na inicialização.

Para saber mais sobre o OpenCV, você pode seguir o tutorial: loading -video-python-opencv-tutorial

Etapa 4: detecção de rosto

Detecção de rosto
Detecção de rosto
Detecção de rosto
Detecção de rosto

A tarefa mais básica no reconhecimento de rosto é, obviamente, "Detecção de rosto". Antes de mais nada, você deve "capturar" um rosto (Fase 1) para reconhecê-lo, quando comparado com um novo rosto capturado no futuro (Fase 3).

A maneira mais comum de detectar um rosto (ou qualquer objeto) é usando o "classificador Haar Cascade"

A detecção de objetos usando classificadores em cascata baseados em recursos Haar é um método eficaz de detecção de objetos proposto por Paul Viola e Michael Jones em seu artigo, "Detecção rápida de objetos usando uma cascata impulsionada de recursos simples" em 2001. É uma abordagem baseada em aprendizado de máquina em que um A função em cascata é treinada a partir de muitas imagens positivas e negativas. Em seguida, é usado para detectar objetos em outras imagens.

Aqui vamos trabalhar com detecção de rosto. Inicialmente, o algoritmo precisa de muitas imagens positivas (imagens de rostos) e imagens negativas (imagens sem rostos) para treinar o classificador. Então, precisamos extrair recursos dele. A boa notícia é que o OpenCV vem com um treinador, além de um detector. Se você deseja treinar seu próprio classificador para qualquer objeto como carro, avião, etc., você pode usar o OpenCV para criar um. Todos os detalhes são fornecidos aqui: Cascade Classifier Training.

Se você não quiser criar seu próprio classificador, o OpenCV já contém muitos classificadores pré-treinados para rosto, olhos, sorriso, etc. Esses arquivos XML podem ser baixados do diretório haarcascades.

Chega de teoria, vamos criar um detector de rosto com OpenCV!

Baixe o arquivo: faceDetection.py do meu GitHub.

importar numpy como np

import cv2 faceCascade = cv2. CascadeClassifier ('Cascades / haarcascade_frontalface_default.xml') cap = cv2. VideoCapture (0) cap.set (3, 640) # set Width cap.set (4, 480) # set Height enquanto True: ret, img = cap.read () img = cv2.flip (img, -1) cinza = cv2.cvtColor (img, cv2. COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale (cinza, scaleFactor = 1.2, minNeighbors = 5, minSize = (20, 20)) para (x, y, w, h) nas faces: cv2.rectângulo (img, (x, y), (x + w, y + h), (255, 0, 0), 2) roi_gray = cinza [y: y + h, x: x + w] roi_color = img [y: y + h, x: x + w] cv2.imshow ('video', img) k = cv2.waitKey (30) & 0xff if k == 27: # pressione 'ESC' para sair do break cap.release () cv2.destroyAllWindows ()

Acredite ou não, as poucas linhas de código acima são tudo que você precisa para detectar um rosto, usando Python e OpenCV.

Ao comparar com o último código usado para testar a câmera, você perceberá que poucas partes foram adicionadas a ele. Observe a linha abaixo:

faceCascade = cv2. CascadeClassifier ('Cascades / haarcascade_frontalface_default.xml')

Esta é a linha que carrega o "classificador" (que deve estar em um diretório chamado "Cascades /", no diretório do seu projeto).

Então, vamos definir nossa câmera e dentro do loop, carregar nosso vídeo de entrada em modo de escala de cinza (o mesmo que vimos antes).

Agora devemos chamar nossa função classificadora, passando alguns parâmetros muito importantes, como fator de escala, número de vizinhos e tamanho mínimo da face detectada.

faces = faceCascade.detectMultiScale (cinza, scaleFactor = 1,2, minNeighbors = 5, minSize = (20, 20))

Onde,

  • cinza é a imagem em tons de cinza de entrada.
  • scaleFactor é o parâmetro que especifica o quanto o tamanho da imagem é reduzido em cada escala de imagem. É usado para criar a pirâmide de escala.
  • minNeighbors é um parâmetro que especifica quantos vizinhos cada retângulo candidato deve ter para retê-lo. Um número mais alto resulta em falsos positivos mais baixos.
  • minSize é o tamanho mínimo do retângulo a ser considerado uma face.

A função detectará rostos na imagem. A seguir, devemos "marcar" as faces da imagem, usando, por exemplo, um retângulo azul. Isso é feito com esta parte do código:

para (x, y, w, h) nas faces:

cv2.rectangle (img, (x, y), (x + w, y + h), (255, 0, 0), 2) roi_gray = cinza [y: y + h, x: x + w] roi_color = img [y: y + h, x: x + w]

Se faces forem encontradas, ele retorna as posições das faces detectadas como um retângulo com o canto superior esquerdo (x, y) e tendo "w" como sua largura e "h" como sua altura ==> (x, y, w, h). Por favor, veja a imagem acima.

Depois de obter essas localizações, podemos criar um "ROI" (retângulo desenhado) para a face e apresentar o resultado com a função imshow ().

Execute o script python acima em seu ambiente python, usando o terminal Rpi:

python faceDetection.py

O resultado:

Imagem
Imagem

Você também pode incluir classificadores para "detecção de olhos" ou mesmo "detecção de sorriso". Nesses casos, você incluirá a função classificadora e o retângulo desenhado dentro do loop de rosto, porque não faria sentido detectar um olho ou um sorriso fora de um rosto.

Note que em um Pi, ter vários classificadores no mesmo código vai retardar o processamento, uma vez que este método de detecção (HaarCascades) usa uma grande quantidade de poder computacional. Em um desktop, é mais fácil executá-lo.

No meu GitHub, você encontrará outros exemplos:

faceEyeDetection.py

faceSmileDetection.py

faceSmileEyeDetection.py

E na foto acima você pode ver o resultado.

Você também pode seguir o tutorial abaixo para entender melhor a detecção de rosto:

Haar Cascade Object Detection Face & Eye OpenCV Python Tutorial

Etapa 5: coleta de dados

Coleta de dados
Coleta de dados
Coleta de dados
Coleta de dados

Em primeiro lugar, devo agradecer a Ramiz Raja por seu ótimo trabalho no Reconhecimento de Rosto em fotos:

RECONHECIMENTO DE ROSTO USANDO OPENCV E PYTHON: UM GUIA PARA INICIANTES

e também Anirban Kar, que desenvolveu um tutorial muito abrangente usando vídeo:

RECONHECIMENTO DE FACE - 3 partes

Eu realmente recomendo que você dê uma olhada em ambos os tutoriais.

Dito isso, vamos iniciar a primeira fase do nosso projeto. O que faremos aqui, é partindo da última etapa (Detecção de Rosto), vamos simplesmente criar um conjunto de dados, onde armazenaremos para cada id, um grupo de fotos em cinza com a parte que foi usada para detecção de rosto.

Primeiro, crie um diretório onde você desenvolve seu projeto, por exemplo, FacialRecognitionProject:

mkdir FacialRecognitionProject

Neste diretório, além dos 3 scripts python que criaremos para nosso projeto, devemos ter salvo nele o Classificador Facial. Você pode baixá-lo do meu GitHub: haarcascade_frontalface_default.xml

Em seguida, crie um subdiretório onde armazenaremos nossas amostras faciais e o nomeie "conjunto de dados":

conjunto de dados mkdir

E baixe o código do meu GitHub: 01_face_dataset.py

import cv2

import os cam = cv2. VideoCapture (0) cam.set (3, 640) # set video width cam.set (4, 480) # set video height face_detector = cv2. CascadeClassifier ('haarcascade_frontalface_default.xml') # Para cada pessoa, insira um id numérico de rosto face_id = input ('\ n insira o id do usuário e pressione ==>') print ("\ n [INFO] Inicializando a captura de rosto. Olhe para a câmera e aguarde …") # Inicialize a contagem de amostra de rosto individual = 0 enquanto (Verdadeiro): ret, img = cam.read () img = cv2.flip (img, -1) # virar imagem de vídeo verticalmente cinza = cv2.cvtColor (img, cv2. COLOR_BGR2GRAY) faces = face_detector.detectMultiScale (cinza, 1,3, 5) para (x, y, w, h) nas faces: cv2.rectângulo (img, (x, y), (x + w, y + h), (255, 0, 0), 2) count + = 1 # Salve a imagem capturada na pasta de conjuntos de dados cv2.imwrite ("dataset / User." + str (face_id) + '.' + str (count) + ".jpg", cinza [y: y + h, x: x + w]) cv2.imshow ('imagem', img) k = cv2.waitKey (100) & 0xff # Pressione 'ESC' para sair do vídeo se k == 27: quebrar contagem elif> = 30: # Faça uma amostra de 30 rostos e pare o intervalo do vídeo # Faça um ab de limpeza de impressão ("\ n [INFO] Saindo do programa e coisas de limpeza") cam.release () cv2.destroyAllWindows ()

O código é muito semelhante ao código que vimos para detecção de rosto. O que adicionamos foi um "comando de entrada" para capturar a id do usuário, que deve ser um número inteiro (1, 2, 3, etc)

face_id = input ('\ n insira o id do usuário e pressione ==>')

E para cada um dos frames capturados, devemos salvá-lo como um arquivo em um diretório "dataset":

cv2.imwrite ("conjunto de dados / usuário." + str (face_id) + '.' + str (contagem) + ".jpg", cinza [y: y + h, x: x + w])

Observe que para salvar o arquivo acima, você deve ter importado a biblioteca "os". O nome de cada arquivo seguirá a estrutura:

User.face_id.count.jpg

Por exemplo, para um usuário com face_id = 1, o quarto arquivo de amostra no conjunto de dados / diretório será algo como:

User.1.4.jpg

como mostrado na foto acima do meu Pi. No meu código, estou capturando 30 amostras de cada id. Você pode alterá-lo no último "elif". O número de amostras é usado para quebrar o loop onde as amostras de rosto são capturadas.

Execute o script Python e capture alguns Ids. Você deve executar o script sempre que desejar agregar um novo usuário (ou trocar as fotos por uma já existente).

Etapa 6: instrutor

Treinador
Treinador

Nesta segunda fase, devemos pegar todos os dados do usuário de nosso conjunto de dados e "treinar" o OpenCV Recognizer. Isso é feito diretamente por uma função OpenCV específica. O resultado será um arquivo.yml que será salvo em um diretório "trainer /".

Então, vamos começar a criar um subdiretório onde armazenaremos os dados treinados:

treinador mkdir

Baixe do meu GitHub o segundo script python: 02_face_training.py

import cv2

importar numpy como np de PIL import Image import os # Caminho para o banco de dados de imagens de rosto path = 'dataset' reconhecizer = cv2.face. LBPHFaceRecognizer_create () detector = cv2. CascadeClassifier ("haarcascade_frontalface_default.xml"); # função para obter as imagens e os dados do rótulo def getImagesAndLabels (path): imagePaths = [os.path.join (path, f) for f em os.listdir (path)] faceSamples = ids = para imagePath em imagePaths: PIL_img = Image.open (imagePath).convert ('L') # converta para tons de cinza img_numpy = np.array (PIL_img, 'uint8') id = int (os.path.split (imagePath) [- 1]. split (".") [1]) faces = detector.detectMultiScale (img_numpy) para (x, y, w, h) em faces: faceSamples.append (img_numpy [y: y + h, x: x + w]) ids.append (id) return faceSamples, ids print ("\ n [INFO] Faces de treinamento. Demorará alguns segundos. Aguarde …") faces, ids = getImagesAndLabels (path) reconhecizer.train (faces, np.array (ids)) # Salve o modelo em trainer / trainer.yml reconhecizer.write ('trainer / trainer.yml') # reconhecizer.save () funcionou no Mac, mas não no Pi # Imprimir o número de faces treinadas e imprimir o programa final ("\ n [INFO] {0} faces treinadas. Saindo do programa".format (len (np.unique (ids))))

Confirme se você tem a biblioteca PIL instalada em seu Rpi. Caso contrário, execute o comando abaixo no Terminal:

pip instalar travesseiro

Usaremos como um reconhecedor, o Reconhecedor Facial LBPH (LOCAL BINARY PATTERNS), incluído no pacote do OpenCV. Fazemos isso na seguinte linha:

reconhecedor = cv2.face. LBPHFaceRecognizer_create ()

A função "getImagesAndLabels (path)", irá tirar todas as fotos do diretório: "dataset /", retornando 2 arrays: "Ids" e "faces". Com essas matrizes como entrada, "treinaremos nosso reconhecedor":

reconhecizer.train (faces, ids)

Como resultado, um arquivo chamado "trainer.yml" será salvo no diretório do treinador que foi criado anteriormente por nós.

É isso! Incluí a última declaração de impressão onde exibi para confirmação, o número de rostos de usuários que treinamos.

Cada vez que você executa a Fase 1, a Fase 2 também deve ser executada

Etapa 7: Reconhecedor

Reconhecedor
Reconhecedor
Reconhecedor
Reconhecedor

Agora, chegamos à fase final do nosso projeto. Aqui, capturaremos um rosto novo em nossa câmera e se essa pessoa tiver seu rosto capturado e treinado antes, nosso reconhecedor fará uma "previsão" retornando seu id e um índice, mostrando o quão confiante o reconhecedor está com esta correspondência.

Vamos baixar o script Python da 3ª fase do meu GitHub: 03_face_recognition.py.

import cv2

import numpy como np import os reconhecizer = cv2.face. LBPHFaceRecognizer_create () reconhecizer.read ('trainer / trainer.yml') cascadePath = "haarcascade_frontalface_default.xml" faceCascade = cv2. CascadeClassifier (cascadePath); font = cv2. FONT_HERSHEY_SIMPLEX #iniciate id counter id = 0 # nomes relacionados a ids: example ==> Marcelo: id = 1, etc names = ['None', 'Marcelo', 'Paula', 'Ilza', 'Z ',' W '] # Inicializar e iniciar a captura de vídeo em tempo real cam = cv2. VideoCapture (0) cam.set (3, 640) # set video widht cam.set (4, 480) # definir altura do vídeo # Definir tamanho mínimo da janela ser reconhecido como um rosto minW = 0,1 * cam.get (3) minH = 0,1 * cam.get (4) enquanto Verdadeiro: ret, img = cam.read () img = cv2.flip (img, -1) # Virar verticalmente cinza = cv2.cvtColor (img, cv2. COLOR_BGR2GRAY) faces = faceCascade.detectMultiScale (cinza, scaleFactor = 1,2, minNeighbors = 5, minSize = (int (minW), int (minH)),) para (x, y, w, h) nas faces: cv2.rectangle (img, (x, y), (x + w, y + h), (0, 255, 0), 2) id, confiança = reconhecedor.predict (cinza [y: y + h, x: x + w]) # Verifique se a confiança é menor que 100 ==> "0" é uma correspondência perfeita se (confiança <100): id = nomes [id] confiança = "{0}% ".format (rodada (100 - confiança)) else: id =" desconhecido "confiança =" {0}% ". formato (rodada (100 - conf idence)) cv2.putText (img, str (id), (x + 5, y-5), fonte, 1, (255, 255, 255), 2) cv2.putText (img, str (confiança), (x + 5, y + h-5), fonte, 1, (255, 255, 0), 1) cv2.imshow ('câmera', img) k = cv2.waitKey (10) & 0xff # Pressione 'ESC' para sair do vídeo if k == 27: break # Faça um pouco de limpeza de impressão ("\ n [INFO] Saindo do programa e coisas de limpeza") cam.release () cv2.destroyAllWindows ()

Estamos incluindo aqui uma nova matriz, portanto, exibiremos "nomes", em vez de ids numerados:

nomes = ['Nenhum', 'Marcelo', 'Paula', 'Ilza', 'Z', 'W']

Assim, por exemplo: Marcelo será o usuário com id = 1; Paula: id = 2, etc.

A seguir, detectaremos um rosto, o mesmo que fizemos antes com o classificador haasCascade. Tendo um rosto detectado, podemos chamar a função mais importante no código acima:

id, confiança = reconhecedor.predict (parte cinza do rosto)

O reconhecizer.predict (), tomará como parâmetro uma porção capturada da face a ser analisada e retornará seu provável dono, indicando seu id e quanta confiança o reconhecedor tem em relação a esta correspondência.

Observe que o índice de confiança retornará "zero" se for considerado uma correspondência perfeita

E por fim, se o reconhecedor pudesse prever um rosto, colocamos um texto sobre a imagem com o id provável e quanto é a "probabilidade" em% de que a correspondência esteja correta ("probabilidade" = 100 - índice de confiança). Caso contrário, um rótulo "desconhecido" é colocado no rosto.

Abaixo um-g.webp

Imagem
Imagem

Na foto acima, mostro alguns testes feitos com este projeto, onde também usei fotos para verificar se o reconhecedor funciona.

Etapa 8: Conclusão

Conclusão
Conclusão

Como sempre, espero que este projeto possa ajudar outras pessoas a encontrar seu caminho para o emocionante mundo da eletrônica!

Para obter detalhes e o código final, visite meu depósito no GitHub: OpenCV-Face-Recognition

Para mais projetos, visite meu blog: MJRoBot.org

Abaixo, um vislumbre de um tutorial futuro, onde exploraremos "rastreamento automático de rosto e outros métodos de detecção de rosto":

Imagem
Imagem

Saludos do sul do mundo!

Vejo você no meu próximo instrutível!

Obrigado, Marcelo

Recomendado: