驴C贸mo se organiza el c贸digo de barras?

Hola Habr!

Una persona moderna encuentra c贸digos de barras todos los d铆as, sin siquiera pensarlo. Cuando compramos productos en el supermercado, sus c贸digos se leen precisamente con la ayuda de un c贸digo de barras. Tambi茅n paquetes, productos en almacenes, y as铆 sucesivamente. Sin embargo, pocas personas saben c贸mo funciona realmente.

驴C贸mo est谩 organizado el c贸digo de barras y qu茅 est谩 codificado en esta imagen?



Intentemos resolverlo, al mismo tiempo escribiremos un decodificador de dichos c贸digos.

Introduccion


El uso de c贸digos de barras tiene una larga historia. Los primeros intentos de automatizaci贸n comenzaron en la d茅cada de 1950; una patente para un lector de c贸digo se obtuvo en 1952. El ingeniero involucrado en la clasificaci贸n de los vagones en el ferrocarril quer铆a simplificar el proceso. La idea era obvia: codificar el n煤mero con tiras y leerlas con fotoc茅lulas. En 1962, los c贸digos comenzaron a usarse oficialmente para identificar autos en el ferrocarril estadounidense (sistema KarTrak ), en 1968 el reflector fue reemplazado por un rayo l谩ser, lo que aument贸 la precisi贸n y redujo el tama帽o del lector. En 1973, apareci贸 el formato "C贸digo de producto universal", y en 1974 el primer producto se vendi贸 usando un esc谩ner de c贸digo (el chicle de Wrigley es Estados Unidos) en un supermercado. En 1984, un tercio de las tiendas usaban serpentinas, pero en Rusia comenzaron a usarse alrededor de los a帽os 90.

Se utilizan muchos c贸digos diferentes para diferentes tareas, por ejemplo, la secuencia "12345678" se puede representar de esta manera (y esto no es todo):



Comencemos el an谩lisis bit a bit. Adem谩s, todo lo que se describe a continuaci贸n se referir谩 al formulario "C贸digo 128", simplemente porque su formato es bastante simple y directo. Aquellos que deseen experimentar con otras especies pueden abrir un generador en l铆nea y ver por s铆 mismos.

A primera vista, el c贸digo de barras parece ser solo una secuencia aleatoria de l铆neas, de hecho, su estructura est谩 claramente fijada:



1 - Espacio vac铆o necesario para identificar claramente el inicio del c贸digo
2 - S铆mbolo de inicio. Para el C贸digo 128, son posibles 3 opciones (llamadas A, B y C): 11010000100, 11010010000 o 11010011100, corresponden a diferentes tablas de c贸digos (m谩s en Wikipedia ).
3 - En realidad, el c贸digo que contiene los datos que necesitamos
4 - Suma de verificaci贸n
5 - S铆mbolo de parada. Para el C贸digo 128, esto es 1100011101011.
6 (1) - Espacio vac铆o.

Ahora sobre c贸mo se codifican los bits. Aqu铆 todo es muy simple: si toma el ancho de la l铆nea m谩s delgada como "1", la l铆nea de doble ancho dar谩 el c贸digo "11", un triple "111", y as铆 sucesivamente. El espacio vac铆o ser谩 "0" o "00" o "000" seg煤n el mismo principio. Aquellos que lo deseen pueden comparar el c贸digo de inicio en la imagen para asegurarse de que se cumpla la regla.

Ahora puedes comenzar a programar.

Obtenga la secuencia de bits


En principio, esta es la parte m谩s dif铆cil y, por supuesto, algor铆tmicamente, se puede implementar de diferentes maneras. No estoy seguro de que el siguiente algoritmo sea 贸ptimo, pero es suficiente para un estudio de caso.

Para comenzar, cargue la imagen, est铆rela en ancho, tome una l铆nea horizontal desde el centro de la imagen, convi茅rtala en b / w y c谩rguela 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, "1" corresponde a negro, y en RGB, por el contrario, 0, por lo que la matriz debe invertirse. Al mismo tiempo, calculamos el valor promedio.

 hor_data = 255 - hor_data avg = np.average(hor_data) plt.plot(hor_data) plt.show() 

Iniciamos el programa para asegurarnos de que el c贸digo de barras se cargue correctamente:



Ahora necesita determinar el ancho de un "bit". Para hacer esto, destacamos el comienzo de la secuencia de inicio "1101", registrando los momentos de transici贸n del gr谩fico a trav茅s de la l铆nea media.

 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) 

Registramos solo las transiciones a trav茅s del medio, por lo que el c贸digo "1101" se escribir谩 como "101", pero esto es suficiente para que podamos encontrar su ancho en p铆xeles.

Ahora la decodificaci贸n real. Encontramos la siguiente transici贸n a trav茅s del medio, y determinamos el n煤mero de bits que caen en el intervalo. Como la coincidencia no es absoluta (el c贸digo puede estar ligeramente curvado o estirado), utilizamos el redondeo.

 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 

No estoy seguro de si esta es la mejor opci贸n, tal vez hay una mejor manera, aquellos que lo deseen pueden escribir en los comentarios.

Si todo se hizo correctamente, obtenemos la siguiente secuencia de salida:

11010010000110001010001000110100010001101110100011011101000111011011
01100110011000101000101000110001000101100011000101110110011011001111
00010101100011101011


Decodificaci贸n


Aqu铆, en principio, no hay dificultades. Los caracteres en el C贸digo 128 est谩n codificados con un c贸digo de 11 bits, que tiene 3 variedades (A, B y C) y puede almacenar diferentes codificaciones de caracteres o n煤meros del 00 al 99.

En nuestro caso, el comienzo de la secuencia es 11010010000, que corresponde al "C贸digo B". Se rompi贸 terriblemente para manejar manualmente todos los c贸digos de Wikipedia, por lo que la tabla simplemente se copi贸 del navegador y su an谩lisis tambi茅n se realiz贸 en Python (pista: esto no es necesario para la 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)) 

Ahora queda lo m谩s simple. Rompemos nuestra secuencia de bits en bloques de 11 caracteres:

 sym_len = 11 symbols = [bits[i:i+sym_len] for i in range(0, len(bits), sym_len)] 

Finalmente, formamos la l铆nea y la mostramos en la pantalla:

 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 dar茅 la respuesta a lo que est谩 codificado en la tabla, deje que sea una tarea para los lectores (el uso de programas listos para tel茅fonos inteligentes se considerar谩 trampa :).

El c贸digo tampoco implementa la verificaci贸n CRC, quienes lo deseen pueden hacerlo ellos mismos.

Por supuesto, el algoritmo es imperfecto y se escribi贸 en media hora. Para fines m谩s profesionales, hay bibliotecas listas para usar , por ejemplo pyzbar . El c贸digo que usa una biblioteca de este tipo solo tomar谩 4 l铆neas:

 from pyzbar.pyzbar import decode img = Image.open(image_path) decode = decode(img) print(decode) 

(primero debe instalar la biblioteca ingresando el comando pip install pyzbar)

Adici贸n : vinograd19 escribi贸 en los comentarios sobre el conteo de CRC:

La historia del d铆gito de verificaci贸n es interesante. Surgi贸 evolutivamente.
El d铆gito de verificaci贸n es necesario para evitar una decodificaci贸n incorrecta. Si el c贸digo de barras era 1234 y se reconoci贸 como 7234, entonces necesita una validaci贸n que evitar谩 el reemplazo de 1 por 7. La validaci贸n puede ser inexacta, de modo que al menos el 90% de los n煤meros no v谩lidos se determinan por adelantado.

1er enfoque: tomemos la cantidad. Para que el resto de la divisi贸n entre 10 sea 0. Bueno, es decir, los primeros 12 caracteres llevan una carga de informaci贸n, y el 煤ltimo d铆gito se selecciona de modo que la suma de los d铆gitos se divida por 10. Decodifique la secuencia, si la suma no es divisible por diez, significa decodificado con un error y debe hacerlo Esta vez m谩s. Por ejemplo, el c贸digo 1234 es v谩lido. 1 + 2 + 3 + 4 = 10. El c贸digo 1216 tambi茅n es v谩lido, pero 1218 no lo es.

