else/ImageFilters/imagefilters.py
2016-05-21 12:51:36 -07:00

97 lines
No EOL
3.2 KiB
Python

import PIL.Image
KERNEL_GAUSSIAN_BLUR = [
[1, 2, 1],
[2, 3, 2],
[1, 2, 1],
]
KERNEL_EDGE_DETECTION_H = [
[-2, 0, 2],
[-2, 0, 2],
[-2, 0, 2],
]
def index_to_xy(index, width):
(y, x) = divmod(index, width)
return (x, y)
def xy_to_index(x, y, width):
return (y * width) + x
def apply_filter(old_image, kernel):
kernel_height = len(kernel)
kernel_width = len(kernel[0])
if (kernel_height % 2 != 1) or (kernel_width % 2 != 1):
raise ValueError('Kernel is not of odd size')
if any(len(segment) != kernel_width for segment in kernel):
raise ValueError('Kernel is of inconsistent size')
kernel_center = (kernel_width // 2, kernel_height // 2)
flat_kernel = list(flatten_list(kernel))
lower = min(flat_kernel)
lower = min(0, lower * 255)
upper = max(flat_kernel)
upper = max(255, upper * 255)
print(lower, upper)
(image_width, image_height) = old_image.size
old_pixels = old_image.getdata()
new_pixels = list(old_image.getdata())
for (index, old_pixel) in enumerate(old_pixels):
operation_sum = 0
operation_denominator = 0
(x, y) = index_to_xy(index, image_width)
#print(x, y, index)
for (kernel_y, kernel_row) in enumerate(kernel):
#print(kernel_row)
subject_y = y - (kernel_center[1] - kernel_y)
if subject_y < 0 or subject_y >= image_height:
continue
for (kernel_x, kernel_entry) in enumerate(kernel_row):
subject_x = x - (kernel_center[0] - kernel_x)
if subject_x < 0 or subject_x >= image_width:
continue
subject = old_pixels[xy_to_index(subject_x, subject_y, image_width)]
#print(x, y, subject_x, subject_y, kernel_entry, subject)
operation_sum += kernel_entry * subject
operation_denominator += kernel_entry
operation_denominator = max(1, operation_denominator)
operation_avg = abs(operation_sum / operation_denominator)
#n_operation_avg = int(map_range(operation_avg, lower, upper, 0, 255))
if index % 4096 == 0:
print(x, y, operation_sum, operation_denominator, operation_avg)
#print(y, '/', image_height)
new_pixels[index] = operation_avg
#print(new_pixels)
new_image = PIL.Image.new('L', (old_image.size))
new_image.putdata(new_pixels, 1, 0)
#print(new_pixels)
#print(list(new_image.getdata()))
return new_image
def flatten_list(li):
for element in li:
if hasattr(element, '__iter__'):
yield from flatten_list(element)
else:
yield element
def map_range(x, old_low, old_high, new_low, new_high):
'''
Given a number x in range [old_low, old_high], return corresponding
number in range [new_low, new_high].
'''
if x > old_high or x < old_low:
raise ValueError('%d not in range [%d..%d]' % (x, old_low, old_high))
percentage = (x - old_low) / (old_high - old_low)
y = (percentage * (new_high - new_low)) + new_low
return y
if __name__ == '__main__':
i = PIL.Image.open('ear.jpg')
i = i.convert('L')
i = apply_filter(apply_filter(i, KERNEL_GAUSSIAN_BLUR), KERNEL_EDGE_DETECTION_H)
i.save('ear.png')