Generate a Photographic mosaic from a given set of thumbnails

1.3k Views Asked by At

Photographic mosaic is a technique of re-generating an existing image as a mosaic of thumbnails. The color of the original pixels should roughly resemble the color of the covering tile.

For example, a role-playing gamer re-generated the world map from thumbnail images of users.

enter image description here

The source code for this image is shared on github, but it's pretty tailored for the specific world-map task.

Is there a general solution for re-generating an existing image as a collage/mosaic of a set of given thumbnails?

1

There are 1 best solutions below

2
On

Proof of concept follows, as a simple bash script with ImageMagick to do the image processing work.

#!/bin/bash

# Take all JPEGS in current directory and get their average RGB color and name in "tiles.txt"
for f in *.jpg; do convert $f -depth 8 -resize 1x1! -format "%[fx:int(mean.r*255)] %[fx:int(mean.g*255)] %[fx:int(mean.b*255)] $f\n" info: ; done > tiles.txt

# Create empty black output canvas same size as original map
convert map.png -threshold 100% result.png

# Split map into tiles of 10x10 and get x,y coordinates of each tile and the average RGB colour
convert map.png -depth 8 -crop 10x10 -format "%X %Y %[fx:int(mean.r*255)] %[fx:int(mean.g*255)] %[fx:int(mean.b*255)]\n" info: | 
   while read x y r g b; do
      thumb=$(awk -v R=$r -v G=$g -v B=$b '
         NR==1{nearest=3*255*255*255;tile=$4}
         { 
            tr=$1;tg=$2;tb=$3
            # Calculate distance (squared actually but sqrt is slow)
            d=((R-tr)*(R-tr))+((G-tg)*(G-tg))+((B-tb)*(B-tb))
            if(d<nearest){nearest=d;tile=$4}
         }
         END{print tile}
      ' tiles.txt)
      echo $x $y $r $g $b $thumb
      convert result.png -draw "image copy $x,$y 10,10 \"$thumb\"" result.png
   done

enter image description here

I don't have an endless supply of thumbnails but the concept seems to work. The maths of distance between colours is done in awk and obviously could be done in a more perceptually uniform colorspace and also things could be speeded up considerably. Another thought, to avoid repetition, might be to bin the tiles into similar colours and then take one at random from the nearest bin rather than the absolute nearest one.

The file tiles.txt looks like this:

111 116 109 0.jpg
82 88 81 1.jpg
112 110 95 10.jpg
178 154 150 100.jpg
190 169 163 101.jpg
187 166 163 102.jpg
...
...