LPR – License Plate Recognition Brazil – Parte 2

No artigo anterior procurei mostrar como fazer o isolamento da região da placa, citando seguidamente outro artigo para traçar a área retangular sobre a região de interesse. Provavelmente nesse artigo serei odiado, porque vou mostrar como essa etapa poderia ser pulada diretamente para a próxima. Isto é, em muitos casos é comum fazer esse isolamento com vários filtros, mas isso gera processamento e para o Raspberry com certeza isso não é bom, portanto vamos utilizar uma ferramenta mágica do OpenCV para isolar diretamente os dígitos, juntamente a dois filtros simples. No final você ao menos ficará feliz.

Prepare-se para a diversão!

Separando os caracteres da placa

Essa seria a próxima etapa, mas se tivessemos entrado diretamente nela, não teria mostrado as etapas encontradas em tutoriais e livros. E é bom fazer essa comparação, porque você percebe que os procedimentos acabam se tornando uma receita de bolo, sem mais experimentações, sendo que às vezes o resultado poderia ser melhor com pouca manipulação. Bem, o conjunto aplicado aqui é bastante simples; GaussianBlur, Threshold, Mser. O resultado:

Isolamento dos digitos
Isolamento dos digitos

Isso não significa que seja o melhor que se pode tirar. Isso foi o que “eu” consegui de melhor para “essa” imagem. É necessário experimentação, utilizando a câmera como referência. Não dá pra você ficar pegando belas fotos e depois pegar uma placa de verdade num ângulo ruim, má iluminação etc.

Na imagem acima, note que a placa está em um ângulo significativo. A placa é da Mercosul, Argentina. Eu escolhi essa imagem porque a maioria dos carros emplacados que encontrei estavam em um ângulo muito favorável, de frente e no máximo, visto de cima a 45º. O isolamento de caracteres ficou excelente, como você pode ver e o maior problema no ângulo é que se demasiado, o retângulo pode invadir a área pertencente ao próximo digito e então dificultar o reconhecimento do caracter. Por isso, atente-se quando estiver fazendo as provas.




Não se preocupe em copiar o código agora, depois você poderá pegar o projeto no git. Esse código está no formato de exemplo, se copiá-lo, poderá testar em seu computador passando a imagem desejada como argumento. Essa configuração não é ideal para todos os casos, portanto, faça os ajustes dos parâmetros conforme necessário.

Para executar:

O código para essa etapa:

Copiando as regiões de interesse (ROI’s)

Nesse código acima a imagem é salva com o mesmo nome com o sufixo “-out” antecedendo a extensão. Mas isso é só para a exibição visual, o que precisamos é copiar essas regiões encontradas, validar os caracteres e então passá-los ao reconhecimento. Faremos a cópia invés de um retângulo verde nas áreas marcadas, que como você pode ver, inclui 2 falsos-positivo.

As capturas aqui são feitas baseando-se no tamanho da imagem. Existe uma proporção para as letras e essa proporção pode ser obtida dividindo altura por base:

 Proporcao = \frac{Altura}{Base}

Para a fonte Alemã a proporção deu 2 no meu caso. Isso, nessa imagem considerando esse tamanho na captura. Quando capturando os caracteres em ângulo, deve-se considerar uma porcentagem a mais porque o retângulo cresce devido às bordas deslocadas.

Não sei se é certo, se é paranóia ou estupidez, mas eu considerei a quantidade de preto dentro da caixa da letra. Para isso, utilizei um outro recurso do OpenCV chamado countNonZero(). Claro que falsos-positivo podem ter a mesma quantidade de pixels pretos que uma caixa de caracter, mas primeiro eu pego o valor e divido pela proporção encontrada, então coloco um limite de pixels a considerar. Se o falso-positivo estiver fora da proporção, seu valor já é descartado:

Colocando uma condicional (no “meu” caso) que considere as proporções de   \frac{Altura}{Base} = 2 e cv2.countNonZero(dst)/proporcao (> 100 & <290) me ponho a crer que trata-se fortemente de um caracter. A partir dessse ponto já é possível passar as regiões de interesse para o reconhecimento! Uma saída de exemplo desse teste inicial para calcular as proporções:

Validando
Validando

Você pode fazer esse processo todo de inúmeras maneiras, inclusive a proporção da letra sendo 2×1 você já pode colocar como certo. Uma forma que talvez possa atribuir mais segurança seria procurar pelo retângulo da placa em sua devida proporção, mas dependendo da posição da câmera, esse mínimo de tratamento já é mais do que o suficiente. Se for utilizar o modo de separação do conjunto de letras ou do retângulo da placa, uma opção mais seria procurar pelo fundo da placa. Sendo branco no novo modelo, fica fácil de isolar. Com infravermelho sobre a placa 2016 também.

Até aqui o resultado foi o seguinte:

'0'
‘0’

1
1

2
2

3
3

4
4

5
5

6
6

Claro que você deve estar pensando que “a placa está ao contrário”, mas na verdade os retângulos foram pegos do último para o primeiro, portanto, lembre-se de manter a ordem. O código abaixo faz essa separação e salvar as letras com os números conforme a tabela acima (0.jpg, 1.jpg etc):

Classificação

Agora é hora de dar o próximo passo. Precisaremos fazer a classificação para garantir que pegamos as partes certas. Se (por exemplo) você pegou a placa inteira invés de cada caracter, uma boa classificação fará a validação para você. Para isso, utiliza-se uma SVM (Support Vector Machine).

A SVM é um algorítmo de reconhecimento de padrões utilizado em redes neurais supervisionadas, originalmente criado para classificação binária. Esse método aprende através de dados nomeados (“rotulados” ou “labeled”, como preferir). Precisaremos agora treinar o algorítmo com uma quantidade de dados devidamente rotulados e cada conjunto de dados precisa ter uma classe.



Um exemplo clássico é um conjunto bi-dimensional (uma matriz X,Y) para fazer comparações. Esse primeiro treinamento que dará a “noção” para a máquina de aprendizado é chamado de treinamento offline.  Só que mais uma vez, o artigo ficou grande e para não ficar massivo, vou escrever a terceira parte, tratando desse tão interessante assunto, que é o uso de SVM, marchine learning, rede neural, DNN…

Se você não rolou até o final da página, desça um pouco mais e repare que há uma seção para “artigos relacionados”. Logo após “Comments”, tem artigos sugeridos “Você pode gostar também”. Quando terminar a leitura dos artigos, dê uma olhada se algo mais lhe interessa, ok? Diferente de noticias, tutoriais tem vida relativamente longa!

Inscreva-se no nosso newsletter, alí em cima à direita e receba novos posts por email.

Siga-nos no Do bit Ao Byte no Facebook.

Prefere twitter? @DobitAoByte.

Inscreva-se no nosso canal Do bit Ao Byte Brasil no YouTube.

Nossos grupos:

Arduino BR – https://www.facebook.com/groups/microcontroladorarduinobr/
Raspberry Pi BR – https://www.facebook.com/groups/raspberrybr/
Orange Pi BR – https://www.facebook.com/groups/OrangePiBR/
Odroid BR – https://www.facebook.com/groups/odroidBR/
Sistemas Embarcados BR – https://www.facebook.com/groups/SistemasEmbarcadosBR/
MIPS BR – https://www.facebook.com/groups/MIPSBR/
Do Bit ao Byte – https://www.facebook.com/groups/dobitaobyte/

Próximo post a caminho!

Comments

comments

Djames Suhanko

Djames Suhanko é Perito Forense Digital. Já atuou com deployer em sistemas de missão critica em diversos países pelo mundão. Programador Shell, Python, C, C++ e Qt, tendo contato com embarcados ( ora profissionalmente, ora por lazer ) desde 2009.