Olá a todos!
Hoje em dia, todo mundo usa códigos de barras, principalmente sem perceber. Quando compramos as compras na loja, seus identificadores são obtidos a partir de códigos de barras. Também é o mesmo com mercadorias nos armazéns, encomendas postais e assim por diante. Mas poucas pessoas realmente sabem como isso funciona.
O que é 'dentro' do código de barras e o que é codificado nesta imagem?

Vamos descobrir e também vamos escrever nosso próprio decodificador de barras.
1. Introdução
O uso de códigos de barras tem uma longa história. As primeiras tentativas de fazer a automação foram feitas nos anos 50, a patente de um sistema de leitura de códigos foi concedida. David Collins, que trabalhava na Pennsylvania Railroad, decidiu facilitar o processo de classificação dos carros. A idéia era óbvia - codificar os identificadores de carros com faixas de cores diferentes e lê-los usando uma célula fotográfica. Em 1962, esses códigos se tornaram um padrão da Associação das Ferrovias Americanas. (o sistema
KarTrak ). Em 1968, a lâmpada foi substituída por um laser, permitindo aumentar a precisão e reduzir o tamanho do leitor. Em 1973, o Código Universal do Produto foi desenvolvido e, em 1974, o primeiro produto de supermercado (um chiclete Wrigley - obviamente estava nos EUA;) foi vendido. Em 1984, a terceira parte de todas as lojas usava códigos de barras; em outros países, tornou-se popular mais tarde.
Existem muitos tipos diferentes de códigos de barras para aplicativos diferentes, por exemplo, a string "12345678" pode ser codificada dessa maneira (e nem todas elas):

Vamos começar a análise. Todas as informações abaixo serão sobre o tipo "Code-128" - apenas porque é fácil entender o princípio. Quem quiser testar outros modos, pode usar o
gerador de código de barras on-line e testar outros tipos por conta própria.
À primeira vista, um código de barras se parece com um conjunto aleatório de números, mas na verdade sua estrutura é bem organizada:

1 - Espaço vazio, necessário para determinar a posição inicial do código.
2 - Iniciar símbolo. Estão disponíveis três tipos de Código-128 (chamados A, B e C) e os símbolos de início podem ser 11010000100, 11010010000 ou 11010011100, respectivamente. Para esses tipos, as tabelas de codificação são diferentes (consulte a
descrição do Code_128 para obter mais detalhes ).
3 - O próprio código, contendo dados do usuário.
4 - Cheque soma.
5 - Símbolo de parada, para o Code-128 é 1100011101011.
6 (1) - espaço vazio.
Agora vamos dar uma olhada em como os bits estão codificando. É realmente fácil - se levarmos a largura da linha mais fina para "1", a linha de largura dupla será "11", a linha de largura tripla será "111" e assim por diante. O espaço vazio será respectivamente "0", "00" ou "000", de acordo com o mesmo princípio. Quem estiver interessado, pode comparar a sequência de início na imagem acima, para ver se a regra é respeitada.
Agora podemos começar a codificar.
Obtendo a sequência de bits
Em geral, é a parte mais complicada e pode ser feita de maneiras diferentes. Não tenho certeza de que minha abordagem seja ótima, mas para a nossa tarefa é definitivamente suficiente.
Primeiro, vamos carregar a imagem, esticar sua largura, cortar uma linha horizontal a partir do meio, convertê-la em cor preto e branco e salvá-la como uma matriz.
from PIL import Image import numpy as np import matplotlib.pyplot as plt image_path = "barcode.jpg" img = Image.open(image_path) width, height = img.size basewidth = 4*width img = img.resize((basewidth, height), Image.ANTIALIAS) hor_line_bw = img.crop((0, int(height/2), basewidth, int(height/2) + 1)).convert('L') hor_data = np.asarray(hor_line_bw, dtype="int32")[0]
No código de barras, a linha preta corresponde a "1", mas no RGB o preto é contrário, 0, portanto a matriz precisa ser invertida. Também calcularemos o valor médio.
hor_data = 255 - hor_data avg = np.average(hor_data) plt.plot(hor_data) plt.show()
Vamos executar o programa para verificar se o código de barras foi carregado corretamente:

Agora precisamos determinar a largura de um 'bit'. Para fazer isso, extrairemos a sequência, salvando as posições do cruzamento médio de linha.
pos1, pos2 = -1, -1 bits = "" for p in range(basewidth - 2): if hor_data[p] < avg and hor_data[p + 1] > avg: bits += "1" if pos1 == -1: pos1 = p if bits == "101": pos2 = p break if hor_data[p] > avg and hor_data[p + 1] < avg: bits += "0" bit_width = int((pos2 - pos1)/3)
Como estamos salvando apenas os cruzamentos médios de linha, o código "1101" será salvo como "101", o suficiente para obter a largura dos pixels.
Agora vamos fazer a decodificação em si. Precisamos encontrar todos os cruzamentos de linha médios e encontrar o número de bits no último intervalo encontrado. Os números não serão perfeitos (o código pode ser esticado ou dobrado um pouco); portanto, precisamos arredondar o valor para inteiro.
bits = "" for p in range(basewidth - 2): if hor_data[p] > avg and hor_data[p + 1] < avg: interval = p - pos1 cnt = interval/bit_width bits += "1"*int(round(cnt)) pos1 = p if hor_data[p] < avg and hor_data[p + 1] > avg: interval = p - pos1 cnt = interval/bit_width bits += "0"*int(round(cnt)) pos1 = p
Talvez haja uma maneira melhor de fazer isso, os leitores podem escrever nos comentários.
Se tudo foi perfeito, obteremos uma sequência como esta:
11010010000110001010001000110100010001101110100011011101000111011011
01100110011000101000101000110001000101100011000101110110011011001111
00010101100011101011
Decodificação
Em geral, é muito fácil. Os símbolos no
Code-128 são codificados com código de 11 bits, que podem ter codificação diferente (de acordo com essa codificação - A, B ou C, podem ser letras ou dígitos de 00 a 99).
No nosso caso, o início da sequência é 11010010000, que corresponde a um "Código B". Eu estava com preguiça de inserir todos os códigos manualmente, então copiei e colei de uma página da Wikipedia. A análise dessas linhas também foi feita no Python (dica - não faça coisas assim na produção).
CODE128_CHART = """ 0 _ _ 00 32 S 11011001100 212222 1 ! ! 01 33 ! 11001101100 222122 2 " " 02 34 " 11001100110 222221 3 # # 03 35 # 10010011000 121223 ... 93 GS } 93 125 } 10100011110 111341 94 RS ~ 94 126 ~ 10001011110 131141 103 Start Start A 208 SCA 11010000100 211412 104 Start Start B 209 SCB 11010010000 211214 105 Start Start C 210 SCC 11010011100 211232 106 Stop Stop - - - 11000111010 233111""".split() SYMBOLS = [value for value in CODE128_CHART[6::8]] VALUESB = [value for value in CODE128_CHART[2::8]] CODE128B = dict(zip(SYMBOLS, VALUESB))
As últimas partes são fáceis. Primeiro, vamos dividir a sequência em blocos de 11 bits:
sym_len = 11 symbols = [bits[i:i+sym_len] for i in range(0, len(bits), sym_len)]
Por fim, vamos gerar a sequência de saída e exibi-la:
str_out = "" for sym in symbols: if CODE128A[sym] == 'Start': continue if CODE128A[sym] == 'Stop': break str_out += CODE128A[sym] print(" ", sym, CODE128A[sym]) print("Str:", str_out)
Não mostrarei aqui o resultado decodificado da imagem superior, que seja o dever de casa para os leitores (usar os aplicativos baixados para smartphones será considerado trapaça :).
A verificação CRC não está implementada neste código; quem quiser, pode fazer isso sozinho.
Com certeza, esse algoritmo não é perfeito, foi feito em meia hora. Para tarefas profissionais, existem bibliotecas prontas para usar, por exemplo,
pyzbar . Para decodificar a imagem, basta 4 linhas de código:
from pyzbar.pyzbar import decode img = Image.open(image_path) decode = decode(img) print(decode)
(primeiro a biblioteca deve ser instalada usando o comando "pip install pyzbar")
Além disso, o usuário do site
vinograd19 enviou um comentário interessante sobre o histórico de cálculo da soma de verificação de código de barras.
O cálculo do número do cheque é interessante, originou-se evolutivamente.
A soma de verificação é obviamente necessária para evitar decodificação incorreta. Se o código de barras era 1234 e foi decodificado como 7234, precisamos de um método para rejeitar a substituição de 1 a 7. A validação pode não ser perfeita, mas pelo menos 90% dos códigos devem ser verificados corretamente.
1ª abordagem: basta pegar a soma, para ter 0 como o restante da divisão. Os primeiros símbolos contêm dados e o último dígito é assim, que a soma de todos os números é dividida por 10. Após a decodificação, se a quantidade não for divisível por 10 - a decodificação está incorreta e precisa ser repetida. Por exemplo, o código 1234 é válido - 1 + 2 + 3 + 4 = 10. Código 1216 - também é válido, mas 1218 não é.
Isso ajuda a evitar problemas de decodificação. Mas os códigos também podem ser inseridos manualmente, usando o teclado de hardware. Usando isso, outro caso incorreto foi encontrado - se a ordem de dois dígitos for alterada, a soma de verificação ainda estará correta, é definitivamente ruim. Por exemplo, se o código de barras 1234 foi inserido como 2134, a soma de verificação será a mesma. Verificou-se que uma ordem incorreta de dígitos era o caso comum, se uma pessoa está tentando digitar dígitos rapidamente.
2ª abordagem. Vamos melhorar o algoritmo de soma de verificação - vamos calcular os números ímpares duas vezes. Então, se a ordem for alterada, a soma estará incorreta. Por exemplo, o código 2364 é válido (2 + 3 * 2 + 6 + 4 * 2 = 20), mas o código 3264 não é (3 + 2 * 2 + 6 + 4 * 2 = 19). É melhor, mas outro caso apareceu. Existem alguns teclados, com 10 teclas em duas linhas, a primeira linha é 12345 e a segunda é 67890. Se, em vez de "1", o usuário digitar "2", a verificação da soma de verificação falhará. Mas se o usuário digitar "6" em vez de "1" - a soma de verificação pode estar correta algumas vezes. É porque 6 = 1 + 5, e se o dígito tiver um lugar ímpar, obtemos 2 * 6 = 2 * 1 + 2 * 5 - a soma aumentou em 10. O mesmo erro ocorrerá, se o usuário digitar "7 "Em vez de" 2 "," 8 "em vez de" 3 "e assim por diante.
3ª abordagem. Vamos pegar a soma novamente, mas vamos obter números ímpares ... 3 vezes. Por exemplo, o código 1234565 - é válido, porque 1 + 2 * 3 + 3 + 4 * 3 + 5 + 6 * 3 +5 = 50.
Este método tornou-se um padrão para o código EAN13, com algumas alterações: o número de dígitos é fixo e igual a 13, onde o 13º dígito - é a soma de verificação. Os números em lugares ímpares são contados três vezes, em lugares pares uma vez.A propósito, o código EAN-13 é o mais amplamente usado em shoppings e lojas, portanto as pessoas o veem com mais frequência do que outros tipos de código. Sua codificação de bits é a mesma do código 128, a estrutura de dados pode ser encontrada no
artigo da
Wikipedia .
Conclusão
Como podemos ver, mesmo uma coisa fácil como um código de barras, pode conter coisas legais. A propósito, outro pequeno truque para os leitores, que foram pacientes o suficiente para ler até este local - o texto sob o código de barras é totalmente idêntico aos dados do código de barras. Foi feito para os operadores, que podem inserir manualmente o código, se não for legível pelo scanner. Portanto, é fácil conhecer o conteúdo do código de barras - basta ler o texto abaixo.
Obrigado pela leitura.