Imagine un camino bidimensional continuo que solo puede girar a la izquierda, a la derecha o en línea recta, no puede intersectarse y debe llenar una cuadrícula rectangular como la cuadrícula de píxeles en una imagen. Llamaremos a este tipo de camino una serpiente .
Este ejemplo ampliado muestra un camino de serpiente en una cuadrícula de 10 × 4 que comienza en rojo y aumenta el tono en aproximadamente un 2% en cada paso hasta que se vuelve púrpura. (Las líneas negras son solo para enfatizar la dirección que toma).
Gol
El objetivo en este concurso de popularidad es escribir un algoritmo que intente recrear una imagen dada usando una sola serpiente cuyo color cambia continuamente en pequeñas cantidades.
Su programa debe tomar una imagen en color verdadero de cualquier tamaño, así como un valor de coma flotante entre 0 y 1 inclusive, la tolerancia .
La tolerancia define la cantidad máxima que el color de la serpiente puede cambiar en cada paso de tamaño de píxel. Definiremos la distancia entre dos colores RGB como la distancia euclidiana entre los dos puntos RGB cuando se disponga en un cubo de color RGB . La distancia se normalizará para que la distancia máxima sea 1 y la distancia mínima sea 0.
Seudocódigo de distancia de color: (Asume que todos los valores de entrada son enteros en el rango [0, 255]
; la salida está normalizada).
function ColorDistance(r1, g1, b1, r2, g2, b2)
d = sqrt((r2 - r1)^2 + (g2 - g1)^2 + (b2 - b1)^2)
return d / (255 * sqrt(3))
Si el resultado de llamar a esta función en el color actual de la serpiente y otro color es mayor que la tolerancia dada, entonces la serpiente no puede cambiar a ese otro color.
Si lo prefiere, puede usar una función de distancia de color diferente. Debe ser algo preciso y bien documentado, como los que figuran en http://en.wikipedia.org/wiki/Color_difference . También debe normalizarlo para que esté dentro [0, 1]
, es decir, la distancia máxima posible debe ser 1 y la mínima debe ser 0. Díganos en su respuesta si usa una métrica de distancia diferente.
Imágenes de prueba
Por supuesto, debe publicar sus imágenes de salida (e incluso animaciones de la serpiente que crece si lo desea). Sugiero publicar una variedad de estas imágenes usando diferentes tolerancias bajas (tal vez alrededor de 0.005 a 0.03).
Criterios de victoria
Como se dijo, este es un concurso de popularidad. La respuesta más votada ganará. Deben votarse las respuestas que brinden la representación de "ruta de la serpiente" más precisa y estéticamente agradable de las imágenes de entrada.
Cualquier usuario que se encuentre enviando imágenes maliciosas que no son serpientes reales será descalificado para siempre.
Notas
- Solo se puede usar un camino de serpiente y debe llenar completamente la imagen sin tocar el mismo píxel dos veces.
- La serpiente puede comenzar y terminar en cualquier lugar de la imagen.
- La serpiente puede comenzar como cualquier color.
- La serpiente debe permanecer dentro de los límites de la imagen. Los límites no son cíclicos.
- La serpiente no puede moverse en diagonal o más de un píxel a la vez.
fuente
Respuestas:
Pitón
Genero una ruta dinámica para minimizar los cambios de color a medida que viaja la serpiente. Aquí hay algunas imágenes:
tolerancia = 0.01
Trazados de color cíclicos para las imágenes anteriores (azul a rojo, cada vez más verde a medida que se repite)
La ruta se genera comenzando con alguna ruta inicial, luego agregando bucles de 2x2 hasta que se llene la imagen. La ventaja de este método es que los bucles se pueden agregar en cualquier parte del camino, por lo que no puede pintar en una esquina y tener más libertad para construir el camino que desee. Realizo un seguimiento de los posibles bucles adyacentes a la ruta actual y los almaceno en un montón, ponderado por el cambio de color a lo largo del bucle. Luego salgo del bucle con el menor cambio de color y lo agrego a la ruta, y repito hasta que se llene la imagen.
Realmente sigo los bucles solo ('DetourBlock' en el código), luego reconstruyo la ruta; esto fue un error, ya que hay algunos casos especiales de ancho / alto extraño y pasé varias horas depurando el método de reconstrucción. Oh bien.
La métrica de generación de ruta necesita ajuste y también tengo una idea para una mejor coloración, pero pensé en sacar esto primero ya que funciona bastante bien. Excepto por este, que parece mejor en algunos de los caminos fijos:
Aquí está el código de Python, con disculpas por mis atroces hábitos de codificación:
Y algunas imágenes más con una tolerancia muy baja de 0.001 :
Y también el gran camino de las olas porque está limpio
EDITAR
La generación de ruta parece mejor cuando se minimiza la distancia de color entre los colores promedio de los bloques adyacentes, en lugar de minimizar la suma de las distancias de color entre sus píxeles adyacentes. Además, resulta que puedes promediar los colores de cualquiera de los dos caminos de serpiente que cumplen con la tolerancia y terminar con otro camino de serpiente que cumple con la tolerancia. Así que recorro el camino en ambos sentidos y los promedio, lo que suaviza muchos de los artefactos. Zombie Lena y Scary Hands Mona se ven mucho mejor. Versiones finales:
Tolerancia 0.01 :
Tolerancia 0.001 :
fuente
Java
Mi programa genera una ruta de serpiente para un ancho y alto dados, usando un algoritmo similar al que genera la curva de Hilbert.
(pequeño juego: en la imagen de arriba, la serpiente comienza en la esquina superior izquierda. ¿Puedes encontrar dónde termina? Buena suerte :)
Aquí están los resultados para varios valores de tolerancia:
Tolerancia = 0.01
Tolerancia = 0.05
Tolerancia = 0.1
Tolerancia = 0.01
Con bloques de píxeles 4x4 y el camino visible
Calculando el camino de la serpiente
Una ruta de serpiente se almacena en una matriz de enteros de doble dimensión. La serpiente siempre entra en la cuadrícula por la esquina superior izquierda. Hay 4 operaciones básicas que mi programa puede hacer en una ruta de serpiente dada:
cree una nueva ruta de serpiente para una cuadrícula de ancho 1 o altura 1. La ruta es solo una línea simple que va de izquierda a derecha o de arriba a abajo, según el caso.
aumente la altura de la cuadrícula, agregando en la parte superior un camino de serpiente de izquierda a derecha, luego reflejando la cuadrícula (la serpiente siempre debe ingresar a la cuadrícula por la esquina superior izquierda)
aumente el ancho de la cuadrícula, agregando a la izquierda un camino de serpiente de arriba a abajo, luego volteando la cuadrícula (la serpiente siempre debe ingresar a la cuadrícula por la esquina superior izquierda)
duplicar la dimensión de la cuadrícula utilizando un algoritmo de "estilo Hilbert" (ver descripción a continuación)
Usando una serie de estas operaciones atómicas, el programa puede generar una ruta de serpiente de cualquier tamaño.
El siguiente código calcula (en orden inverso) qué operaciones serán necesarias para obtener un ancho y una altura dados. Una vez calculadas, las acciones se ejecutan una por una hasta que tenemos una ruta de serpiente del tamaño esperado.
Duplicar el tamaño del camino de la serpiente:
El algoritmo que duplica el tamaño funciona de la siguiente manera:
Considere este nodo que está vinculado a DERECHA e INFERIOR. Quiero duplicar su tamaño.
Hay 2 formas de duplicar su tamaño y mantener las mismas salidas (derecha e inferior):
o
Para determinar cuál elegir, necesito manejar para cada dirección de nodo un valor de "desplazamiento", que indica si la puerta de salida se desplaza hacia la izquierda / derecha o hacia arriba / abajo. Sigo el camino como lo haría la serpiente, y actualizo el valor de desplazamiento a lo largo del camino. El valor de desplazamiento determina de forma exclusiva qué bloque expandido necesito usar para el siguiente paso.
fuente
Pitón
Aquí hay un algoritmo muy simple para comenzar las cosas. Comienza en la parte superior izquierda de la imagen y se mueve en espiral en el sentido de las agujas del reloj hacia adentro, haciendo que el color se acerque lo más posible al color del siguiente píxel mientras se mantiene dentro de la tolerancia.
Se necesitan uno o dos minutos para ejecutar las imágenes más grandes, aunque estoy seguro de que la lógica en espiral podría optimizarse enormemente.
Resultados
Son interesantes pero no hermosos. Sorprendentemente, una tolerancia superior a 0.1 produce resultados de aspecto bastante precisos.
La gran ola con una tolerancia de 0.03:
Mona Lisa con una tolerancia de 0.02:
Lena con una tolerancia de 0.03, luego 0.01, luego 0.005, luego 0.003:
Varios en tolerancia 0.1, luego 0.07, luego 0.04, luego 0.01:
fuente
Cobra
Llena la imagen con una serpiente como:
Esto permite un ajuste de color mucho más rápido que solo líneas en direcciones alternas, pero no se vuelve tan bloqueado como lo hace una versión de 3 anchos.
Incluso con tolerancias muy bajas, los bordes de una imagen siguen siendo visibles (aunque con la pérdida de detalles en resoluciones más pequeñas).
0,01
0.1
0,01
0,01
0.1
0,03
0.005
fuente
DO#
Snake comienza en el píxel superior izquierdo con color blanco y alterna de izquierda a derecha y luego de derecha a izquierda en la imagen.
Tolerancia de imagen resultante = 0.1
fuente