Como a máquina leu uma tabela nutricional?
Como foi possível ler tabelas nutricionais com OCR, Tesseract e muita visão computacional!
Ha um tempo atrás estava imerso em um projeto que trabalhava com a formação de um data lake de dados alimentícios, coletando desde produtos em geral até as informações nutricionais de uma massa de alimentos, todavia em determinado ponto percebeu-se que a maior parte das informações nutricionais estavam inseridas em imagens e não em textos, dificultando, assim, a questão de web scrapping com o framework Scrapy e Python.
Esse problema abriu oportunidade para o aprendizado de algo que está presente na tecnologia há muito tempo e ganhou percussão com David H. Shepard. Essa tecnologia é muito conhecida como Optical Character Recognition (OCR). Inclusive, o seguinte video é muito legal para ter uma noção do início do OCR:
Dessa forma o desafio era que a partir de uma imagem, fosse possível obter os dados de tabelas nutricionais em texto.
Sumário
- Tesseract e PyTesseract;
- Teoria das linhas da tabela;
- EAST;
- Symspell;
- Fluxograma e Implementação.
Tesseract e PyTesseract
Procurando sobre OCR, cheguei a uma ferramenta que é líder de uso atualmente, além de ser conhecida pela sua grande eficiência. Essa ferramenta é o Tesseract.
O Tesseract é um engine open source com a licença da Apache 2.0 que atualmente pertence à Google, sendo que este visa aplicar o reconhecimento óptico de caracteres. Sua implementação incial aconteceu com a linguagem C, sendo desenvolvida pela HP. Para mais detalhes, fique a vontade para olhar o repositório no GitHub ou consultar o seguinte artigo, que também é bem completo quanto ao assunto:
Todavia, com o uso crescente da linguagem Python, a comunidade abraçou a causa e desenvolveu um wrapper que foi nomeado de Pytesseract, contemplando todas as funcionalidades que pertencem ao projeto original. O Pytesseract também é um projeto open source que se encontra disponível no GitHub ou pronto para o uso no Python Package Index (PyPI).
Essa engine e esse pacote foram essenciais para o desenvolvimento do projeto, a ponto de tornarem-se um requisito (o qual é abordado no repositório do projeto).
Teoria das linhas da tabela
Como mencionado no início do projeto o desafio estava voltado a ler tabelas nutricionais e diferente de um ambiente controlado, quando se trata de tabelas nutricionais, temos varias palavras que por vezes são desconexas, além de linhas horizontais e linhas verticais que separam as palavras dos valores, dessa forma, a questão que fica é: como facilitar a leitura para a máquina nessa situação? Ou seja, a missão era remover essas linhas e colunas e deixar apenas as palavras e valores, de modo que não “desviássemos” a atenção da máquina para aquilo que ela não precisava se quer saber.
Para resolver esse problema duas coisas foram feitas.
A primeira foi utilizar de kernels horizontais e verticais para identificar onde essas linhas estavam, gerando uma imagem limiarizada. Para realizar esse trabalho, usamos o OpenCV uma biblioteca completa e muito popular para a área de imagens em Python. Abaixo segue o resultado das linhas encontradas.
Mas após ter essas linhas identificadas, como deleta-las da imagem?
K-means
A resposta não foi nada mais nada menos que K-means, um algoritmo não supervisionado de aprendizado de máquina que normalmente é utilizado para clusterização, o qual não precisa de inputs externos para seu funcionamento, precisando determinar apenas o número de K, ou seja, a quantidade de agrupamentos necessários para o seu problema.
Mas a final de contas para que esse K-means? O que tem a ver com o problema das linhas?
Como descrito em sua breve introdução, o k-means é utilizado para agrupamentos, dessa forma em vez de deletar as linhas foi realizado um agrupamento de cores na imagem e sobrescrevemos (em vez de deletar) as linhas pela cor predominante da imagem, sendo que normalmente quando se trata de uma tabela nutricional, as cores predominantes são, respectivamente, para o fundo, linhas, letras e, às vezes, detalhes.
Por esse motivo, também, não foi utilizado o famigerado elbow method para definir a quantidade de Ks, pois temos uma situação com o número conhecidos de agrupamentos necessários.
O resultado desse processo é demonstrado na imagem abaixo, assim como as funções utilizadas para sobrescrever as linhas detectadas à priori. O código para uso do k-means pode ser encontrado detalhadamente na biblioteca sklearn ou no repositório do projeto.
EAST — Efficient and Accurate Scene Text Detector
Nessa etapa ainda não temos uma leitura por parte das máquinas, mas utilizamos o EAST, um scene text detector que também é open source com o código disponível no GitHub e, nesse projeto, foi utilizado com o objetivo de facilitar ainda mais o trabalho da máquina, tirando as distrações e focando no texto da imagem.
Como eu disse, o EAST sozinho apenas localiza onde tem texto, mas não realiza a leitura, processo o qual podemos assimilar a um analfabeto, que sabe que tem um texto naquele lugar, mas não faz ideia do que está escrito. Seu resultado é pode ser visualizado na imagem abaixo:
Há tutoriais e publicações excelentes na internet que ensinam a usar esse tipo de tecnologia, dos quais posso citar:
Após aplicarmos o EAST com uma série de filtros morfológicos, então fazemos uma leitura das palavras de no estilo ocidental, ou seja, de cima para baixo e da esquerda para direita, deixando mais próximo do que é realizado na leitura humana, como é demonstrado na imagem a seguir.
Nessa etapa, podemos assimilar não mais a um analfabeto, mas a uma criança que está aprendendo a realizar leitura e entende algumas coisas. Mas como corrigir ou melhorar a leitura dessa criança?
SymSpell
O SymSpell é um algoritmo alternativo para Symmetric Delete spelling correction algorithm, sendo que o SymSpell foi considerado 1000x mais veloz na realização dessa tarefa, trabalhando com um dicionário que é carregado na memória, além de contemplar uma série de linguagens. Seu repositório está no GitHub e pode ser acessado a partir do seguinte link.
Continuando com as nossas assimilações, nesse caso podemos dizer que o SymSpell é como um professor para a nossa leitura, o qual aplica correções das trabalhando com uma distância de similaridade entre as palavras.
Fluxograma e Implementação.
Todo o processo de leitura da imagem com a tabela nutricional até ter o texto corrigido e pronto para o uso resume-se na seguinte imagem.
Além disso, toda a implementação desse projeto encontra-se disponível tanto no Python Package Index (PyPI), podendo ser utilizada em apenas 3 linhas, como no exemplo a seguir.
Vale dizer que esse projeto faz parte da comunidade open source e conta com novas participações de implementação, incluindo a sua! Sinta-se a vontade para contribuir com pull requests e issues.
Muito obrigado pela leitura, espero que tenha agregado em algo para a sua vida. Sinta-se a vontade para entrar em contato, para mais informações!