Skip to content

Instantly share code, notes, and snippets.

@linus
Created March 8, 2011 02:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save linus/859747 to your computer and use it in GitHub Desktop.
Save linus/859747 to your computer and use it in GitHub Desktop.
Så förbättrade vi Rättviseförmedlingens pressbild
# Main function. Takes the original image and a list of
# profile pictures, and returns the finished, improved, mosaic
def create_better_mosaic(original_image, profile_pictures):
# Calculate the width and height of the scaled image, where
# each profile picture maps to a pixel in the original image
width, height = image_ratio(original_image, len(profile_pictures))
# Get the pixel values of the scaled image, "unfolded" in
# one dimension
pixels = get_pixels_one_dimensional(original_image, width, height)
# Get a list of tuples with (image, color) for each profile picture
tiles = profile_colors(profile_pictures)
# Put the profile pictures in their places!
tiles = iterate(tiles, pixels, 1e6)
mosaic = Image.new("RGB", (width * TILE_SIZE, height * TILE_SIZE))
# Paste the profile pictures one after the other
for i, tile in enumerate(tiles):
x, y = divmod(i, width)
mosaic.paste(tile[0].resize((TILE_SIZE, TILE_SIZE), Image.ANTIALIAS), (x * TILE_SIZE, y * TILE_SIZE)
return mosaic
# Massage our pixel data so we get it in a
# one dimensional array
def get_pixels_one_dimensional(image, width, height):
pixels = get_pixels(image, width, height)
return [pixels[x, y] for x in range(width) for y in range(height)]
# Sum the distances between all tiles (i.e. profile pictures)
# and the pixels in the corresponding place
def initial_solution(tiles, pixels):
return sum([distance(tiles[i][1], color) for i, color in enumerate(pixels)])
import random
# Swap random tiles (profile pictures) and calculate
# the difference for each solution. Keep good solutions.
# Iterate num_iterations times
def iterate(tiles, pixels, num_iterations):
for i in range(num_iterations):
i1 = random.randint(0, len(pixels) - 1)
i2 = random.randint(0, len(pixels) - 1)
current_solution = distance(tiles[i1][1], pixels[i1]) + distance(tiles[i2][1], pixels[i2])
new_solution = distance(tiles[i2][1], pixels[i1]) + distance(tiles[i1][1], pixels[i2])
if new_solution < current_solution:
tiles[i2], tiles[i1] = tiles[i1], tiles[i2]
return tiles
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment