1
1
"""
2
- centered(kernel) -> shiftedkernel
2
+ shiftedkernel = centered(kernel)
3
3
4
4
Shift the origin-of-coordinates to the center of `kernel`. The
5
5
center-element of `kernel` will be accessed by `shiftedkernel[0, 0,
@@ -13,6 +13,71 @@ See also: [`imfilter`](@ref).
13
13
"""
14
14
centered (A:: AbstractArray ) = OffsetArray (A, map (n-> - ((n+ 1 )>> 1 ), size (A)))
15
15
16
+ """
17
+ kernfft = freqkernel([T::Type], kern, sz=size(kern); rfft=false)
18
+
19
+ Return a frequency-space representation of `kern`.
20
+ This embeds `kern` in an array of size `sz`, in a manner that implicitly imposes periodic boundary
21
+ conditions, and then returns the fourier transform. This is sometimes called the optical transfer
22
+ function, and known in some frameworks as `psf2otf`. If `rfft` is `true`, the fft for real-valued
23
+ arrays (`rfft`) is returned instead and the first dimension size will be approximately half of `sz[1]`.
24
+
25
+ `kern` should be zero-centered, i.e., `kern[0, 0]` should reference the center of your kernel.
26
+ See [`centered`](@ref). Optionally specify the numeric type `T` (which must be one of the
27
+ types supported by FFTW, either `Float32` or `Float64`).
28
+
29
+ The inverse of `freqkernel` is [`spacekernel`](@ref).
30
+ """
31
+ function freqkernel (:: Type{T} , kern:: AbstractArray , sz:: Dims = size (kern); rfft= false ) where T<: Union{Float32,Float64}
32
+ wrapindex (i, s) = i< 1 ? i+ s : i
33
+ all (size (kern) .<= sz) || throw (DimensionMismatch (" kernel size $(size (kern)) is bigger than supplied size $sz " ))
34
+ kernw = zeros (T, sz... )
35
+ for I in CartesianIndices (kern)
36
+ J = CartesianIndex (map (wrapindex, Tuple (I), sz))
37
+ kernw[J] = kern[I]
38
+ end
39
+ return rfft ? FFTW. rfft (kernw) : fft (kernw)
40
+ end
41
+ freqkernel (kern:: AbstractArray{T} , args... ; rfft= false ) where T =
42
+ freqkernel (ffteltype (T), kern, args... ; rfft= rfft)
43
+
44
+ """
45
+ kern = spacekernel(kernfft, axs; rfftsz=0)
46
+
47
+ Return a real-space representation of `kernfft`, a frequency-space representation of a kernel.
48
+ This performs an inverse fourier transform, implicitly imposes periodic boundary conditions,
49
+ and then trims & truncates axes of the output to `axs`. By default `kernfft` is assumed to have
50
+ been generated by `fft`; if it was instead generated by `rfft`, specify the original size
51
+ of the first dimension. (If `kernfft` was generated by [`freqkernel`](@ref), this is just `sz[1]`.)
52
+
53
+ The inverse of `spacekernel` is [`freqkernel`](@ref).
54
+ """
55
+ function spacekernel (kernfft:: AbstractArray , axs:: Indices ; rfftsz= 0 )
56
+ wrapindex (i, s) = i< 1 ? i+ s : i
57
+ kernw = rfftsz > 0 ? irfft (kernfft, rfftsz) : ifft (kernfft)
58
+ kern = zeros (eltype (kernw), axs... )
59
+ sz = size (kernw)
60
+ for I in CartesianIndices (kern)
61
+ J = CartesianIndex (map (wrapindex, Tuple (I), sz))
62
+ kern[I] = kernw[J]
63
+ end
64
+ return kern
65
+ end
66
+ function spacekernel (kernfft:: AbstractArray ; rfftsz= 0 )
67
+ sz = size (kernfft)
68
+ if rfftsz > 0
69
+ sz = (rfftsz, Base. tail (sz)... )
70
+ end
71
+ upper = map (s-> s>> 1 , sz)
72
+ axs = map ((u, s)-> u- s+ 1 : u, upper, sz)
73
+ return spacekernel (kernfft, axs; rfftsz= rfftsz)
74
+ end
75
+
76
+ ffteltype (:: Type{T} ) where T<: Union{Float32,Float64} = T
77
+ ffteltype (:: Type{Float16} ) = Float32
78
+ ffteltype (:: Type{T} ) where T<: Normed = ffteltype (FixedPointNumbers. floattype (T))
79
+ ffteltype (:: Type{T} ) where T = Float64
80
+
16
81
dummyind (:: Base.OneTo ) = Base. OneTo (1 )
17
82
dummyind (:: AbstractUnitRange ) = 0 : 0
18
83
0 commit comments