2

Nem tudo é IA, às vezes é só uma heurística simples: como fiz um joguinho com expressões faciais

O que aprendi ao usar MediaPipe para perceber um rosto e regras explícitas para controlar o Chrome Dino.

Quando comecei um projeto de disciplina envolvendo visão computacional, eu tinha uma ideia que parecia óbvia: controlar o Chrome Dino com expressões faciais. A webcam observaria o rosto; uma expressão faria o personagem pular; outra o faria abaixar.

Também tive uma reação quase automática: vou precisar treinar um classificador para isso.

Afinal, havia uma câmera, havia landmarks faciais e havia um problema que, de longe, parecia caber no grande guarda-chuva de “IA”. Mas, conforme o projeto tomava forma, a pergunta deixou de ser “qual modelo eu treino?” e passou a ser bem mais útil: qual é a menor solução que resolve o comportamento que eu quero?

Foi assim que surgiu o DinoExpression. Ele usa MediaPipe para perceber o rosto, mas não usa um modelo treinado por mim para decidir a ação. A decisão final é uma heurística simples organizada como regras explícitas. Parece uma distinção pequena; para mim, ela mudou completamente a forma de pensar o projeto.

Perceber não é decidir

Antes de tudo, vale deixar a nuance correta: o MediaPipe não é “só uma biblioteca de desenho de pontos”. O Face Mesh usa aprendizado de máquina para localizar landmarks no rosto. Então seria errado dizer que o projeto “não usa IA”.

O que ele não precisava usar era um segundo modelo treinado para transformar cada frame em pular, abaixar ou neutro.

Essas são duas responsabilidades diferentes. A primeira é perceber: onde estão a boca, os olhos e as sobrancelhas? A segunda é decidir: dado o estado do rosto, qual ação faz sentido no jogo? O MediaPipe já resolvia muito bem a primeira parte. Para a segunda, eu tinha somente três ações discretas e sinais faciais que eu conseguia descrever com clareza.

Não era um problema aberto de reconhecimento de emoções. Não era preciso distinguir dezenas de intenções humanas. Eu só precisava de uma interação compreensível: boca aberta abaixa; sobrancelhas levantadas pulam; ausência das duas condições mantém o personagem neutro.

Essa percepção reduziu bastante a complexidade. Em vez de coletar um dataset, rotular exemplos, escolher uma arquitetura, treinar, avaliar e depois explicar os erros de um classificador, eu poderia explicitar o comportamento que queria.

Do rosto ao comando

O primeiro passo foi escolher medidas que não dependessem de uma posição fixa diante da câmera. O projeto acompanha a abertura da boca e a distância entre as sobrancelhas e os olhos. Em vez de trabalhar com pixels brutos, as distâncias são normalizadas pela distância entre os cantos externos dos olhos.

Essa normalização é pequena, mas importante. Sem ela, aproximar o rosto da webcam poderia parecer uma mudança de expressão. Com uma referência proporcional ao próprio rosto, a regra se torna mais estável para a interação pretendida.

Depois vem a calibração. Nos primeiros 24 frames válidos, o projeto espera um rosto neutro e usa a mediana das medidas como baseline. A partir daí, não pergunta simplesmente se uma sobrancelha está “alta”; pergunta se ela está mais alta do que a referência daquela pessoa naquele momento.

graph TD
    Webcam --> MediaPipe
    MediaPipe --> MedidasNormalizadas[Medidas normalizadas]
    MedidasNormalizadas --> Regras[Regras explícitas]
    Regras --> Acao[Ação no Chrome Dino]

Com essa base, as regras ficam diretas:

Expressão detectadaAção
Boca abertaAbaixar
Boca fechada e as duas sobrancelhas levantadasPular
Boca fechada e sobrancelhas não levantadasPermanecer neutro

