33
9
I've compiled a mosaic of 2025 headshots from the avatars of the top Stack Overflow users.
(Click the image to view it full-size.)
Your task is to write an algorithm that will create an accurate photomosaic of another image using the 48×48 pixel avatars from this 45×45 grid of them.
Test Images
Here are the test images. The first is, of course, a light bulb!
(They are not full-sized here. Click an image to view it at full-size. Half-sized versions are available for The Kiss, A Sunday Afternoon..., Steve Jobs, and the spheres.)
Thanks to Wikipedia for all but the raytraced spheres.
At full-size these images all have dimensions divisible by 48. The larger ones had to be JPEGs so they could be compressed enough to upload.
Scoring
This is a popularity contest. The submission with mosaics that most accurately depict the original images should be voted up. I will accept the highest voted answer in a week or two.
Rules
Your photomosaics must be entirely composed of unaltered 48×48 pixel avatars taken from the mosaic above, arranged in a grid.
You may reuse an avatar in a mosaic. (Indeed for the larger test images you'll have to.)
Show your output, but keep in mind that the test images are very large, and StackExchange only allows posting of images up to 2MB. So compress your images or host them somewhere else and put smaller versions here.
To be confirmed the winner you must provide PNG versions of your light bulb or spheres mosaics. This is so I can validate them (see below) to ensure you are not adding extra colors to the avatars to make the mosaics look better.
Validator
This Python script can be used to check whether a completed mosaic really uses unaltered avatars. Just set toValidate
and allTiles
. It is unlikely to work for JPEGs or other lossy formats since it compares things exactly, pixel-for-pixel.
from PIL import Image, ImageChops
toValidate = 'test.png' #test.png is the mosaic to validate
allTiles = 'avatars.png' #avatars.png is the grid of 2025 48x48 avatars
def equal(img1, img2):
return ImageChops.difference(img1, img2).getbbox() is None
def getTiles(mosaic, (w, h)):
tiles = {}
for i in range(mosaic.size[0] / w):
for j in range(mosaic.size[1] / h):
x, y = i * w, j * h
tiles[(i, j)] = mosaic.crop((x, y, x + w, y + h))
return tiles
def validateMosaic(mosaic, allTiles, tileSize):
w, h = tileSize
if mosaic.size[0] % w != 0 or mosaic.size[1] % h != 0:
print 'Tiles do not fit mosaic.'
elif allTiles.size[0] % w != 0 or allTiles.size[1] % h != 0:
print 'Tiles do not fit allTiles.'
else:
pool = getTiles(allTiles, tileSize)
tiles = getTiles(mosaic, tileSize)
matches = lambda tile: equal(tiles[pos], tile)
success = True
for pos in tiles:
if not any(map(matches, pool.values())):
print 'Tile in row %s, column %s was not found in allTiles.' % (pos[1] + 1, pos[0] + 1)
success = False
if success:
print 'Mosaic is valid.'
return
print 'MOSAIC IS INVALID!'
validateMosaic(Image.open(toValidate).convert('RGB'), Image.open(allTiles).convert('RGB'), (48, 48))
Good luck everyone! I cant wait to see the results.
Note: I know photomosaic algorithms are easy to find online, but they aren't yet on this site. I'm really hoping we see something more interesting than the usual "average each tile and each grid space and match them up" algorithm.
1Isn't this essentially a duplicate of the previous one? Compute the color of each one, downscale the target to 2025px and apply the existing algorithm? – John Dvorak – 2014-07-13T15:49:16.447
1
possible duplicate of American Gothic in the palette of Mona Lisa: Rearrange the pixels
– John Dvorak – 2014-07-13T15:49:57.2772@JanDvorak It's similar but I think not enough to be a duplicate. The algorithm you mentioned is one way to get a result. There are much more sophisticated solutions though. – Howard – 2014-07-13T15:59:26.750
K then... reverting (still too similar for me to upvote). Let's see what the answer bring... – John Dvorak – 2014-07-13T16:00:42.867
1My cat is missing from the avatars :-( – Joey – 2014-07-13T17:09:07.130
@JanDvorak The fact that the current answer is repeating avatars is enough to make me think this question is different. The pixel rearranging challenge could not reuse pixels, if I read it correctly. – trlkly – 2014-07-13T17:11:09.817
@trlkly didn't notice you could reuse avatars; is it specified explicitly somewhere I didn't notice, or just allowed because unspecified? – John Dvorak – 2014-07-13T17:14:03.847
But, once you specify a metric, all you need to do is to implement it and then grep the state space. Not a very interesting challenge, I'd say, unless someone comes up with a global metric. – John Dvorak – 2014-07-13T17:24:31.460
@JanDvorak Not really a global metric but my new version reduces reuse of the same tile within a pre-defined radius. – Howard – 2014-07-13T18:00:32.017
2You may wish to change "to make a light bulb" to "to replace a light bulb". – DavidC – 2014-07-13T18:49:42.660
1
@JanDvorak The questions are similar but as trlkly says, this allows multiple avatars. Also you can take the "shape" of the tiles into account since you're arranging pictures not single pixels. Besides, if creating a program that applies a metric to an image is the defining point of these problems then http://codegolf.stackexchange.com/questions/33172/american-gothic-in-the-palette-of-mona-lisa-rearrange-the-pixels was already a duplicate of http://codegolf.stackexchange.com/questions/21041/cubify-this-a-lesson-in-grayscale-er-color-er-whatever.
– Calvin's Hobbies – 2014-07-13T19:13:31.567Did you choose only headshot avatars in that image? – nneonneo – 2014-07-14T18:46:45.927
@nneonneo Yep. I wanted recognizable shots of real people. – Calvin's Hobbies – 2014-07-14T20:14:25.003
1The answers will eventually show how different this question is from the suggested duplicates. Not only can the shape of the avatars can be used to give a better fit than just treating each avatar as an average colour (as Calvin's Hobbies points out), but also the avatar with the closest fit based on average colour may not give the best colour fit for the finished image. A more accurate approach would treat it as a collection of "subpixels" rather than a single averaged superpixel. This question has the potential to gather some interesting solutions with a variety of different approaches. – trichoplax – 2014-07-15T23:25:49.787
It is worth noting that Photomosaic® is a registered trademark of Runaway Technology. http://www.photomosaic.com/
– Todd Lehman – 2014-08-18T03:20:47.590