Last active
August 29, 2015 14:15
-
-
Save mlaugharn/ab2c5eaf8759077da055 to your computer and use it in GitHub Desktop.
port of filters.py project, it was too hackish to warrant a whole repo
This file contains hidden or 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
# much (some) of this code isn't mine | |
import PIL.Image, numpy, scipy.misc, scipy.ndimage, scipy.spatial | |
import time, sys, random, math, functools, collections | |
# image = PIL.Image.open("4.2.06.tiff") # sailboat on lake | |
# image = PIL.Image.open("lena.tiff") # lena | |
pixel_definition = ["r", "g", "b"] # definition of pixel | |
# neighborhood_kernel = numpy.array([[1, 1, 1], | |
# [1, 1, 1], | |
# [1, 1, 1]]) | |
# | |
neighborhood_kernel = numpy.ones((5,5)) | |
self_kernel = numpy.array([[1]]) | |
# some example transformations | |
def collatz(n): | |
if n == 0: return 0 | |
i = 0 | |
while n != 1: | |
i += 1 | |
if n % 2 == 0: | |
n = n // 2 | |
else: | |
n = 3 * n + 1 | |
return i | |
collatz_list = [min(collatz(n), 255) for n in range(256)] | |
def collatz_map(n, minimum = 0, maximum = 255): | |
return collatz_list[int(n[0])] | |
def median(scalar_list): | |
return sorted(scalar_list)[len(scalar_list) // 2] | |
def mean(scalar_list): | |
return sum(scalar_list) // len(scalar_list) | |
def primes(n): | |
primfac = [] | |
d = 2 | |
while d * d <= n: | |
while (n % d) == 0: | |
primfac.append(d) # supposing you want multiple factors repeated | |
n /= d | |
d += 1 | |
if n > 1: | |
primfac.append(n) | |
return list(map(int, primfac)) | |
def counter_to_coordinate(d): | |
# d might look like e.g. n = 12, d = {2:2 , 3: 1} | |
dimension = max(some_primes) | |
coordinate = [0] * (dimension + 1) | |
for index, (prime, times) in enumerate(zip(d, d.values())): | |
coordinate[prime] = times | |
return coordinate | |
prime_factors = [primes(n) for n in range(256)] # e.g. prime_factors[12] = [2, 2, 3] | |
some_primes = list(set.union(*list(map(set, prime_factors)))) | |
coordinate = lambda n: counter_to_coordinate(dict(collections.Counter(prime_factors[n]))) | |
cache = {i: numpy.array(coordinate(i)) for i in range(len(prime_factors))} | |
nums = numpy.array(list(cache.values())) | |
grid = scipy.spatial.distance.cdist(nums, nums, 'cityblock') | |
def prime_factor_dist_convolve(scalar_list): | |
middle = scalar_list[len(scalar_list)//2] | |
prime_space_distances = numpy.array([grid[middle][x] for x in scalar_list]) | |
norm = numpy.linalg.norm(prime_space_distances) | |
if norm == 0: return middle | |
normalized_distances = prime_space_distances / norm | |
products = numpy.array([normalized_distances[i] * scalar_list[i] for i in range(len(scalar_list))]) | |
return sum(products) | |
sine_cache = [255 * math.sin((n) * (math.pi / 2) / 255) for n in range(256)] | |
def sine_map(n): | |
return sine_cache[int(n[0])] | |
quadratic_cache = [255 * (n / 255) ** 2 for n in range(256)] | |
def quadratic_map(n): | |
return quadratic_cache[int(n[0])] | |
log_cache = [0] + [math.log(n) for n in range(1, 256)] | |
def log_map(n): | |
return log_cache[int(n[0])] | |
exp_cache = [(255/148) * math.e ** n for n in range(256)] | |
def exp_map(n): | |
return exp_cache[int(n[0])] | |
def threshold(n): | |
return 0 if 128 < n else 255 | |
pixel_transformations = functools.partial(scipy.ndimage.generic_filter, footprint = self_kernel) | |
window_transformations = functools.partial(scipy.ndimage.generic_filter, footprint = neighborhood_kernel) | |
def transform_queue(image, queue, bijection): | |
pixel_system = numpy.array(image) # each pixel_system[y, x] = 3vector <R, G, B> | |
RGBimages = [pixel_system[:,:,index] for index, color in enumerate(pixel_definition)] # split into RGB images | |
# guarantee every transformation has a partial type class | |
transformed_images = [] # will contain transformed RGB images | |
for image in RGBimages: | |
for transformation in queue: | |
transformation_partial = list(filter(lambda key: transformation in bijection[key], bijection.keys()))[0] # each transformation maps to one partial; filter away irrelevant partials | |
image = transformation_partial(image, transformation) | |
transformed_images.append(image) | |
return numpy.uint8(numpy.dstack(transformed_images)) # make one RGB image from the R, G, B planes | |
def process(image_name, transformation_class_map, queue): | |
image = PIL.Image.open(image_name) | |
result = transform_queue(image, queue, transformation_class_map) | |
image = PIL.Image.fromarray(result) | |
image.show() | |
image.save(''.join(list(map(lambda f: f.__name__ + '_', queue))) + str(time.time()) + '_' + image_name) | |
if __name__ == '__main__': | |
transformation_class_map = {pixel_transformations: set([collatz_map, | |
sine_map, | |
quadratic_map, | |
log_map, | |
exp_map, | |
threshold]), | |
window_transformations: set([median, | |
mean, | |
random.choice, | |
prime_factor_dist_convolve])} | |
queue = [sine_map] * 3 + [prime_factor_dist_convolve] | |
process(sys.argv[1], transformation_class_map, queue) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment