En lugar del prólogo
No hace mucho tiempo, en Internet, aprendí sobre una copia tan maravillosa y sorprendente de la biblioteca de Babilonia como
la fórmula Tapper . Más bien, es más la desigualdad de Tupper que la fórmula. La peculiaridad de esta desigualdad es que crea su propia imagen en el gráfico. ¡Solo mira este milagro!

(Fuente de Wikipedia)
Lo que ves en la imagen es la fórmula de ese mismo Jeff Tupper. Probablemente, la mitad de los lectores ya han ido al tungsteno para dibujar el resultado de esta desigualdad ... Pero esto no es tan simple. Como puede ver en esta imagen, la fórmula en el gráfico se puede ver en un segmento a lo largo del eje OY [k; k + 15]. ¿Cuál es este misterioso número k? ¿Dónde conseguirlo? ¡La cuestión es que esta desigualdad, según el concepto de la biblioteca de Babilonia, puede mostrar absolutamente cualquier imagen con una resolución de 106x17! Cada imagen tiene su propia posición en el gráfico, por lo tanto tiene un número único k. ¡Por lo tanto,
para cada número k hay una sola imagen en todo el gráfico !
Para una imagen dada, el número k es el siguiente:
4858450636189713423582095962494202044581400587983244549483093085061934704708809928450644769865524364849997247024915119110411605739177407856919754326571855442057210445735883681829823754139634338225199452191651284348332905131193199953502413758765239264874613394906870130562295813219481113685339535565290850023875092856892694555974281546386510730049106723058933586052544096664351265349363643957125565695936815184334857605266940161251266951421550539554519153785457525756590740540157929001765967965480064427829131488548259914721248506352686630476300
Es interesante observar a las personas que se desplazarán a dicha coordenada para ver la fórmula.Se me ocurrió escribir un programa en Python3 que convertiría una imagen en un número k y viceversa y le informaría sobre otra excelente forma de codificar una imagen en un número.
Teoría
(Agregado) ¿Cómo funciona?
Echemos un vistazo a la fórmula en sí:

Definamos su sintaxis:

- número redondeado hacia abajo
mod (x, y) - resto de dividir x por y
Y luego, al parecer, todo está claro.
Tenga en cuenta que tanto x como y se redondean hacia abajo. Es este redondeo lo que finalmente nos da una imagen de píxeles

Denote todo lo que se redondea en el lado derecho de la desigualdad por
.
Entonces
Lo cual es obvio, porque toda la expresión se redondea hacia abajo.
Sea y = 17r + q, donde r es la parte entera de dividir y por 17, y r es el resto de la división. Por lo tanto, podemos reemplazar en la fórmula
en r, y
en q.
Nosotros obtenemos
O de lo contrario
mod (
, 2) toma 2 valores - 0 o 1. En consecuencia, esta desigualdad dirá si el número
incluso o no
Tenga en cuenta que la imagen se ve en el intervalo [N, N + 16], respectivamente
permanece constante en toda la altura de la imagen, lo que no se puede decir sobre el número r (en toda la imagen varía de 0 a 16).
Y ahora la guinda del pastel. Numero
será impar si y solo si el número de bit (17x + r) en la representación binaria de q es igual a 1. Y dado que el número q cambia constantemente con su altura y su representación binaria también, ¡siempre obtenemos una imagen única! Eso es exactamente lo que funciona la fórmula de Tapper.
Ahora veamos cómo calcular la altura a la que queremos ver nuestra imagen
El principio de calcular el número k
El mismo Tupper describió el cálculo del número k para cualquier imagen de 106x17 (¡esto es importante!) De la siguiente manera:
- Convertir imagen a blanco y negro
- Lea cada píxel de abajo hacia arriba, de izquierda a derecha y colóquelo en el búfer. Si el píxel es negro, ponga 1, si es blanco, 0.
- Convertir binario a decimal y multiplicar por 17
- Beneficio!
Para obtener una imagen del número k, hacemos todo exactamente lo contrario. Bueno, vamos a codificar!
Kodim
UPD: En los comentarios, la gente mejoró un poco el código, lo hizo más simple y más transparente. Este artículo ha publicado datos de actualización. Si desea ver las versiones anteriores del código, vaya al repositorio de github (hasta que lo confirme, enlace al final del artículo) y en el comentarioDe k a imagen
UPD
A pedido de los comentaristas,
se agregó una nueva forma de calcular la imagen utilizando esta desigualdad y k! ¡Ahora no haremos manipulaciones con el número, transferiremos al sistema binario, sino que afectaremos directamente la función en sí!
Usando el método Tapper para decodificar el número k
Obtenemos el número k del usuario,
con los ojos cerrados lo dividimos por 17 y lo traducimos al sistema binario.
def from_k_to_bin(k: int) -> list: k //= 17 binary = bin(k)[2:]
Entendemos que algunos píxeles iniciales pueden ser blancos (igual a 0), respectivamente, para nuestro número binario, los primeros bits serán ceros, y al traducir un número a un sistema decimal, estos ceros iniciales se perderán. Por lo tanto, verificamos el tamaño del número binario resultante, si es menor que 1802, luego agregamos ceros al principio.
def from_k_to_bin(k: int) -> list: k //= 17 binary = bin(k)[2:]
A continuación, declare una lista bidimensional en la que almacenaremos información sobre cada línea de la imagen. Luego escribimos todos esos bits que leemos (no olvide el algoritmo por el cual se crea el número k, de abajo hacia arriba, de izquierda a derecha)
lists = [[] for x in range(17)]
Intentemos insertar el número k, que indiqué al principio del artículo, en nuestro programa y obtener lo siguiente:

Como puede ver, todo funcionó para nosotros, ¡y ahora podemos decodificar cualquier k!
Usando la desigualdad para generar una imagen de k
Primero, escribe la función en python:
def f(x,y): return ((y//17)//(1 << (17*x+(y%17))))%2
Gracias a los operadores // y <<, la implementación de la función se ha simplificado enormemente. ¡Se garantiza que los números x e y serán
enteros !
Nuevamente creamos una lista bidimensional, donde almacenaremos los bits de la imagen y escribiremos información sobre cada línea usando bucles.
lists = [[] for x in range(17)] for y in range(16,-1,-1): for x in range(105,-1,-1): lists[y].append(int(f(x,y+k) > 1/2))
Y luego, como en el ejemplo anterior, dibujamos una imagen usando la biblioteca PIL.
La función completa se ve así:
def from_k_to_bin(k: int) -> list: lists = [[] for x in range(17)] for y in range(16,-1,-1): for x in range(105,-1,-1): lists[y].append(int(f(x,y+k) > 1/2)) return lists
Imagen en k
Bueno, ahora aprenderemos a codificar cualquier imagen en el número k.
Primero obtenemos la imagen en sí
def get_image() -> Image: name = input(" ( ):") try: im = Image.open(name) except Exception: print("!") exit(0) return im
Comprueba su tamaño
_SIZE_WIDTH = 106 _SIZE_HEIGHT = 17 image = get_image() width, height = image.size flag_okay = False if width == _SIZE_WIDTH and height == _SIZE_HEIGHT: flag_okay = True if not flag_okay: print(" ") print(width, height) exit(0) print(" !")
Hacemos la imagen en blanco y negro y comenzamos a leer píxel por píxel:
image = image.convert('1') byteset = "" for x in range(105,-1,-1): for y in range(0,17):
Solo resta convertir al sistema decimal y multiplicar por 17.
k = int(byteset,2)*17 print(" :") print(k)
Bueno, vamos a probar!
Decidí codificar el logotipo de habr. Aquí está la imagen de origen:

Iniciamos el programa y especificamos el nombre de la imagen:

Tenemos la siguiente k:
4858487703217654168507377107565676789145697178497253677539145555247620343537955749299116772611982962556356527603203744742682135448820545638134012705381689785851604674225344958377377969928942310236199337805399065932982909660659786056259547094494380793146587709009524498386724160055692719747815828234655968636671461350354316223620304956111171025410498514602810746287134775641383930152393933036921599511277388743068766568352667661462097979110006690900253037600818522726237351439443865433159187625289316917268254866954663750093103703327097252478959
Vamos a verlo en nuestro propio programa.
Aquí está la imagen que recibimos:

Estaba un poco distorsionado debido a una traducción ligeramente torcida de la imagen en blanco y negro.
Resumen
Código fuente:
GithubFuentes:
artículo de Wiki