-
Notifications
You must be signed in to change notification settings - Fork 0
/
notebook.jl
296 lines (236 loc) · 7.67 KB
/
notebook.jl
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
### A Pluto.jl notebook ###
# v0.11.14
using Markdown
using InteractiveUtils
# ╔═╡ 88cfc46c-f46d-11ea-21df-59c027e4b86b
begin
import Pkg
Pkg.activate(mktempdir())
Pkg.add(["Images", "ImageIO", "ImageMagick", "ImageTransformations", "ImageFiltering"])
using Images, LinearAlgebra, SparseArrays
md"Libraries added"
end
# ╔═╡ 045fc73c-f5bb-11ea-210d-c3a88c7b5c08
md"# Reversing a convolution"
# ╔═╡ ce1dd8fc-f5bb-11ea-3cf4-4b20b1250bb1
md"## Functions"
# ╔═╡ f1cf67d8-f5bc-11ea-0015-192f0ebb1fdf
md"### Kernel"
# ╔═╡ f284c890-f5bb-11ea-30e8-abbc1f458cec
function Kernel_uniform(shape)
value = 1/prod(shape)
return fill(value, shape)
end
# ╔═╡ fcae7582-f5bb-11ea-2b79-43f8cd3178c3
function get_pad(kernel)
return (size(kernel).-1).÷2
end
# ╔═╡ e6b903c2-f5bc-11ea-0c2c-03e099517d90
md"### Convolution and Reverse"
# ╔═╡ fb654aee-f5bc-11ea-35f4-3397194c8722
md"## Example"
# ╔═╡ 116fe702-f5bd-11ea-0ba9-c55263d026ba
md"### Importing image"
# ╔═╡ a3f814ac-f46c-11ea-33d7-81d4c435aba2
begin
i = 2
if i==1
filename = "monkey"
large_image = load("monkey.jpg")
image = imresize(large_image; ratio=0.15)
elseif i==2
filename = "lena"
large_image = load("lena.jpg")
image = imresize(large_image; ratio=0.35)
end
#image = Gray.(image)
#image = Gray.(rand(Float64, (5, 5)))
end
# ╔═╡ e731fd9c-f475-11ea-0123-b5df0503c9ba
size(image)
# ╔═╡ 5965dbc0-f4fa-11ea-3d29-536288bec4f6
typeof(image)
# ╔═╡ 1eb50ff0-f5bd-11ea-34a9-65ceeb74698a
md"### Initializing filter"
# ╔═╡ 820976ec-f476-11ea-0113-d909496fa398
begin
#kernel = Kernel_uniform((3, 3))
kernel = Kernel.gaussian((3, 3))
pad = Pad(:replicate, get_pad(kernel))
#pad = Fill(0, size(kernel))
size(kernel)
end
# ╔═╡ 110e881e-f5bc-11ea-0a20-3dabe51098a3
function f2mat(img, f, pad=Pad(:replicate, get_pad(kernel)))
input_shape = size(img)
input_size = prod(input_shape)
indices = reshape(1:input_size, input_shape)
pad_size = get_pad(f)
indices = padarray(indices, pad)
indices = parent(indices)
f = parent(f)
output_shape = size(indices) .- size(f) .+ (1, 1)
output_size = prod(output_shape)
mat = sparse([], [], Float64[], input_size, output_size)
for j=1:output_shape[2], i=1:output_shape[1]
for n=1:size(f, 2), m=1:size(f, 1)
input_idx = indices[i+m-1, j+n-1]
if input_idx > 0
output_idx = i + (j-1)*output_shape[1]
mat[input_idx, output_idx] += f[m, n]
end
end
end
return mat'
end
# ╔═╡ 9966750a-f5bc-11ea-2402-f16ff519f56d
function convolution(image, kernel, pad=Pad(:replicate, get_pad(kernel)))
matrix = f2mat(image, kernel, pad)
mono = (length(size(channelview(image)))==2)
if mono
return reshape(matrix*vec(image), size(image))
else
channels = channelview(image)
new_image = [reshape(matrix*vec(channels[i, :, :]), size(image)) for i=1:3]
return colorview(RGB, new_image[1], new_image[2], new_image[3])
end
end
# ╔═╡ a053dae2-f5bc-11ea-11fb-7115b2489efa
function get_original(image, kernel, pad=Pad(:replicate, get_pad(kernel)))
matrix = f2mat(image, kernel, pad)
mono = (length(size(channelview(image)))==2)
if mono
channel = channelview(image)
estim = matrix\vec(channel)
estim = [(x>1) ? 1 : (x<0) ? 0 : x for x in estim] # image values in [0, 1]
return Gray.(reshape(estim, size(image)))
else
channels = channelview(image)
new_image = zeros(size(channels))
for i=1:3
estim = matrix\vec(channels[i, :, :])
estim = [(x>1) ? 1 : (x<0) ? 0 : x for x in estim] # in [0, 1]
new_image[i, :, :] = estim
end
return colorview(RGB, new_image)
end
end
# ╔═╡ 3d477c82-f5bd-11ea-2571-f5cdb9fc1525
md"### Filtered image"
# ╔═╡ 9017eb36-f47d-11ea-0ae8-f3b3bb85bf53
filtered_pad = imfilter(image, kernel, pad, Algorithm.FIR())
# ╔═╡ d89f858a-f47d-11ea-20fc-ed418cc5653b
size(filtered_pad)
# ╔═╡ 3626ce80-f482-11ea-15f0-497b0ee9b3a4
#matrix = f2mat(image, kernel, "zero")
# ╔═╡ 30f93266-f4fa-11ea-35d5-b7bd56cb73e3
#convolution(image, kernel, "replicate")
# ╔═╡ 52ae79ae-f5bd-11ea-1d9b-a5963c9bcd16
md"### Reversing the convolution"
# ╔═╡ 4bd86730-f512-11ea-1c03-bfd6d008e37a
begin
estimate = false
if !estimate
estimated_kernel = kernel
estimated_pad = pad
else
estimated_kernel = Kernel.gaussian((3, 3))
#estimated_kernel = Kernel_uniform((7, 7))
#estimated_pad = Fill(0, get_pad(estimated_kernel))
estimated_pad = Pad(:replicate, get_pad(estimated_kernel))
end
recovered = get_original(filtered_pad, estimated_kernel, estimated_pad)
end
# ╔═╡ 68b18282-f5bd-11ea-1801-933fb61400ab
md"#### Original | Filtered | Recovered"
# ╔═╡ 4eb55d58-f514-11ea-064c-2b8a08b3c1eb
[image filtered_pad recovered]
# ╔═╡ 18642c9c-f5bf-11ea-2d7f-0956bb770cc7
begin
save(filename * "_original.jpg", image)
save(filename * "_blurred.jpg", filtered_pad)
save(filename * "_recovered.jpg", recovered)
md"Files saved"
end
# ╔═╡ d6714f18-f60b-11ea-15b6-517d7006d9e4
md"old functions inside"
#=
begin
function get_b(img, f, pad, mat, idx)
pad_size = get_pad(f)
if pad=="replicate"
img_padded = padarray(img, Pad(:replicate,pad_size))
img_padded[1:end-pad_size[1], 1:end-pad_size[2]] .= 0
else
return 0
end
mono = (length(size(channelview(img)))==2)
if mono
b = mat*vec(img)
return reshape(b[idx], size(img))
else
channels = channelview(img)
b = zeros(size(img))
for i=1:3
b_i = mat*vec(channels[i, :, :])
b[i, :, :] = reshape(b_i[idx], size(img))
end
return colorview(RGB, b)
end
end
function f2mat2(img, f, pad="zero")
# https://stackoverflow.com/questions/16798888/2-d-convolution-as-a-matrix-matrix-multiplication
pad_size = get_pad(f)
mask = padarray(fill(true, size(img)), Fill(false, pad_size))
input_shape = size(mask)
output_shape = input_shape .- size(f) .+ (1, 1)
input_size = prod(input_shape)
output_size = prod(output_shape)
mat = sparse([], [], Float64[], input_size, output_size)
delta = input_shape[1]-size(f, 1)
f_flat = sparse([], [], Float64[], input_shape[1], size(f, 2))
f_flat[1:size(f, 1), :] = parent(f)
f_flat = sparsevec(f_flat)[1:end-delta]
delta = input_shape[1] - size(f, 1) + 1
for i=1:size(mat, 2)÷delta, j=1:delta
ii = (i-1)*input_shape[1]+j
jj = (i-1)*delta+j
mat[ii:ii+length(f_flat)-1, jj] = f_flat
end
mask_flat = vec(mask)
#b = get_b(img, f, pad, mat, mask_flat)
idx = [i for i=1:length(mask) if mask[i]]
mat = mat[idx, :]
return mat'
end
end
=#
# ╔═╡ Cell order:
# ╟─045fc73c-f5bb-11ea-210d-c3a88c7b5c08
# ╟─ce1dd8fc-f5bb-11ea-3cf4-4b20b1250bb1
# ╟─88cfc46c-f46d-11ea-21df-59c027e4b86b
# ╟─f1cf67d8-f5bc-11ea-0015-192f0ebb1fdf
# ╟─f284c890-f5bb-11ea-30e8-abbc1f458cec
# ╟─fcae7582-f5bb-11ea-2b79-43f8cd3178c3
# ╟─e6b903c2-f5bc-11ea-0c2c-03e099517d90
# ╟─110e881e-f5bc-11ea-0a20-3dabe51098a3
# ╟─9966750a-f5bc-11ea-2402-f16ff519f56d
# ╟─a053dae2-f5bc-11ea-11fb-7115b2489efa
# ╟─fb654aee-f5bc-11ea-35f4-3397194c8722
# ╟─116fe702-f5bd-11ea-0ba9-c55263d026ba
# ╠═a3f814ac-f46c-11ea-33d7-81d4c435aba2
# ╟─e731fd9c-f475-11ea-0123-b5df0503c9ba
# ╟─5965dbc0-f4fa-11ea-3d29-536288bec4f6
# ╟─1eb50ff0-f5bd-11ea-34a9-65ceeb74698a
# ╠═820976ec-f476-11ea-0113-d909496fa398
# ╟─3d477c82-f5bd-11ea-2571-f5cdb9fc1525
# ╠═9017eb36-f47d-11ea-0ae8-f3b3bb85bf53
# ╟─d89f858a-f47d-11ea-20fc-ed418cc5653b
# ╠═3626ce80-f482-11ea-15f0-497b0ee9b3a4
# ╠═30f93266-f4fa-11ea-35d5-b7bd56cb73e3
# ╟─52ae79ae-f5bd-11ea-1d9b-a5963c9bcd16
# ╠═4bd86730-f512-11ea-1c03-bfd6d008e37a
# ╟─68b18282-f5bd-11ea-1801-933fb61400ab
# ╠═4eb55d58-f514-11ea-064c-2b8a08b3c1eb
# ╟─18642c9c-f5bf-11ea-2d7f-0956bb770cc7
# ╟─d6714f18-f60b-11ea-15b6-517d7006d9e4