Ainda há uma proteção simples contra ruído: a mesma ação precisa aparecer em três frames consecutivos antes de ser enviada ao jogo. Não é uma técnica sofisticada, e essa é justamente a graça. Para um controle por gestos pequeno, ela reduz oscilações sem introduzir um sistema complexo de filtragem.

Por que usar Agente Logico?

Em primeira instância, usei os Agente Logicos porque era uma das alternativas dada pelo professor (Existiam outras como Classificadores ML). Entretanto, escolhi justamente essa pelo fato de ser algo simples, sem ter a necessidade de treinar um modelo IA do zero.

Se a boca está fechada e as sobrancelhas estão levantadas, o agente recebe esses dois fatos por uma operação chamada TELL. As regras são aplicadas por encadeamento para frente: quando as premissas de uma regra são verdadeiras, sua conclusão também passa a ser verdadeira. Depois, uma consulta ASK procura exatamente uma ação entre pular, abaixar e neutro.

Os nomes podem soar formais, mas o ganho é prático. As regras e os limiares ficam em um arquivo JSON, fora do fluxo principal do código. Ajustar a sensibilidade não exige reescrever a captura de câmera. Trocar uma regra não exige tocar na parte que envia teclas para o navegador.

Mais importante: a decisão deixa de ser uma surpresa. No modo de depuração, consigo observar as medidas, os fatos enviados pelo TELL e a ação encontrada pelo ASK. Se o personagem pulou na hora errada, existe uma trilha curta para investigar: a medida foi ruim? O limiar era inadequado? A regra descrevia o comportamento errado?

Esse tipo de explicabilidade é fácil de subestimar quando a solução parece simples. Mas, em um projeto de interação em tempo real, conseguir identificar a origem de um comportamento vale muito mais do que usar uma ferramenta mais impressionante no papel.

Arquitetura sem complicação

O mesmo princípio de simplificar apareceu na arquitetura. Cada frame passa por uma cadeia de responsabilidades: capturar a imagem, espelhá-la, detectar os landmarks, aplicar o agente lógico e, dependendo do modo, executar a ação no jogo ou desenhar as informações de depuração.

Essa organização segue a ideia de Chain of Responsibility: cada etapa recebe o mesmo contexto, cuida de uma responsabilidade e entrega o resultado para a próxima. A etapa de captura não precisa saber quais regras decidem um pulo. O agente lógico não precisa saber como o Chrome recebe uma tecla. A visualização não precisa interferir na decisão.

Na prática, isso tornou o projeto mais fácil de mexer. Posso olhar apenas para a etapa de percepção quando uma medida parece estranha. Posso alterar regras sem tocar na automação do navegador. Posso ativar a visualização de pontos e tempos sem mudar a lógica que controla o jogo.

Não é uma arquitetura grandiosa. É uma estrutura pequena, mas compatível com o tamanho do problema. E essa compatibilidade talvez seja uma das decisões de engenharia mais importantes que um projeto pequeno pode ter.

A heurística não é uma solução de segunda classe

Há uma pressão curiosa para que qualquer projeto que toque em uma câmera ou em landmarks termine em um modelo treinado. Às vezes isso é necessário. Se o problema tiver muitas classes, sinais ambíguos, variações difíceis de descrever ou dados que revelem padrões impossíveis de transformar em regras, um modelo pode ser a escolha certa.

Mas não era o que eu tinha aqui.

Eu tinha poucas ações, gestos definidos, uma interação local e a necessidade de entender por que cada decisão acontecia. Uma heurística calibrada, com regras explícitas e confirmação temporal, atendia melhor a esse cenário do que um classificador adicional.

O que ficou desse projeto não foi uma rejeição a modelos de aprendizado de máquina. Foi uma lição mais simples: usar IA não é empilhar modelos até o problema parecer sofisticado. É reconhecer quais partes realmente pedem aprendizado e quais partes só pedem uma boa descrição do comportamento.

Às vezes, a solução mais inteligente não é a mais complexa. Às vezes, é só uma heurística simples — e saber por que ela basta.

Carregando publicação patrocinada...