Created
March 6, 2014 10:42
-
-
Save christianp/9387171 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from math import sqrt | |
from rtree import index | |
from itertools import product | |
from PIL import Image | |
from random import shuffle | |
import numpy | |
# granularity of colour comonents | |
component_max = 64 | |
# values each colour component can take | |
component_space = range(component_max) | |
# Ratio between component_max and 256 | |
colour_scale = component_max/255.0 | |
# unique id number for an (r,g,b) tuple | |
def id(colour): | |
r,g,b = colour | |
return r*component_max*component_max + g*component_max + b | |
# convert id back to (r,g,b) tuple | |
def unid(n): | |
b = n % component_max | |
n = (n-b)/component_max | |
g = n % component_max | |
n = (n-g)/component_max | |
r = n | |
return (r,g,b) | |
# make a 3d r-tree | |
property_3d = index.Property() | |
property_3d.dimension = 3 | |
idx = index.Index(properties=property_3d) | |
# fill up the r-tree with one of every colour | |
print("Filling r-tree...") | |
for colour in product(component_space,component_space,component_space): | |
idx.insert(id(colour),colour) | |
# calculate width of an image which contains every colour | |
img_width = int(sqrt(component_max**3)) | |
# load the input image | |
print("Opening image...") | |
img = Image.open(open(r'd:\tmp\4096doge.png','rb')).resize((img_width,img_width)) | |
#create the output image | |
new_img = Image.new('RGB',(img_width,img_width)) | |
arr = numpy.array(new_img) | |
# shuffle up the pixels in the output image | |
print("Shuffling pixels...") | |
pixels = list(product(range(img_width),range(img_width))) | |
shuffle(pixels) | |
print("Replacing pixels...") | |
progress = 0 | |
l = len(pixels) | |
acc = 0 | |
for pixel in pixels: | |
acc += 1.0 | |
oprogress, progress = progress, int(100*acc/l) | |
if progress>oprogress: | |
print(progress) | |
# get the colour of this pixel in the source image | |
colour = [c*colour_scale for c in img.getpixel(pixel)] | |
# find the id of the nearest colour still in the r-tree | |
nearest = idx.nearest(colour).next() | |
# convert back from the id to (r,g,b) | |
r,g,b = unid(nearest) | |
# remove it from the r-tree | |
idx.delete(nearest,(r,g,b)) | |
new_pixel = arr[pixel] | |
new_pixel[0] = r/colour_scale | |
new_pixel[1] = g/colour_scale | |
new_pixel[2] = b/colour_scale | |
print("Saving image...") | |
new_img = Image.fromarray(arr) | |
new_img.save("out.png") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment