Pesquisa de código de barras incrivelmente precisa, rápida e leve através de segmentação semântica

Procurar objetos em imagens? Com uma amostra de treinamento e um conjunto mínimo de conhecimentos sobre redes neurais, qualquer estudante hoje pode obter uma solução com uma certa precisão. No entanto, a maioria das redes neurais usadas para resolver esse problema é bastante profunda e, portanto, exige muitos dados para treinamento, eles trabalham de forma relativamente lenta na fase de inferência (especialmente se o dispositivo não tiver uma GPU), pesam muito e consomem muita energia. Todos os itens acima podem ser muito críticos em certos casos, principalmente para aplicativos móveis.


Os códigos de barras são objetos com uma estrutura bastante simples. No decorrer da pesquisa, fomos capazes, usando uma abordagem relativamente original, de procurar objetos simples com muita precisão (superamos o estado da arte) e com rapidez suficiente (em tempo real em uma CPU média). Além disso, nosso detector é muito leve, tendo apenas 30k de peso. Falaremos sobre os resultados de nossa pesquisa neste artigo.


Mas, antes de falar sobre a solução, ainda vale a pena mergulhar na área de assunto e talvez valha a pena começar com o que são os códigos de barras.


O que é um código de barras e por que procurá-lo?


Códigos de barras é um nome genérico para um grupo de formatos de dados legíveis por máquina. Você provavelmente já ouviu falar sobre códigos de barras e códigos QR - esses são apenas casos especiais de códigos de barras. No mundo moderno, eles podem ser encontrados em ingressos, mercadorias em lojas, documentos oficiais e em muitos outros lugares.



Os códigos de barras são geralmente divididos em unidimensionais, representados por um conjunto de listras preto e branco, e bidimensionais, consistindo em pequenos blocos quadrados ou retangulares. Como você pode ver na figura, em geral, os vários tipos são muito semelhantes entre si.


A complexidade pode ser representada por alguns tipos de códigos de barras para os quais o comprimento não é especificado. Esses códigos de barras podem ser arbitrariamente longos e, ao mesmo tempo, muito finos.



O exemplo acima é artificial, mas códigos de barras com proporções semelhantes são encontrados em documentos reais, principalmente em faturas.


E como esses são formatos legíveis por máquina, eles devem ser relativamente facilmente reconhecidos pelo hardware. No entanto, o primeiro passo no caminho para o reconhecimento é a pesquisa, e será discutido neste artigo.


Vale a pena notar que os scanners a laser e muitas aplicações implicam a participação ativa de uma pessoa - você precisa apontar claramente a câmera / scanner para o código de barras para que seja reconhecido, e nesse caso a necessidade de pesquisa desaparece. No entanto, nesse cenário, os usuários são forçados a gastar esforços adicionais da parte deles, o que não é bom. Essa abordagem também não permite o reconhecimento de vários objetos na imagem, limitados a apenas um.


Declaração do problema e métricas de qualidade


O que gostaríamos do detector de código de barras criado?


  1. Encontrar todos os códigos de barras na imagem é preciso o suficiente *
  2. Encontre códigos de barras longos e muito estreitos
  3. Tempo real na CPU

* Propõe-se usar a medida f para objetos com um limiar de IoU = 0,5 como a principal métrica de precisão. Também veremos a precisão, a recuperação e a taxa de detecção.


Definição formal de métricas

Primeiro, apresentamos o conceito de IoU - Intersecção sobre União (também conhecido como Índice Jaccard). Tendo verdadeiro ( G) e previsto ( F) a máscara do objeto, IoU é calculada como a área de interseção dividida pela área da união.

J(G,F)= frac|G capF||G cupF|



É fácil ver que a IoU assume valores de 0 a 1. Agora, com base nessa medida, apresentamos os conceitos de precisão, recuperação, medida f e taxa de detecção.


Que haja N objetos na amostra. Definimos o limiar IoU igual a algum número fixo t(por exemplo, 0,5). Para algum objeto Ge detecção Facredito que se J(G,F) get, o objeto foi encontrado (1), caso contrário, acreditamos que o objeto não foi encontrado (0). Então recordação(t)definida como a proporção de objetos de amostra encontrados, precisão(t)- a proporção de detecções correspondentes a pelo menos um objeto de amostra. A medida f é definida padronmente como média harmônica 2precisão(t)recall(t)/(precisão(t)+recall(t)).


Resta entender o que é uma taxa de detecção. Haja M figuras com objetos na amostra. Calculamos a IoU entre as máscaras verdadeira e prevista na figura , cortando da mesma forma o limiar da figura. A taxa de detecção é a fração de imagens pela qual a IoU total de todos os objetos verdadeiros com a IoU total de todos os objetos previstos é maior que um determinado limite t.


Em estudos anteriores (sobre a detecção de códigos de barras), é habitual usar a taxa de detecção para avaliar a qualidade. No entanto, vamos considerar esta situação - haja um objeto muito grande e um objeto muito pequeno na imagem, mas o detector foi grande e não foi pequeno. Nesse caso, a taxa de detecção sinalizará apenas um erro se o limite for muito grande. tperto de 1. enquanto recallnão será maior que 0,5 para valores-limite arbitrários t, que também tornará a medida f menor que 1. Ou seja, para esse exemplo, a medida f pode sinalizar um erro mais cedo (no sentido de um limite mais baixo t) que a taxa de detecção.


Portanto, em nossos experimentos, contamos com a medida f e usamos a taxa de detecção para comparar com o trabalho dos anos anteriores.


Inspirado em detectores de texto


Talvez o detector de objetos mais famoso e popular quando a velocidade é importante seja o YOLO (você só olha uma vez). Também existem versões posteriores do YOLOv2 e YOLOv3, mas, em geral, essa abordagem é boa para objetos mais ou menos quadrados, mas, ao encontrar objetos estreitos, mas muito alongados, essa abordagem não é tão forte.


Então decidimos seguir o outro caminho. Como você pode ver facilmente, as linhas com texto na imagem também são muito alongadas e estreitas, e a tarefa de encontrar texto em imagens na comunidade científica é bastante popular (certamente mais popular do que procurar códigos de barras) e várias arquiteturas interessantes baseadas na estrutura gráfica foram inventadas para isso. Nossa decisão é motivada por apenas um dos trabalhos de pesquisa de texto nos quais a arquitetura PixelLink é proposta.



A essência da abordagem é a seguinte - vamos resolver o problema da segmentação de instância assim:


  1. Para cada pixel, resolveremos o problema de classificação binária (texto / não texto).
  2. Para cada pixel, preveremos 8 links (links) com seus vizinhos. Comunicação significa que esse par de pixels pertence a um objeto (instância).
  3. Tendo recebido um mapa de segmentação por texto / não texto e mapas com links da imagem, montamos um gráfico no qual os vértices serão pixels cuja previsão de classe de texto e as bordas são links.
  4. Encontramos componentes conectados neste gráfico.
  5. Em torno de cada componente conectado, selecione o retângulo mínimo incluído (por exemplo, usando OpenCV), que será a detecção final.

Esse processo é ilustrado graficamente, a figura é retirada do artigo original .



Essa abordagem para procurar texto fornece resultados bastante decentes comparáveis ​​ao estado da arte.



Voltamos agora aos códigos de barras. Nós nos perguntamos - realmente precisamos desses links? Afinal, os códigos de barras, ao contrário do texto, na grande maioria dos casos, estão longe um do outro. E, de fato, de acordo com a especificação, muitos tipos de códigos de barras devem ter um certo espaço para os objetos vizinhos mais próximos.
Em geral, decidimos que não precisávamos de links e modificamos a abordagem da seguinte maneira:


  1. Resolvemos o problema da segmentação semântica - para cada pixel, determinamos a classe do código de barras / não código de barras.
  2. Construímos um gráfico com vértices em pixels para os quais o tipo de código de barras é determinado. Como arestas, em vez de procurar links, consideramos que existe um link entre qualquer par de pixels adjacentes do tipo de código de barras.
  3. Encontramos componentes conectados neste gráfico.
  4. Ao redor de cada componente conectado, selecione o retângulo mínimo anexo, que será a detecção final.

Então, decidimos o esquema geral da solução. Os parágrafos 2 a 4 podem ser considerados triviais, mas vamos discutir como lidar exatamente com a segmentação semântica.


Arquitetura de rede para segmentação semântica


Um pouco de história que é comumente usado


Em geral, a segmentação semântica usando redes neurais vem ocorrendo desde 2013, desde o advento da U-Net. No U-Net, a resolução espacial foi reduzida gradualmente primeiro no codificador, depois aumentada gradualmente no decodificador; também houve conexões de salto de recursos intermediários do codificador para recursos intermediários do decodificador. Um pouco mais tarde, apareceram convoluções dilatadas (veja a figura abaixo), que produziram melhor qualidade, mas exigiram mais memória e cálculos para o processamento. Bem, no final, havia uma abordagem conhecida como Deeplabv3 +, combinando essas duas abordagens e sendo o estado da arte entre as arquiteturas projetadas por seres humanos no momento em que este artigo foi escrito (de fato, graças à Neural Architecture Search, soluções mais eficazes, por exemplo ).


Vamos nos concentrar um pouco mais na convolução dilatada, porque na decisão final, confiaremos em suas propriedades.


Convolução normal funciona assim



Enquanto a convolução dilatada é mostrada abaixo (na imagem, o fator dilatado é 2)



Você pode notar que a convolução convencional é realmente um caso especial de convolução dilatada (com fator de dilatação 1).


Em geral, uma discussão de soluções para segmentação semântica é um tópico para um artigo bastante grande e separado. Eu só queria fazer um pequeno lembrete no qual a coisa mais importante é lidar com o dispositivo de convolução dilatado. Se você é novo na segmentação semântica, aqui está a melhor revisão conhecida pelo autor, no entanto, para entender o que acontecerá a seguir, a familiarização com ela não é necessária.


Se tudo fosse tão simples ...


O principal requisito para nossa rede neural, além da qualidade, é a velocidade. Em nossos dados, existem códigos de barras tão pequenos em relação ao tamanho da imagem que a resolução mínima na qual faz sentido executar uma rede neural deve ser de pelo menos 512x512 e, de preferência, 1024x1024. Ao mesmo tempo, é necessário trabalhar na CPU por não mais que 100 ms na imagem (e também em um núcleo!). Em termos do conjunto de requisitos para a resolução de entrada e o tempo total de operação, a tarefa não é muito trivial. Com restrições tão severas, o uso de arquiteturas fortes e profundas não é possível. Para ser justo, ainda não cumprimos o requisito de 100 ms em um núcleo, mas a solução final funciona 40 ms em 4 núcleos (Intel Core i5, 3,2 GHz).


Infelizmente, todas as arquiteturas que conhecemos para segmentação semântica categoricamente não se encaixam nessas restrições. Então tivemos uma escolha: ou não se sabe como criar algo completamente novo, ou tente simplificar o máximo possível uma das arquiteturas populares. Como não tínhamos idéias brilhantes, escolhemos a última.


Inspirado pela Rede de Agregação de Contexto


As convoluções dilatadas têm a seguinte propriedade útil - se você as aplicar seqüencialmente com um fator dilatado exponencialmente crescente, o campo receptivo crescerá exponencialmente (enquanto que no caso das convoluções comuns ele cresce linearmente).



A figura ( fonte ) mostra o aumento exponencial no campo receptivo da rede neural ao aplicar sequencialmente a convolução dilatada. (a) F1 é obtido de F0 por convolução com dilatação = 1, campo receptivo = 3x3 para cada elemento em F1 (b) F2 é obtido de F1 por convolução com dilatação = 2, campo receptivo = 7x7 para cada elemento em F2 (c) F3 obtido de F2 usando convolução com dilatação = 4, campo receptivo = 15x15 para cada elemento em F3


No artigo "Agregação de contexto em escala múltipla por convoluções dilatadas" com base nessa propriedade, foi inventado um bloco especial (chamado pelos autores do Módulo de Contexto), usado para coletar informações do contexto do pixel atual. No artigo, esse bloco é usado no topo de uma rede que já sabe como resolver o problema de segmentação para refinar essas previsões usando informações de contexto.


Decidimos usar esse Módulo de Contexto, mas não o utilizamos para melhorar as previsões de um bom modelo existente, mas como a parte principal da rede de convolução, que resolverá esse problema. Em geral, nossa arquitetura é organizada da seguinte forma (consulte a tabela):


  1. Módulo de redução de escala - convolução inicial para extrair os recursos mais simples e reduzir a resolução.
  2. O Módulo de Contexto é essencialmente um conjunto de convoluções dilatadas que aumentarão rapidamente o campo receptivo, reunindo atributos de um contexto maior.
  3. A camada final (convolução 1x1), recebendo um mapa de probabilidade para segmentação semântica de código de barras / não código de barras. Além disso, se quisermos distinguir entre o tipo de código de barras detectado, N canais são previstos adicionalmente (veja abaixo).


Ou seja, na arquitetura resultante, um número pequeno e constante de C = 24 canais é usado em cada camada, as três primeiras convoluções reduzem a resolução, as convoluções subsequentes (Módulo de Contexto) aumentam o campo receptivo de cada elemento do mapa de características.


A tabela de hiperparâmetros da arquitetura, entre outras coisas, indica se a convolução na camada atual é separável. Convoluções separáveis ​​teoricamente dão uma aceleração da ordem de k ^ 2 vezes em comparação com uma convolução convencional, onde k é o tamanho do filtro. Na prática, a aceleração pode ser muito menor (tudo depende da resolução da imagem, do número de filtros de entrada e saída).


Inicialmente, tentamos separar todas as convoluções, mas isso fez com que a qualidade caísse muito. Decidimos, então, separar apenas as três primeiras convoluções, que funcionam com resoluções de imagem mais altas e, portanto, exigem mais cálculos que as convoluções subsequentes. Ao mesmo tempo, a qualidade dessa substituição já caiu um pouco. Total devido à separabilidade, a rede neural acelerou outros 20%.


Resta o último momento inexplicável - o que significa o número N na última camada. N é responsável pelo número de diferentes tipos de objetos (no nosso caso, códigos de barras) que queremos distinguir. Se considerarmos o caso mais simples - quando você só precisa encontrar objetos e não precisar determinar seu tipo (este é um código de barras e não importa o que seja) - considere N = 0. Se ainda queremos distinguir entre tipos de códigos de barras (este é um código de barras do tipo [tal-e-tal]), na última camada são adicionados N canais nos quais são previstas as probabilidades de ser de um determinado tipo. Agora, tendo recebido a detecção na forma do retângulo no qual o código de barras está localizado, podemos calcular as probabilidades das classes dentro desse retângulo encontrado, a partir das quais podemos descobrir o tipo do código de barras encontrado.


Resultados


Depois de receber uma solução, você deve sempre procurar e comparar a qualidade da solução com estudos anteriores. Em geral, a tarefa de procurar códigos de barras não é muito popular. Nos últimos 10 anos, apenas 1-2 artigos foram publicados por ano (como você sabe, a maneira mais simples de superar o estado da arte é encontrar a tarefa impopular que fizemos no final. .). A tabela abaixo se compara a outras abordagens em dois conjuntos de dados, em um dos quais obtivemos melhores resultados.



A excelência, é claro, não é super impressionante, mas ainda está presente. No entanto, o principal recurso da solução encontrada não é exatamente, mas em velocidade - em comparação com o mesmo YOLO na mesma GPU (GTX 1080) e com uma resolução de imagem mais alta, nosso método funciona ~ 3,5 vezes mais rápido.



Além da vantagem de velocidade, há uma vantagem no peso do modelo final. O detector possui ~ 30 mil escalas, enquanto a grande maioria das redes de convolução modernas (mesmo aprimoradas para dispositivos móveis) possui milhões de parâmetros. A solução final pesa ainda menos que o LeNet, que tinha ~ 60 mil parâmetros.


Conclusão


De fato, este trabalho é baseado em duas idéias simples:


  1. Detecção por segmentação semântica.
  2. Usando uma sequência de convolução dilatada com um pequeno número de canais para maximizar o campo receptivo.

O resultado foi uma arquitetura muito leve e rápida, que, no entanto, mostrou resultados bastante decentes (e até superou a SOTA na tarefa impopular de encontrar códigos de barras). Além disso, a aplicação dessa abordagem não se limita aos códigos de barras. Usamos a mesma arquitetura para encontrar texto, pesquisar cartões de visita e passaportes, obtendo bons resultados para essas tarefas.


No entanto, vale ressaltar que essa abordagem neste formulário tem limitações. Se 2 objetos do mesmo tipo estiverem localizados muito próximos, eles se unirão em um. Talvez na próxima série, mostraremos como lidar com esse problema.


Com base nos resultados de experimentos com códigos de barras, escrevemos um artigo que será apresentado no ICDAR2019 em Sydney.


Literatura


  1. Um artigo com os resultados de nossas experiências e um grande número de detalhes. Detector universal de código de barras via segmentação semântica
  2. Um excelente artigo de revisão sobre o desenvolvimento de arquiteturas para segmentação semântica. link
  3. PixelLink: Detectando texto de cena por meio de segmentação de instância
  4. Este artigo é sobre o uso da convolução dilatada para melhorar as previsões, reunindo informações do contexto. Agregação de Contexto Multi-Escala por Convoluções Dilatadas

Grupo de Pesquisa em Visão Computacional

Source: https://habr.com/ru/post/pt455764/


All Articles