-
Notifications
You must be signed in to change notification settings - Fork 22
/
filter.py
120 lines (90 loc) · 3.02 KB
/
filter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
"""
The extraction of the curves from the acv files are from here:
https://github.com/vbalnt/filterizer
"""
from struct import unpack
from scipy import interpolate
from PIL import Image
import numpy
import scipy
import sys
class Filter:
def __init__(self, acv_file_path, name):
self.name = name
with open(acv_file_path, 'rb') as acv_file:
self.curves = self._read_curves(acv_file)
self.polynomials = self._find_coefficients()
def _read_curves(self, acv_file):
_, nr_curves = unpack('!hh', acv_file.read(4))
curves = []
for i in range(0, nr_curves):
curve = []
num_curve_points, = unpack('!h', acv_file.read(2))
for j in range(0, num_curve_points):
y, x = unpack('!hh', acv_file.read(4))
curve.append((x,y))
curves.append(curve)
return curves
def _find_coefficients(self):
polynomials = []
for curve in self.curves:
xdata = [x[0] for x in curve]
ydata = [x[1] for x in curve]
p = interpolate.lagrange(xdata, ydata)
polynomials.append(p)
return polynomials
def get_r(self):
return self.polynomials[1]
def get_g(self):
return self.polynomials[2]
def get_b(self):
return self.polynomials[3]
def get_c(self):
return self.polynomials[0]
class FilterManager:
def __init__(self):
self.filters = {}
#add some stuff here
def add_filter(self,filter_obj):
# Overwrites if such a filter already exists
# NOTE: Fix or not to fix?
self.filters[filter_obj.name] = filter_obj
def apply_filter(self,filter_name,image_array):
if image_array.ndim < 3:
raise Exception('Photos must be in color, meaning at least 3 channels')
else:
def interpolate(i_arr, f_arr, p, p_c):
p_arr = p_c(f_arr)
return p_arr
# NOTE: Assumes that image_array is a numpy array
image_filter = self.filters[filter_name]
# NOTE: What happens if filter does not exist?
width,height,channels = image_array.shape
filter_array = numpy.zeros((width, height, 3), dtype=float)
p_r = image_filter.get_r()
p_g = image_filter.get_g()
p_b = image_filter.get_b()
p_c = image_filter.get_c()
filter_array[:,:,0] = p_r(image_array[:,:,0])
filter_array[:,:,1] = p_g(image_array[:,:,1])
filter_array[:,:,2] = p_b(image_array[:,:,2])
filter_array = filter_array.clip(0,255)
filter_array = p_c(filter_array)
filter_array = numpy.ceil(filter_array).clip(0,255)
return filter_array.astype(numpy.uint8)
if __name__ == '__main__':
if len(sys.argv) < 3:
print("Wrong number of arguments")
print(""" Usage: \
python filter.py [curvefile] [imagefile] """)
else:
img_filter = Filter(sys.argv[1], 'crgb')
im = Image.open(sys.argv[2])
im.show()
image_array = numpy.array(im)
filter_manager = FilterManager()
filter_manager.add_filter(img_filter)
filter_array = filter_manager.apply_filter('crgb', image_array)
im = Image.fromarray(filter_array)
im.save('temp.png')
im.show()