Neste post, é apresentado como realizar a detecção de pontos faciais com o algoritmo de Kazemi, implementado na biblioteca Dlib utilizando Shape Predictor. Na primeira parte deste tutorial, é apresentado o conceito de shape predictor (preditor de forma/ponto de referência) e como ele pode se usado para prever localizações específicas em objetos estruturais.
Este conteúdo é continuação do post Detecção de pontos faciais (Facemark) com OpenCV, recomendo a leitura dele primeiro, para melhor entender os conceitos básicos aqui apresentados.
Revisão de Conteúdo
Caso você não queira ler o post anterior, segue uma rápida revisão do conteúdo.
Os pontos faciais, em visão computacional, como o próprio nome diz, são pequenas regiões faciais identificadas por uma numeração, conforme ilustra a Fig 1.. Estas regiões, são identificadas por um ponto e uma numeração que pode variar de técnica para técnica utilizada.
Para realizar a detecção de pontos faciais, são necessárias as seguintes etapas antecessoras à coleta dos pontos na imagem: (1) identificar os rostos na imagem; (2) rotacionar o rosto caso necessário e (3) identificar os pontos faciais A Fig 2. Ilustra estas etapas..
Algoritmo Shape Predictor de Kazemi
“Shape Predictor” são utilizados para localizar coordenadas (x, y) específicas a partir de uma forma de entrada. O termo “Shape” é arbitrário, mas presume-se que a forma seja de natureza estrutural, como: rostos; mãos; dedos; etc [R].
Por exemplo, os rostos têm formas e tamanhos diversos, e todos eles compartilham características estruturais comuns: os olhos estão acima do nariz, o nariz está acima da boca, etc. O objetivo dos preditores de forma/ponto de referência, é explorar esse conhecimento estrutural e, com dados de treinamento suficientes, aprender como prever automaticamente a localização dessas estruturas [R].
Existem vários algoritmos preditores de forma. O algoritmo do preditor de forma implementado na biblioteca Dlib vem do artigo CVPR de Kazemi e Sullivan de 2014, One Millisecond Face Alignment with an Ensemble of Regression Trees [KJ1].
Código e Experimentos
A seguir, são apresentados partes do código criado para realizar os experimentos de detecção de pontos faciais. Caso queira replicar estes experimentos, basta baixar o código fonte disponível no github (link na seção “Source” no final deste post).
Neste primeiro bloco, são inicializados todos os detectores do sistema, o detector facial e o detector de pontos faciais. Para iniciar todos estes detectores é muito simples, basta instanciar a classe dlib::frontal_face_detector, instanciar a classe dlib::shape_predictor e carregar o modelo treinado para a classe shape_predictor.
... #include < dlib/image_processing/frontal_face_detector.h > #include < dlib/image_processing.h > dlib::frontal_face_detector detector; dlib::shape_predictor shapePredictor; main() { ... // Inicia Detector faciauk detector = dlib::get_frontal_face_detector(); //Carrega o modelo treinado do shape predictor iniciarDetectorPontosFacialSP(shapePredictor); ... } void iniciarDetectorPontosFacialSP(dlib::shape_predictor &sp) { dlib::deserialize("../../extra/shape_predictor_68_face_landmarks.dat") >> sp; }
Para carregar o modelo de dados com Dlib, basta utilizar a função de dlib::deserialize e informar o caminho do arquivo. Esta função carrega o modelo treinado e transfere os dados carregados para a classe de predição com o operador “>>” conforme trecho de código “>> sp”.
Com os detectores/preditores carregados, agora precisamos carregar a imagem com os rostos a serem detectados. Neste experimento, utilizamos a webcam para este fim e para carregar as imagens da webcam, utilizamos a biblioteca OpenCV, que é de fácil instalação.
Para capturar a câmera do vídeo com o OpenCV, basta instanciar a classe “cv::VideoCapturecap” e coletar a imagem do vídeo com o operador “>>” conforme trecho de código “cap>>img”.
main() { ... //Inicia captura dos vídeos cv::VideoCapturecap cap(0); if (!cap.isOpened()) { std::cout<<"Video Capture Fail"<<std::endl; return1; } cv::Mat img; cap>>img; return 1; } //Calcula nova dimensão da imagem para 320 pixels auto showSize = cv::Size(320, ((float)320 / img.cols) * img.rows); for (;;) { //Coleta a imagem da camera cap>>img; //Reescala a imagem para uma largura de 320 pixels cv::resize(img, img, showSize, 0, 0, cv::INTER_LINEAR_EXACT); coletarPontosFaciais(img); cv::imshow("Origem", img); cv::waitKey(5); } }
Por fim, no último trecho de código, é apresentado como coletar os pontos faciais com o OpenCV.
dlib::image_window win, win_faces; std::vector< dlib::rectangle > rostosDetectados; void coletarPontosFaciais(const dlib::array2d& imagemOriginal) { //Detecta os pontos faciais e retorna a lista de rostos detectados rostosDetectados = detector(imagemOriginal); //Percorre os rostos detectados e coloca os pontos faciais std::vector< dlib::full_object_detection > pontosFaciais; for (unsigned long j = 0; j < rostosDetectados.size(); ++j) { //Coleta os pontos faciais de um único rosto dlib::full_object_detection shape = shapePredictor(imagemOriginal, rostosDetectados[j]); pontosFaciais.push_back(shape); } // Exibe a imagem com o contorno dos pontos. win.clear_overlay(); win.set_image(imagemOriginal); win.add_overlay(render_face_detections(pontosFaciais)); // Recorta o rosto da imagem original e a exibe. dlib::array rostosRecortados; extract_image_chips(imagemOriginal, get_face_chip_details(pontosFaciais), rostosRecortados); win_faces.set_image(tile_images(rostosRecortados)); }
Observe que para detectar os rostos faciais com a classe dlib::frontal_face_detector, basta utilizar a variável detector como fosse uma função, passando a imagem como parâmetro. Ao utilizar o detector como função, serão detectados os rostos e retorna uma lista de retângulos com sua localização.
Com os rostos detectados, basta percorrer cada região dos rostos e chamar a função do shapePredictor, para coletar os pontos faciais. Esta função retorna uma lista com todos pontos localizados.
A classe dlib::image_window é utilizada para criar uma janela para exibição das imagens. A função render_face_detections é disponibilizada pela própria Dlib a fim de demarcar as regiões do rosto na imagem. E as funções extract_image_chips e get_face_chip_details recortam o rosto a partir dos pontos faciais. Como resultado deste projeto, foi realizado o experimento ilustrado pela Fig 3.
Espero que esse conteúdo os ajudem na tarefa de identificação de pontos faciais.
Caso tenham dúvidas e sugestões de melhorias no post, deixe seu comentário abaixo.
Source:
Referencias:
Huber, Patrik. (2018). Real-time 3D morphable shape model fitting to monocular in-the-wild videos.
[R] Rosebrock, A, Training a custom dlib shape predictor, 2019, acessado em: 18/10/2101
Nenhum comentário ainda!