#!/usr/bin/python """A stupid program to hill-climbingly approximate an image with randomly chosen rectangles. Doesn't work well enough to be interesting. """ import pygame import random import sys import time import Numeric rand = random.randrange def draw_on(objects, canvas): canvas.fill(0) for color, xx, yy, ww, hh in objects: pygame.draw.rect(canvas, color, (xx, yy, ww, hh)) def compare(canvas_1, canvas_2): array_1 = pygame.surfarray.pixels3d(canvas_1) array_2 = pygame.surfarray.pixels3d(canvas_2) diffs = Numeric.absolute(array_1.astype(Numeric.Int16) - array_2.astype(Numeric.Int16)) return Numeric.sum(Numeric.sum(Numeric.sum(diffs.astype(Numeric.Int32)))) def randrect(width, height): return (rand(2**24), rand(width), rand(height), 10, 10) def mutate_dimension(dimension, maximum): if rand(2): return rand(maximum) else: return dimension + rand(7) - 3 def mutate(display_list, width, height): new = display_list[:] if not new or rand(64) == 0: new[0:0] = [randrect(width, height)] return new if rand(32) == 0: new.pop(rand(len(new))) return new if len(new)> 1 and rand(20) == 0: ii = rand(len(new)) jj = rand(len(new)-1) if jj>= ii: jj += 1 new[ii], new[jj] = new[jj], new[ii] return new index = rand(len(new)) color, xx, yy, ww, hh = new[index] component = rand(5) if component == 0: if rand(2): color = rand(2**24) else: color += 2**(8*rand(3)) * (2*rand(2) - 1) elif component == 1: xx = mutate_dimension(xx, width) elif component == 2: yy = mutate_dimension(yy, height) elif component == 3: ww = mutate_dimension(ww, width) else: hh = mutate_dimension(hh, height) new[index] = color, xx, yy, ww, hh return new def shadow_text(canvas, font, text, (xx, yy)): canvas.blit(font.render(text, 1, (0, 0, 0, 255)), (xx+2, yy+2)) canvas.blit(font.render(text, 1, (255, 255, 255, 255)), (xx, yy)) def main(argv): if len(argv) != 2: sys.stderr.write("Usage: %s foo.jpg\n" % argv[0]) sys.exit(1) pygame.init() img = pygame.image.load(argv[1]) screen = pygame.display.set_mode((768, 288)) ww, hh = screen.get_size() font = pygame.font.Font(None, 24) # default font, 24 pixels img_size = ww/2, hh img_scaled = pygame.transform.smoothscale(img, img_size) screen.blit(img_scaled, (0, 0)) other_canvas = pygame.Surface(img_size) objects = [] last_diff = ww*hh*3*2**8 mutations = 0 start = time.time() while True: ev = pygame.event.poll() if ev.type in (pygame.QUIT, pygame.MOUSEBUTTONDOWN): break elif ev.type != pygame.NOEVENT: continue other_objects = mutate(objects, ww/2, hh) mutations += 1 draw_on(other_objects, other_canvas) diff = compare(other_canvas, img_scaled) shadow_text(other_canvas, font, 'diff %d, gen %d, %d rect%s' % (last_diff, mutations, len(objects), '' if len(objects) == 1 else 's'), (5, 5)) screen.blit(other_canvas, (ww/2, 0)) if diff <= last_diff: objects = other_objects if diff < last_diff and mutations % 32 == 0: print objects last_diff = diff pygame.display.flip() end = time.time() print objects print "%.1f seconds, %2g per mutation" % (end-start, (end-start)/mutations) if __name__ == '__main__': main(sys.argv)

AltStyle によって変換されたページ (->オリジナル) /