Sat, 04 Dec 2021 09:08:24 +0200
Oops, the ColourTools.jl file was missing.
18
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
1 | ################################################## |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
2 | # Simple (and fast for small filters compared to |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
3 | # ImageFiltering) image filtering |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
4 | ################################################## |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
5 | |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
6 | __precompile__() |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
7 | |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
8 | module ImFilter |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
9 | |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
10 | using OffsetArrays |
48 | 11 | using AlgTools.Util: @threadsif, norm₁ |
12 | using AlgTools.LinOps | |
18
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
13 | |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
14 | ########## |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
15 | # Exports |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
16 | ########## |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
17 | |
22
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
18 | export simple_imfilter, |
48 | 19 | simple_imfilter!, |
20 | simple_imfilter_adjoint, | |
21 | simple_imfilter_adjoint!, | |
22 | gaussian, | |
23 | FilterKernel | |
18
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
24 | |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
25 | ############## |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
26 | # The routine |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
27 | ############## |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
28 | |
48 | 29 | Image = Array{Float64,2} |
30 | Kernel = OffsetArray{Float64,2,Image} | |
31 | ||
18
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
32 | @inline function inside(i, aʹ, bʹ, a, b) |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
33 | return (max(a, i - aʹ) - i):(min(b, i + bʹ) - i) |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
34 | end |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
35 | |
48 | 36 | function simple_imfilter!(res::Image, b::Image, kernel::Kernel; threads::Bool=true) |
18
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
37 | n, m = size(b) |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
38 | k, 𝓁 = size(kernel) |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
39 | o₁, o₂ = kernel.offsets |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
40 | a₁, a₂ = k + o₁, 𝓁 + o₂ |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
41 | b₁, b₂ = -1 - o₁, -1 - o₂ |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
42 | kp = kernel.parent |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
43 | |
48 | 44 | @assert(isodd(k) && isodd(𝓁) && size(res)==size(b)) |
18
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
45 | |
32 | 46 | @threadsif threads for i=1:n |
30
0b25d9ef7af9
Better @inbounds placements etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
29
diff
changeset
|
47 | @inbounds for j=1:m |
18
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
48 | tmp = 0.0 |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
49 | it₁ = inside(i, a₁, b₁, 1, n) |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
50 | it₂ = inside(j, a₂, b₂, 1, m) |
30
0b25d9ef7af9
Better @inbounds placements etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
29
diff
changeset
|
51 | for p=it₁ |
18
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
52 | @simd for q=it₂ |
29 | 53 | tmp += kp[p-o₁, q-o₂]*b[i+p,j+q] |
18
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
54 | end |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
55 | end |
30
0b25d9ef7af9
Better @inbounds placements etc.
Tuomo Valkonen <tuomov@iki.fi>
parents:
29
diff
changeset
|
56 | res[i, j] = tmp |
18
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
57 | end |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
58 | end |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
59 | |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
60 | return res |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
61 | end |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
62 | |
48 | 63 | function simple_imfilter(b::Image, kernel::Kernel; threads::Bool=true) |
64 | res = similar(b) | |
65 | simple_imfilter!(res, b, kernel) | |
66 | end | |
67 | ||
68 | function simple_imfilter_adjoint!(res::Image, b::Image, kernel::Kernel; threads::Bool=true) | |
69 | n, m = size(b) | |
70 | k, 𝓁 = size(kernel) | |
71 | o₁, o₂ = kernel.offsets | |
72 | a₁, a₂ = k + o₁, 𝓁 + o₂ | |
73 | b₁, b₂ = -1 - o₁, -1 - o₂ | |
74 | kp = kernel.parent | |
75 | ||
76 | @assert(isodd(k) && isodd(𝓁) && size(res)==size(b)) | |
77 | ||
78 | res .= 0 | |
79 | ||
80 | @threadsif threads for i=1:n | |
81 | @inbounds for j=1:m | |
82 | it₁ = inside(i, a₁, b₁, 1, n) | |
83 | it₂ = inside(j, a₂, b₂, 1, m) | |
84 | for p=it₁ | |
85 | @simd for q=it₂ | |
86 | res[i+p,j+q] += kp[p-o₁, q-o₂]*b[i, j] | |
87 | end | |
88 | end | |
89 | end | |
90 | end | |
91 | ||
92 | return res | |
93 | end | |
94 | ||
95 | function simple_imfilter_adjoint(b::Image, kernel::Kernel; threads::Bool=true) | |
96 | res = similar(b) | |
97 | simple_imfilter_adjoint!(res, b, kernel) | |
98 | end | |
99 | ||
100 | ########################### | |
101 | # Abstract linear operator | |
102 | ########################### | |
103 | ||
104 | struct FilterKernel <: AdjointableOp{Image, Image} | |
105 | kernel::Kernel | |
106 | end | |
107 | ||
108 | function (op::FilterKernel)(b::Image) | |
109 | return simple_imfilter(b, op.kernel) | |
110 | end | |
111 | ||
112 | function LinOps.inplace!(y::Image, op::FilterKernel, x::Image) | |
113 | return simple_imfilter!(y, x, op.kernel) | |
114 | end | |
115 | ||
116 | function LinOps.calc_adjoint(op::FilterKernel, y::Image) | |
117 | return simple_imfilter_adjoint(y, op.kernel) | |
118 | end | |
119 | ||
120 | function LinOps.calc_adjoint!(res::Image, op::FilterKernel, y::Image) | |
121 | return simple_imfilter_adjoint!(res, y, op.kernel) | |
122 | end | |
123 | ||
124 | function LinOps.opnorm_estimate(op::FilterKernel) | |
125 | # Due to |f * g|_p ≤ |f|_p|g|_1 | |
126 | return norm₁(op.kernel) | |
127 | end | |
128 | ||
22
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
129 | ###################################################### |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
130 | # Distributions. Just to avoid the long load times of |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
131 | # ImageFiltering and heavy dependencies on FFTW etc. |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
132 | ###################################################### |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
133 | |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
134 | function gaussian(σ, n) |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
135 | @assert(all(isodd.(n))) |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
136 | a=convert.(Integer, @. (n-1)/2) |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
137 | g=OffsetArray{Float64}(undef, [-m:m for m in a]...); |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
138 | for i in CartesianIndices(g) |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
139 | g[i]=exp(-sum(Tuple(i).^2 ./ (2 .* σ.^2))) |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
140 | end |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
141 | g./=sum(g) |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
142 | end |
4403f0445814
Add gaussian distr to avoid hevy ImageFiltering dependencies.
Tuomo Valkonen <tuomov@iki.fi>
parents:
18
diff
changeset
|
143 | |
18
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
144 | end # Module |
0d99f8f7d261
Added ImFilter & simple_imfilter.
Tuomo Valkonen <tuomov@iki.fi>
parents:
diff
changeset
|
145 |