Túnel do Tempo: detectando rostos (ou outros objetos) com PHP e OpenCV

Um dos temas que mais me fascinam na computação é a visão computacional. Acho que isso me fascina tanto porque "enxergar" é uma característica nossa, e levar isso para uma máquina é um desafio e tanto.

As aplicações que utilizam visão computacional são inúmeras e agregam muito valor em diversos tipos de produtos e serviços: de um lado, existem alguns drones, como o DJI Inspire, utilizam algoritmos de fluxo ótico para estabilização do mesmo. Câmeras ficam apontadas para baixo do drone, onde um algoritmo processa esse vídeo e verifica a movimentação do mesmo em relação ao solo. Apesar de sensores IMU hoje em dia serem muito precisos, seu erro é cumulativo e em ambientes internos, onde não há GPS, um sistema ótico capaz de detectar se o drone está se locomovendo sobre o solo é bastante útil.

De outro lado, redes sociais como o Facebook se beneficiam de algoritmos de detecção e identificação de rostos. Um recurso assim pode parecer dispensável a primeira vista, mas ele agrega valor ao serviço ajudando os usuários da rede a se conectarem.

Foi pensando nisso que, há 5 anos atrás, eu fiz um módulo para PHP capaz de detectar rostos utilizando OpenCV.

O OpenCV oferece uma série de métodos e possibilidades de detecção de objetos de imagens. É possível utilizar, por exemplo, descritores de características locais de imagens, detectores já existentes que utilizam aprendizado de máquina ou então fazer um utilizando suas próprias características visuais. Essa extensão usa uma abordagem com aprendizado de máquina. Apesar de antiga, essa abordagem (que utiliza classificadores Adaboost com árvores de decisão e características Haar para os classificadores) é funcional para detectar objetos que tem uma forma predominantemente estática, como rostos!

A maior dificuldade com essa abordagem consiste no treinamento. Para isso, é necessário uma boa dose de tempo e muitos bons exemplos de imagens dos objetos que precisam ser detectados. E os resultados, obviamente, variam de objeto para objeto. Por sorte, o OpenCV já vem com alguns bons classificadores treinados que podem ser utilizados como exemplos. Dentre eles, alguns para detecção de faces. Um deles foi utilizado nesse módulo.

Outra (boa) característica desse método de detecção de objetos é sua velocidade e custo computacional. Arvores de decisão e características Haar foram criadas de tal forma que são simples e consequentemente rápidas! Essa velocidade, então, é ampliada pelo fato de que o algoritmo do OpenCV está escrito em C. Aliás, um dos melhores argumentos pró-extensões PHP reside no fato de que códigos em C e C++ são muito mais rápidos que seus equivalentes em PHP. A relação que se tem com o código que o programador escreve em C/C++ e com o código-máquina gerado é muito maior que a relação que se tem com o código PHP e o código-máquina gerado. Isso gera overhead na escrita do código em C/C++, mas dá um controle maior do código gerado ao programador, o que facilita sua otimização.

Se você ficou interessado no módulo, ele está disponível e possui código aberto: https://github.com/fsjunior/FaceDetectionForPHP