Hola a todos!
Cada persona está usando códigos de barras hoy en día, principalmente sin darse cuenta de esto. Cuando compramos los comestibles en la tienda, sus identificadores se obtienen de los códigos de barras. También es lo mismo con los productos en los almacenes, paquetes postales, etc. Pero no mucha gente sabe realmente cómo funciona.
¿Qué está 'dentro' del código de barras y qué está codificado en esta imagen?

Vamos a resolverlo, y también vamos a escribir nuestro propio decodificador de barra.
Introduccion
El uso de códigos de barras tiene una larga historia. Los primeros intentos de hacer la automatización se hicieron en los años 50, se otorgó la patente de un sistema de lectura de códigos. David Collins, que trabajaba en el ferrocarril de Pensilvania, decidió facilitar el proceso de clasificación de automóviles. La idea era obvia: codificar los identificadores del automóvil con diferentes franjas de color y leerlos con una celda fotográfica. En 1962, tales códigos se convirtieron en un estándar de la Asociación de Ferrocarriles Americanos. (el sistema
KarTrak ). En 1968, la lámpara fue reemplazada por un láser, lo que permitió aumentar la precisión y reducir el tamaño del lector. En 1973 se desarrolló el Código Universal de Productos, y en 1974 se vendió el primer producto de supermercado (un chicle de Wrigley, obviamente en EE. UU.). En 1984, la tercera parte de todas las tiendas ha utilizado códigos de barras, en otros países se hizo popular más tarde.
Hay muchos tipos diferentes de códigos de barras para diferentes aplicaciones, por ejemplo, la cadena "12345678" se puede codificar de esta manera (y no todas):

Vamos a comenzar el análisis. Toda la información a continuación se referirá al tipo "Código 128", simplemente porque es fácil de entender el principio. Aquellos que quieran probar otros modos, pueden usar
el generador de códigos de barras en línea y probar otros tipos por su cuenta.
A primera vista, un código de barras parece un conjunto aleatorio de números, pero de hecho su estructura está bien organizada:

1 - Espacio vacío, requerido para determinar la posición de inicio del código.
2 - Símbolo de inicio. Hay tres tipos de Código 128 disponibles (llamados A, B y C), y los símbolos de inicio pueden ser 11010000100, 11010010000 o 11010011100 respectivamente. Para estos tipos, las tablas de codificación son diferentes (consulte la
descripción del Código_128 para obtener más detalles ).
3 - El código en sí, que contiene datos del usuario.
4 - Verificar suma.
5 - Símbolo de parada, para el Código 128 su 1100011101011.
6 (1) - Espacio vacío.
Ahora veamos cómo se codifican los bits. Es realmente fácil: si tomamos el ancho de línea más delgado a "1", entonces la línea de doble ancho será "11", la línea de triple ancho será "111", y así sucesivamente. El espacio vacío será respectivamente "0", "00" o "000", según el mismo principio. Aquellos que estén interesados, pueden comparar la secuencia de inicio en la imagen de arriba, para ver que se respeta la regla.
Ahora podemos comenzar a codificar.
Obteniendo la secuencia de bits
En general, es la parte más complicada, y se puede hacer de diferentes maneras. No estoy seguro de que mi enfoque sea óptimo, pero para nuestra tarea es definitivamente suficiente.
Primero, carguemos la imagen, estiremos su ancho, recortemos una línea horizontal desde el centro, la convirtamos a color b / n y la guardemos como una 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]
En el código de barras, la línea negra corresponde a "1", pero en RGB el negro es, por el contrario, 0, por lo que la matriz debe invertirse. También calcularemos el valor promedio.
hor_data = 255 - hor_data avg = np.average(hor_data) plt.plot(hor_data) plt.show()
Ejecutemos el programa para verificar que el código de barras se haya cargado correctamente:

