Thu, 19 Sep 2024 21:30:26 -0500
Print ∑_{i=0}^N} 𝒢(x^{k+1}; x^k) as value
|
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 |