Te dan una imagen en color verdadero. Su tarea es generar una versión de esta imagen, que parece pintada con pintura por números (actividad de los niños, no nonogramas). Junto con la imagen, se le dan dos parámetros: P , el tamaño máximo de la paleta de colores (es decir, el número máximo de colores distintos para usar) y N , el número máximo de celdas para usar. Su algoritmo no tiene que usar todos los colores P y N celdas, pero no debe usar más que eso. La imagen de salida debe tener las mismas dimensiones que la entrada.
Una celda se define como un área contigua de píxeles que tienen el mismo color. Los píxeles que se tocan solo en una esquina no se consideran contiguos. Las células pueden tener agujeros.
En resumen, debe aproximar la imagen de entrada con solo N áreas sombreadas planas / de color sólido y P diferentes colores.
Solo para visualizar los parámetros, aquí hay un ejemplo muy simple (para ninguna imagen de entrada en particular; mostrando mis habilidades locas de pintura). La siguiente imagen tiene P = 6 y N = 11 :
Aquí hay algunas imágenes para probar su algoritmo (principalmente nuestros sospechosos habituales). Haga clic en las imágenes para versiones más grandes.
Incluya un puñado de resultados para diferentes parámetros. Si desea mostrar una gran cantidad de resultados, puede crear una galería en imgur.com , para mantener razonable el tamaño de las respuestas. Alternativamente, coloque miniaturas en su publicación y conviértalas en enlaces a imágenes más grandes, como hice anteriormente. Además, siéntase libre de usar otras imágenes de prueba, si encuentra algo bueno.
Supongo que los parámetros alrededor de N ≥ 500 , P ~ 30 serían similares a las plantillas reales de pintar por número.
Este es un concurso de popularidad, por lo que gana la respuesta con más votos netos. Se alienta a los votantes a juzgar las respuestas por
- qué tan bien se aproximan las imágenes originales.
- qué tan bien funciona el algoritmo en diferentes tipos de imágenes (las pinturas son generalmente generalmente más fáciles que las fotografías).
- qué tan bien funciona el algoritmo con parámetros muy restrictivos.
- qué tan orgánicas / suaves se ven las formas de las celdas.
Usaré el siguiente script de Mathematica para validar los resultados:
image = <pastedimagehere> // ImageData;
palette = Union[Join @@ image];
Print["P = ", Length@palette];
grid = GridGraph[Reverse@Most@Dimensions@image];
image = Flatten[image /. Thread[palette -> Range@Length@palette]];
Print["N = ",
Length@ConnectedComponents[
Graph[Cases[EdgeList[grid],
m_ <-> n_ /; image[[m]] == image[[n]]]]]]
Sp3000 tuvo la amabilidad de escribir un verificador en Python 2 usando PIL, que se encuentra en este pastebin .
fuente
Respuestas:
Python 2 con PIL ( Galería )
¡Tiempo de actualizacion! Esta actualización presenta un algoritmo de suavizado simple para que las imágenes se vean menos borrosas. Sin embargo, si actualizo de nuevo, tendré que renovar una buena parte de mi código, porque se está volviendo desordenado y tengo dos problemas de rendimiento.
También hice colores de peso k-means basados en tamaños de celda, que pierde algunos detalles para parámetros más restrictivos (por ejemplo, el centro de la nebulosa y la horquilla de American Gothic) pero hace que la elección general del color sea más nítida y agradable. Curiosamente, pierde todo el fondo de las esferas con trazado de rayos para P = 5.
Resumen de algoritmo:
El tiempo de procesamiento para cada imagen depende en gran medida de su tamaño y complejidad, con tiempos que van desde 20 segundos a 7 minutos para las imágenes de prueba.
Debido a que el algoritmo usa la aleatorización (p. Ej., Fusión, k-means), puede obtener resultados diferentes en diferentes ejecuciones. Aquí hay una comparación de dos carreras para la imagen del oso, con N = 50 y P = 10:
Nota: Todas las imágenes a continuación son enlaces. La mayoría de estas imágenes son directas desde la primera ejecución, pero si no me gustó el resultado, me permití hasta tres intentos para ser justo.
N = 50, P = 10
N = 500, P = 30
Pero soy bastante vago cuando se trata de pintar por colores, así que solo por diversión ...
N = 20, P = 5
Además, es divertido ver qué sucede cuando intentas exprimir 1 millón de colores en N = 500, P = 30:
Aquí hay un tutorial paso a paso del algoritmo para la imagen subacuática con N = 500 y P = 30, en forma de GIF animado:
También hice una galería para las versiones anteriores del algoritmo aquí . Aquí hay algunos de mis favoritos de la última versión (de cuando la nebulosa tenía más estrellas y el oso parecía más peludo):
fuente
im = im.convert("RGB")
es necesario para algunas fotos. Lo pondré después de reestructurar un poco el código.Python 2 con PIL
También una solución de Python y probablemente mucho trabajo en progreso:
El algoritmo sigue un enfoque diferente al de SP3000, comenzando con los colores primero:
Encuentre una paleta de colores de colores P por agrupamiento k-means y pinte la imagen en esta paleta reducida.
Aplique un ligero filtro mediano para eliminar el ruido.
Haga una lista de todas las células monocromáticas y ordénelas por tamaño.
Combina las celdas más pequeñas con su vecino más grande hasta que solo queden N celdas.
Hay bastante margen de mejora, tanto en términos de velocidad como de calidad de los resultados. Especialmente el paso de fusión celular puede tomar muchos minutos y da resultados lejos de ser óptimos.
P = 5, N = 45
P = 10, N = 50
P = 4, N = 250
P = 11, N = 500
fuente
Mathematica
Por el momento, esto toma la cantidad de colores y el radio gaussiano que se utilizarán en el filtro gaussiano. Cuanto mayor sea el radio, mayor será el desenfoque y la fusión de colores.
Debido a que no permite la entrada del número de celdas, no cumple con uno de los requisitos básicos del desafío.
La salida incluye el número de celdas para cada color y también el número total de celdas.
Actualizar
quantImage2
permite especificar el número deseado de celdas como entrada. Determina el mejor radio gaussiano recorriendo escenarios con radios mayores hasta encontrar una coincidencia cercana.quantImage2
salidas (imagen, celdas solicitadas, celdas usadas, error, radio gaussiano usado).Sin embargo, es muy lento. Para ahorrar tiempo, puede comenzar con un radio inicial, cuyo valor predeterminado es 0.
Ejemplo para el que especificamos el número de celdas deseadas en la salida.
Ejemplo solicitando 90 celdas con 25 colores. La solución devuelve 88 celdas, error del 2%. La función eligió el radio gaussiano de 55. (Mucha distorsión).
Ejemplos para los cuales la entrada incluye el radio gaussiano, pero no el número de celdas.
25 colores, radio gaussiano de 5 píxeles
Tres colores, radio de 17 píxeles.
Veinte colores, radio de 17 píxeles.
Aumentamos la cantidad de colores pero no el foco. Tenga en cuenta el aumento en el número de celdas.
Seis colores, radio de 4 píxeles.
Noche estrellada
Con solo 6 colores y 60 celdas. Hay una falta de coincidencia de color en los colores que las
showColors
reclamaciones utiliza. (El amarillo no aparece entre los 5 colores, pero se usa en el dibujo). Veré si puedo resolver esto.fuente
showColors
, recorriendo un rango de números de colores y radios y eligiendo la combinación que más se acerque al número deseado de celdas. No estoy seguro si tengo el gas para hacer eso en este momento. Quizás mas tarde.Python 2 con PIL
Esto todavía es algo un trabajo en progreso. Además, el siguiente código es un horrible desastre de espagueti y no debe usarse como inspiración. :)
Cómo funciona
El programa divide el lienzo en
P
regiones, cada una de las cuales consta de cierto número de celdas sin agujeros. Inicialmente, el lienzo se divide en cuadrados aproximados, que se asignan aleatoriamente a las regiones. Luego, estas regiones se "deforman" en un proceso iterativo, donde un píxel determinado puede cambiar su región siLa última condición puede hacerse cumplir localmente, por lo que el proceso es un poco como un autómata celular. De esta forma, no tenemos que encontrar ninguna ruta o tal, lo que acelera el proceso en gran medida. Sin embargo, dado que las células no se pueden dividir, algunas de ellas terminan como largos "filamentos" que bordean otras células e inhiben su crecimiento. Para solucionar esto, hay un proceso llamado "corte de filamento", que ocasionalmente rompe una celda con forma de filamento en dos, si hay menos de
N
células en ese momento. Las células también pueden desaparecer si su tamaño es 1, y esto deja espacio para los cortes de filamentos.El proceso finaliza cuando ningún píxel tiene el incentivo para cambiar regiones, y después de eso, cada región simplemente se colorea por su color promedio. Por lo general, quedarán algunos filamentos en la salida, como se puede ver en los ejemplos a continuación, especialmente en la nebulosa.
P = 30, N = 500
Más fotos después.
Algunas propiedades interesantes de mi programa son que es probabilístico, por lo que los resultados pueden variar entre diferentes ejecuciones, a menos que utilice la misma semilla pseudoaleatoria, por supuesto. Sin embargo, la aleatoriedad no es esencial, solo quería evitar cualquier artefacto accidental que pueda resultar de la forma particular en que Python atraviesa un conjunto de coordenadas o algo similar. El programa tiende a usar todos los
P
colores y casi todas lasN
celdas, y las celdas nunca contienen agujeros por diseño. Además, el proceso de deformación es bastante lento. Las bolas de colores tardaron casi 15 minutos en producirse en mi máquina. Por el lado positivo, enciendes elGRAPHICAL_LOGGING
opción, obtendrá una serie genial de imágenes del proceso de deformación. Convertí los de Mona Lisa en una animación GIF (se redujo un 50% para reducir el tamaño del archivo). Si miras detenidamente su cara y cabello, puedes ver el proceso de corte de filamentos en acción.fuente