Olá, pessoal! Neste artigo vou apresentar os detalhes técnicos de uma abordagem que utilizei para capturar dados em tempo real de um vídeo. Esta solução apresentada pode ser útil para aqueles que precisam coletar informações diretamente de um vídeo, seja ele proveniente de uma webcam, streaming, vídeo do YouTube ou mesmo de câmeras de segurança.
Antes de entrar na parte técnica, vou explicar o cenário com o qual me deparei. Apesar de me concentrar neste cenário específico, os leitores podem aproveitar as ideias contidas neste artigo para outros cenários, contextos e situações que necessitem de captura de dados em tempo real a partir de imagens e vídeos.
Recentemente, estive envolvido em um projeto que envolvia a coleta de dados biológicos para posterior análise quantitativa e qualitativa durante a execução de certas atividades físicas. A obtenção destes dados foi realizada por dispositivos próprios, tais como cronômetros, pedômetros e medidores de batimentos cardíacos. Estes dispositivos não possuem nenhum tipo de interface para se conectar com computadores, tais como portas USB, bluetooth ou outros. Além de capturar estes dados para posterior análise o projeto tinha como um dos requisitos apresentar em tempo real estas informações na forma de um gráfico, para que certas atitudes possam ser tomadas pelos especialistas de domínio, tais como a hidratação do atleta ou a solicitação de uma pausa durante o exercício.
A figura abaixo mostra alguns exemplos de podômetros e outros dispositivos que podem ser utilizados para este tipo de captura de dados, incluindo a interface de uma aplicação para o iPhone.
Bem, a principal dificuldade deste cenário estava justamente na falta de conectividade do aparelho que registrava as informações. A principal métrica que deveria ser calculada era a quantidade de batimentos cardíacos do atleta (BPM) durante o decorrer do exercício. Devido à limitação do dispositivo não possuir nenhuma interface com um computador, resolvi pensar um pouco e começar a fazer o design e a arquitetura da solução.
A solução encontrada para coletar os dados foi recorrer ao auxílio de uma webcam simples conectada a um laptop. Deste modo, era preciso posicionar a webcam perto da tela do aparelho que mostra os indicadores numéricos e, de alguma forma, capturar o que eles mostravam em tempo real. Uma vez que os dados estivessem coletados em tempo real, pensei em montar um gráfico de linha dentro de uma planilha do Excel, para que a medida que os dados forem reconhecidos, eles seriam inseridos em células da planilha que mostrariam de forma dinâmica a variação no gráfico. Além disso, os dados seriam armazenados na planilha para análises posteriores.
Aqui gostaria de fazer uma pequena observação: atualmente, nos deparamos com diversas câmeras posicionadas nos mais variados locais, como entrada/saída do prédio, elevador, ruas, escolas, bancos e praticamente qualquer canto. Porém, ainda é raro encontrar algum nível de inteligência computacional aplicado nas imagens e vídeos capturados. Geralmente o emprego destas câmeras é apenas para monitoria manual, ou seja, há algum ser humano olhando para elas, ou para arquivamento posterior que também envolve a análise humana.
Talvez o principal motivo pelo qual existam poucas aplicações voltadas para a análise automática de dados em tempo real, seja a dificuldade de programação de algoritmos e técnicas de visão computacional – uma área que é muito importante e vem ganhando atenção e diversos recursos, do ponto de vista de programação. Em resumo, era importante que a solução que eu apresentasse não fosse demasiadamente complexa e que pudesse ser aproveitada em outros cenários e contextos.
Voltando para o problema de coleta e captura de dados… Uma vez que a arquitetura da solução estava definida, foi preciso correr atrás de recursos para coletar os dados. Felizmente era preciso coletas apenas dos números de um visor. Para realizar os testes iniciais, trabalhei apenas com o cronômetro do dispositivo, cuja tela pode ser visualizada na figura abaixo. A imagem mostra um exemplo de como a webcam capturou o mostrador digital de cronômetro utilizado neste projeto e que fornecia uma boa aproximação dos dados numéricos que deveriam ser capturados em tempo real. Durante os primeiros testes, apenas o valor numérico maior da figura (representado por 42.5) deveria ser reconhecido em um tempo adequado, conforme o contador do cronômetro se modificava para marcar a passagem do tempo.
Após algumas pesquisas sobre algoritmos e soluções para visão computacional, me deparei com este projeto no site CodeProjet, cuja possibilidade de reconhecimento de letras e números a partir de um vídeo me pareceu muito interessante a princípio. A figura abaixo mostra um exemplo de reconhecimento de caracteres deste projeto que utiliza a análise de contornos programada em uma biblioteca para o C#.
Quando comecei a estudar este projeto, logo me deparei com diversos problemas operacionais. O reconhecimento era muito aleatório, havia muita variação do reconhecimento de acordo com a iluminação, a programação estava muito complexa e mesmo com os parâmetros de ajuste do software, eu não consegui fazer o reconhecimento satisfatório. Resolvi abandonar este projeto e procurar algo mais simples e robusto.
Foi então que me lembrei do projeto Sikuli, que já tinha mencionado em um artigo anterior. O objetivo deste projeto é facilitar a automação de tarefas que exijam a manipulação da interface gráfica, através de uma linguagem própria e da releitura e reconhecimento da interface gráfica ou do desktop. A figura abaixo mostra um pouco como esta automação pode ser feita através da linguagem de programação do próprio Sikuli, que combina aspectos do Python com imagens da tela. Também é possível converter esta linguagem de programação do Sikuli em um código fonte em Java e assim criar diversas aplicações muito interessantes que envolvam visão computacional e automação da manipulação da interface gráfica.
O algoritmo inicial para esta solução baseada no Sikuli funcionaria da seguinte forma: no desktop eu abriria a janela de captura do software da câmera. Em seguida, eu indicaria que gostaria de monitorar apenas uma região do vídeo da câmera. Esta região deveria ser criada em uma variável fora do loop principal do programa. Dentro deste loop, eu iria capturar a região do primeiro dígito do indicador do dispositivo e fazer o reconhecimento do dígito através de vários comandos de desvio condicional (if). Cada um destes ifs deveria comparar a região da tela com figuras pré-gravadas dos indicadores. Caso houvesse o reconhecimento eu enviaria o valor numérico do dígito como se fosse pressionada uma tecla do teclado. Este valor numérico seria gravado automaticamente em uma célula da planilha do Excel aberta, que seria responsável por montar o gráfico em tempo real. O código parcial no projeto Sikuli deste programa é apresentado na figura abaixo.
Para um programador que está acostumado a ver apenas caracteres em um código fonte, pode ser esquisito notar que junto com as estruturas da linguagem de programação podemos colocar imagens. Isso é proporcionado pela IDE de programação do Sikuli e, internamente, são gravadas imagens no disco que são lidas quando o programa for executado. Outro detalhe interessante é que é possível configurar índices de reconhecimento por imagem, ou seja, o quão similar a imagem capturada deve ser em relação à imagem gravada. Isso é apresentado pelo retângulo verde do canto superior direto de cada imagem. Procurei ajustar estes valores da melhor forma possível para capturar os dados. Destaco que a quantidade de código necessário para montar este pequeno programa foi relativamente pequena, se comparado com outros frameworks, bibliotecas e alternativas que envolviam a utilização de algoritmos de visão computacional. Além disso, o código ficou muito fácil de ser compreendido.
Apesar desta primeira ideia para o programa funcionar, descobri que esta captura não foi robusta o suficiente, ou seja, em diversas ocasiões o algoritmo não conseguia reconhecer corretamente o dígito, ou quando o reconhecimento estava correto, ele não era em tempo real. Portanto, ao invés de continuar manipulando os parâmetros de reconhecimento, resolvi procurar na documentação e verificar se já havia algum recurso para o reconhecimento de caracteres em imagens – ou seja, se o Sikuli proporcionava algum recurso de OCR. E, para minha surpresa, havia uma função que estava em beta e que recebia como parâmetro uma imagem e retornava em string o que estava escrito nela.
Sendo assim, resolvi alterar o programa para apenas capturar a região da tela que continha o cronômetro, converter o que a função retornava para string e enviar para o dispositivo de entrada. Testes iniciais necessitaram um posicionamento melhor da câmera e um controle da incidência de luz no visor do dispositivo. Além disso, também precisei fazer um pequeno controle e verificar se realmente o que estava sendo retornado pela função que reconhecia os dados era numérico programado na função is_number(). A nova versão da solução é apresentada na figura abaixo:
Apesar do reconhecimento dos dígitos requerer ajustes na posição da câmera, consegui bons resultados no que diz respeito ao tempo de captura, que ficou abaixo dos 0,3 segundos. Ainda sim, alguns dos dados capturados não foram numéricos – porém este tipo de problema foi facilmente tratado na própria planilha do Excel. Além disso, é natural coletar diversos dados para fazer uma análise e posteriormente descartar certas medidas que não forem numéricas. Gostaria que os leitores observassem que o código final desta solução ficou muito simples e que foram gastas doze linhas de código para realizar esta tarefa complexa de reconhecimento de caracteres em vídeo.
Após realizar diversos testes com o cronômetro, rapidamente ajustei o medidor para coletar os BPM e indiquei ao atleta que ele poderia fazer o exercício. A solução funcionou sem maiores problemas e abriu novas possibilidades para a coleta de dados que podem auxiliar tanto o treinador quando o atleta. Desta forma, espero que este tipo de solução possa ser aplicado em outros contextos e cenários onde os algoritmos de visão computacional podem ser utilizados para fornecer algum tipo de inteligência e automação a partir de imagens e vídeos coletados por câmeras.
Um grande abraço, pessoal, e até a próxima!