Ahora necesitamos determinar un ancho de un 'bit'. Para hacer esto, extraeremos la secuencia, guardando las posiciones del cruce de línea promedio.
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)
Estamos guardando solo los cruces de línea promedio, por lo que el código "1101" se guardará como "101", pero es suficiente para obtener el ancho de píxeles.
Ahora hagamos la decodificación en sí. Necesitamos encontrar cada cruce de línea promedio y encontrar el número de bits en el último intervalo que se encontró. Los números no coincidirán perfectamente (el código se puede estirar o doblar un poco), por lo tanto, necesitamos redondear el valor a entero.
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
Tal vez hay una mejor manera de hacer esto, los lectores pueden escribir en los comentarios.
Si todo se hizo perfecto, obtendremos una secuencia como esta:
11010010000110001010001000110100010001101110100011011101000111011011
01100110011000101000101000110001000101100011000101110110011011001111
00010101100011101011
Decodificación
En general, es bastante fácil. Los símbolos en el
Código 128 están codificados con un código de 11 bits, que puede tener una codificación diferente (de acuerdo con esta codificación: A, B o C, pueden ser letras o dígitos del 00 al 99).
En nuestro caso, el comienzo de la secuencia es 11010010000, que corresponde a un "Código B". Fui demasiado vago para ingresar todos los códigos manualmente, así que simplemente lo pegué de una página de Wikipedia. El análisis de estas líneas también se realizó en Python (pista: no haga cosas como esta en producción).
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))
Las últimas partes son fáciles. Primero, dividamos la secuencia en bloques de 11 bits:
sym_len = 11 symbols = [bits[i:i+sym_len] for i in range(0, len(bits), sym_len)]
Finalmente, vamos a generar la cadena de salida y mostrarla:
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)
No mostraré aquí el resultado decodificado de la imagen superior, deje que sea la tarea para los lectores (el uso de las aplicaciones descargadas para teléfonos inteligentes se considerará trampa :).
La verificación CRC no está implementada en este código, aquellos que quieran, pueden hacerlo ellos mismos.
Por supuesto, este algoritmo no es perfecto, se realizó en media hora. Para tareas profesionales hay bibliotecas listas para usar, por ejemplo,
pyzbar . Para decodificar la imagen, 4 líneas de código son suficientes:
from pyzbar.pyzbar import decode img = Image.open(image_path) decode = decode(img) print(decode)
(Primero, la biblioteca debe instalarse con el comando "pip install pyzbar")
Adición : el usuario del sitio
vinograd19 envió un comentario interesante sobre el historial de cálculo de la suma de verificación del código de barras.
El cálculo del número de cheque es interesante, se originó evolutivamente.
Obviamente, la suma de verificación es necesaria para evitar una decodificación incorrecta. Si el código de barras era 1234 y se decodificó como 7234, necesitamos un método para rechazar el reemplazo del 1 al 7. La validación puede no ser perfecta, pero al menos el 90% de los códigos deben verificarse correctamente.
1er enfoque: tomemos la suma, para tener 0 como el resto de la división. Los primeros símbolos contienen datos, y el último dígito es así, que la suma de todos los números se divide por 10. Después de la decodificación, si la cantidad no es divisible por 10, la decodificación es incorrecta y debe repetirse. Por ejemplo, el código 1234 es válido - 1 + 2 + 3 + 4 = 10. Código 1216 - también es válido, pero 1218 no lo es.
Ayuda a evitar problemas de decodificación. Pero los códigos también se pueden ingresar manualmente, utilizando el teclado de hardware. Al usar esto, se encontró otro caso incorrecto: si se cambia el orden de dos dígitos, la suma del cheque seguirá siendo correcta, definitivamente es incorrecta. Por ejemplo, si el código de barras 1234 se ingresó como 2134, la suma del cheque será la misma. Se descubrió que un orden de dígitos incorrecto era el caso común, si una persona está tratando de ingresar dígitos rápidamente.
2º enfoque Mejoremos el algoritmo de suma de comprobación: calculemos los números impares dos veces. Luego, si se cambia el orden, la suma será incorrecta. Por ejemplo, el código 2364 es válido (2 + 3 * 2 + 6 + 4 * 2 = 20), pero el código 3264 no lo es (3 + 2 * 2 + 6 + 4 * 2 = 19). Es mejor, pero ha aparecido otro caso. Hay algunos teclados, que tienen 10 teclas en dos filas, la primera fila es 12345 y la segunda es 67890. Si en lugar de "1" el usuario escribirá "2", la verificación de la suma de verificación fallará. Pero si el usuario ingresa “6” en lugar de “1”, la suma de verificación puede ser a veces correcta. Es porque 6 = 1 + 5, y si el dígito tiene un lugar impar, obtenemos 2 * 6 = 2 * 1 + 2 * 5 - la suma ha aumentado en 10. El mismo error ocurrirá, si el usuario ingresa "7 "En lugar de" 2 "," 8 "en lugar de" 3 ", y así sucesivamente.
3er enfoque. Tomemos la suma nuevamente, pero obtengamos números impares ... 3 veces. Por ejemplo, el código 1234565 - es válido, porque 1 + 2 * 3 + 3 + 4 * 3 + 5 + 6 * 3 +5 = 50.
Este método se convirtió en un estándar para el código EAN13, con algunos cambios: el número de dígitos es fijo e igual a 13, donde el dígito 13 es la suma del cheque. Los números en lugares impares se cuentan tres veces, en lugares pares una vez.Por cierto, el código EAN-13 es el más utilizado en centros comerciales y de compras, por lo que las personas lo ven con más frecuencia que otros tipos de códigos. Su codificación de bits es la misma que en el Código 128, la estructura de datos se puede encontrar en el
artículo de Wikipedia .
Conclusión
Como podemos ver, incluso algo tan fácil como un código de barras puede contener algunas cosas interesantes. Por cierto, otro pequeño truco para los lectores, que fueron lo suficientemente pacientes como para leer hasta este lugar: el texto debajo del código de barras es completamente idéntico a los datos del código de barras. Fue hecho para los operadores, que pueden ingresar manualmente el código, si el escáner no lo puede leer. Por lo tanto, es fácil saber el contenido del código de barras: solo lea el texto a continuación.
Gracias por leer