Esto evita problemas con la automatizaci贸n. Sin embargo, en el momento de crear los c贸digos de barras, hubo un retroceso en la forma de escribir un n煤mero en las teclas. Y hay un mal caso: si cambia el orden de los dos d铆gitos, la suma de verificaci贸n no cambia, y esto es malo. Es decir, si el c贸digo de barras 1234 se introdujo como 2134, la suma de verificaci贸n converger谩, pero ingresamos el n煤mero incorrecto. Resulta que el orden incorrecto de los n煤meros es un caso com煤n si toca las teclas r谩pidamente.

2潞 enfoque Bueno, hagamos que la cantidad sea un poco m谩s complicada. Para que los n煤meros en lugares pares se tengan en cuenta dos veces. Luego, al cambiar el orden, la cantidad definitivamente no converger谩 al deseado. Por ejemplo, el c贸digo 2364 es v谩lido (2 + 3 + 3 + 6 + 4 + 4 = 20), y el c贸digo 3264 no es v谩lido (3+ 2 + 2 + 6 + 4 + 4 = 19). Pero aqu铆 hab铆a otro mal ejemplo de conducci贸n. Algunos teclados son tales que diez d铆gitos est谩n dispuestos en dos filas. la primera fila es 12345 y debajo de la segunda segunda fila es 67890. Si, en lugar de la tecla "1", presione la tecla "2" a la derecha, la suma de verificaci贸n evitar谩 la entrada incorrecta. Pero si en lugar de la tecla "1", presiona la tecla "6" a continuaci贸n, es posible que no advierta. Despu茅s de todo, 6 = 1 + 5, y en el caso de que esta cifra est茅 en un lugar par al calcular la suma de verificaci贸n, tenemos 2 * 6 = 2 * 1 + 2 * 5. Es decir, la suma de verificaci贸n aument贸 exactamente 10, por lo que su 煤ltimo d铆gito no ha cambiado. Por ejemplo, las sumas de verificaci贸n en los c贸digos 2134 y 2634 son las mismas. El mismo error ocurrir谩 si presionamos 7 en lugar de 2, en lugar de 3 presionamos 8, y as铆 sucesivamente.

3er enfoque. Ok, tomemos la suma nuevamente, solo se tendr谩n en cuenta los n煤meros en lugares pares ... tres veces. Es decir, el c贸digo 1234565 es v谩lido, porque 1 + 2 * 3 + 3 + 4 * 3 + 5 + 6 * 3 +5 = 50.

El m茅todo descrito se ha convertido en el est谩ndar para calcular la suma de verificaci贸n EAN13 con algunas correcciones: el n煤mero de d铆gitos se ha vuelto fijo e igual a 13, donde el 13 es la misma suma de verificaci贸n. Los n煤meros en lugares impares se cuentan tres veces, en pares, una vez.

Conclusi贸n


Como puede ver, incluso algo tan simple como un c贸digo de barras tiene muchas cosas interesantes. Por cierto, otro truco de vida para aquellos que han le铆do hasta aqu铆: el texto debajo del c贸digo de barras (si lo hay) duplica completamente su contenido. Esto se hace para que, en caso de c贸digo ilegible, el operador pueda ingresarlo manualmente. Por lo tanto, averiguar el contenido de un c贸digo de barras suele ser simple: solo mire el texto debajo de 茅l.

Como se sugiere en los comentarios, el m谩s popular en el comercio es el c贸digo EAN-13, la codificaci贸n de bits es la misma all铆, y aquellos que lo deseen pueden ver la estructura de los personajes.

Si los lectores no han perdido inter茅s, puede considerar por separado los c贸digos QR.

Gracias por su atencion

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


All Articles