Algoritmos para hacer mosaicos de imágenes: ¿hay una forma más rápida que esta?

9

He estado jugando a hacer mosaicos de imágenes. Mi script toma una gran cantidad de imágenes, las reduce a un tamaño de miniatura y luego las usa como mosaicos para aproximar una imagen de destino.

El enfoque es realmente bastante agradable:

Calculo el error cuadrático medio para cada pulgar en cada posición de mosaico.

Al principio, solo usé una ubicación codiciosa: coloque el pulgar con el menor error en el mosaico que mejor se ajuste, y luego el siguiente y así sucesivamente.

El problema con codicioso es que eventualmente te deja colocando los pulgares más diferentes en las fichas menos populares, ya sea que coincidan o no. Muestro ejemplos aquí: http://williamedwardscoder.tumblr.com/post/84505278488/making-image-mosaics

Entonces hago intercambios aleatorios hasta que el script se interrumpe. Los resultados están bastante bien.

Un intercambio aleatorio de dos mosaicos no siempre es una mejora, pero a veces una rotación de tres o más mosaicos da como resultado una mejora global, es decir, A <-> Bpuede no mejorar, pero A -> B -> C -> A1puede ...

Por esta razón, después de elegir dos fichas aleatorias y descubrir que no mejoran, elijo un montón de fichas para evaluar si pueden ser la tercera ficha en esa rotación. No exploro si cualquier conjunto de cuatro mosaicos se puede rotar de manera rentable, y así sucesivamente; eso sería súper costoso muy pronto.

Pero esto lleva tiempo. ¡Mucho tiempo!

¿Existe un enfoque mejor y más rápido?


Bounty Update

Probé varias implementaciones de Python y enlaces del método húngaro .

Por mucho, el más rápido fue el Python puro https://github.com/xtof-durr/makeSimple/blob/master/Munkres/kuhnMunkres.py

Mi presentimiento es que esto se aproxima a la respuesta óptima; cuando se ejecuta en una imagen de prueba, todas las demás bibliotecas estuvieron de acuerdo con el resultado, pero este kuhnMunkres.py, aunque fue mucho más rápido, solo se acercó mucho al puntaje que acordaron las otras implementaciones.

La velocidad depende mucho de los datos; Mona Lisa se apresuró a través de kuhnMunkres.py en 13 minutos, pero el Perico Escarlata Escarlata tardó 16 minutos.

Los resultados fueron muy similares a los intercambios y rotaciones aleatorias para el periquito:

ingrese la descripción de la imagen aquíingrese la descripción de la imagen aquí

(kuhnMunkres.py a la izquierda, intercambios aleatorios a la derecha; imagen original para comparar )

Sin embargo, para la imagen de Mona Lisa con la que probé, los resultados mejoraron notablemente y en realidad hizo que su 'sonrisa' definida brillara:

ingrese la descripción de la imagen aquíingrese la descripción de la imagen aquí

(kuhnMunkres.py a la izquierda, intercambios aleatorios a la derecha)

Será
fuente
1
Relacionado ... ish. En Codegolf, la transformación del paladar tuvo problemas similares.
1
Y otro conjunto relacionado de imágenes es allRGB donde cada imagen (aunque eso no le da demasiada pista de cómo hacerlo ... solo que hay otra área donde se ha abordado este problema).
1
Me encontré con este problema con un fabricante de mosaicos hace unos años. Mi línea de razonamiento entonces y ahora es que el problema no es tanto con su algoritmo (la parte MSE) sino con el tamaño limitado de su paleta de imágenes de entrada. Al no tener mil millones de imágenes con las que trabajar, lo fingí permitiendo que una imagen se reutilizara después de cierto tiempo. Sin embargo, si desea seguir con su enfoque, puede ser bueno hacer una primera pasada para ajustes "buenos" y luego tratar el resto de las imágenes como aleatorias (o aleatorias), con un conjunto de entrada limitado que solo tiene tantas opciones.
J Trana
@MichaelT gracias por ese excelente enlace :) El codegolf particularmente es fascinante. Encuentro la votaron-mejores soluciones están utilizando permutas de azar (rotaciones no aleatorios) y presumiblemente se ejecutan durante bastante tiempo ...
Will
1
Llegando a esto después de haber seleccionado una respuesta y otorgado una recompensa. Un enfoque diferente sería tratar esto como un problema de recocido simulado . Puede usar SA como una de las etapas de su tubería de soluciones.
andy256

Respuestas:

3

Sí, hay dos enfoques mejores y más rápidos.

  • Problema más simple: para cada mosaico, elija el mejor pulgar (con posible duplicación). Ok, eso es trampa, pero solo puede conducir a un mejor resultado visual.
  • Su toma es algorítmicamente más interesante y se reduce a "problema de asignación lineal", suponiendo que tome MSE como costos de coincidencia cuya suma debe ser mínima. Dicho problema puede resolverse en tiempo polinómico, por ejemplo, mediante el "Método húngaro"

Luego, puede ajustar sus costos reemplazando MSE por una distancia visualmente más precisa, sin cambiar el algoritmo subyacente.

YvesgereY
fuente
¡Gracias! ¡LAP y el método húngaro fueron los leads que necesitaba! Actualización con resultados en cuestión.
Will
3

Estoy razonablemente seguro de que es un problema NP-difícil. Para encontrar una solución 'perfecta', debe probar todas las posibilidades exhaustivamente, y eso es exponencial.

Un enfoque sería utilizar el ajuste codicioso y luego tratar de mejorarlo. Eso podría ser tomando una imagen mal colocada (una de las últimas) y encontrando otro lugar para colocarla, luego tomando esa imagen y moviéndola y así sucesivamente. Ha terminado cuando (a) se le acaba el tiempo (b) el ajuste es "suficientemente bueno".

Si introduce un elemento probabilístico, podría dar lugar a un enfoque de recocido simulado o un algoritmo genético. Quizás todo lo que está tratando de lograr es difundir los errores de manera uniforme. Sospecho que esto se está acercando a lo que ya está haciendo, por lo que la respuesta es: con el algoritmo correcto, puede obtener un mejor resultado más rápido, pero no hay un atajo mágico para Nirvana.


Sí, esto es similar a lo que ya estás haciendo. El punto es olvidar una respuesta mágica y pensar en términos de 2 algoritmos: primero rellenar, luego optimizar.

El relleno podría ser: aleatorio, mejor disponible, primero mejor, lo suficientemente bueno, algún tipo de punto caliente.

La optimización podría ser aleatoria, corregir lo peor o (como sugerí) un recocido simulado o un algoritmo genético.

Necesita una métrica de 'bondad' y una cantidad de tiempo que esté preparado para gastar en ella y simplemente experimentar. O encuentre a alguien que realmente lo haya hecho.

david.pfx
fuente
¿Describe exactamente el enfoque descrito en la pregunta ...?
Will
1

Si los últimos mosaicos son su problema, debe intentar colocarlos desde el principio, de alguna manera;)

Un enfoque sería mirar el mosaico que está más alejado del x% superior de sus coincidencias (intuitivamente iría con 33%) y colocarlo en su mejor coincidencia. Esa es la mejor combinación que puede obtener de todos modos.

Además, puede optar por no utilizar la mejor coincidencia para la peor ficha, sino aquella en la que introduce el menor error en comparación con la mejor coincidencia para esa ranura, de modo que no descarte por completo sus mejores coincidencias por el simple hecho de " control de daños".

Otra cosa a tener en cuenta es que al final estás produciendo una imagen para que sea procesada por un ojo. Entonces, lo que realmente desea es utilizar un poco de detección de bordes para determinar qué posiciones en su imagen son más importantes. Del mismo modo, lo que sucede en la periferia de la imagen tiene poco valor para la calidad del efecto. Superponga estos dos pesos e inclúyalos en su cálculo de distancia. Cualquier inquietud que obtenga debe gravitar hacia el borde y lejos de los bordes, lo que perturbará mucho menos.

También con la detección de bordes en su lugar, es posible que desee colocar el primer y% con avidez (tal vez hasta que caiga por debajo de un cierto umbral de "nerviosismo" en los mosaicos a la izquierda), de modo que los "puntos calientes" se aborden muy bien, y luego cambie a "control de daños" para el resto.

back2dos
fuente