Fri, 03 May 2024 17:17:16 +0300
merge
0 | 1 | ################################ |
2 | # Code relevant to optical flow | |
3 | ################################ | |
4 | ||
5 | __precompile__() | |
6 | ||
7 | module OpticalFlow | |
8 | ||
9 | using AlgTools.Util | |
10 | using ImageTools.Gradient | |
11 | import ImageTools.Translate | |
12 | using ImageTools.ImFilter | |
13 | ||
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
14 | # using ImageTransformations |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
15 | # using Images, CoordinateTransformations, Rotations, OffsetArrays |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
16 | # using Interpolations |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
17 | |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
18 | import Images: center, warp |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
19 | import CoordinateTransformations: recenter |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
20 | import Rotations: RotMatrix |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
21 | import Interpolations: Flat |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
22 | |
0 | 23 | ########## |
24 | # Exports | |
25 | ########## | |
26 | ||
27 | export flow!, | |
28 | pdflow!, | |
29 | flow_grad!, | |
30 | flow_interp!, | |
31 | estimate_Λ², | |
32 | estimate_linear_Λ², | |
33 | pointwise_gradiprod_2d!, | |
34 | pointwise_gradiprod_2dᵀ!, | |
35 | horn_schunck_reg_prox!, | |
36 | horn_schunck_reg_prox_op!, | |
37 | mldivide_step_plus_sym2x2!, | |
38 | linearised_optical_flow_error, | |
39 | Image, AbstractImage, ImageSize, | |
40 | Gradient, Displacement, | |
41 | DisplacementFull, DisplacementConstant, | |
42 | HornSchunckData, | |
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
43 | filter_hs, |
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
44 | petpdflow!, |
47
70fd92ac9da0
experimental dual scaling
Neil Dizon <neil.dizon@helsinki.fi>
parents:
42
diff
changeset
|
45 | DualScaling, Greedy, Rotation, ZeroDual, PrimalOnly, ActivatedDual, |
36 | 46 | identifier |
0 | 47 | |
48 | ############################################### | |
49 | # Types (several imported from ImageTools.Translate) | |
50 | ############################################### | |
51 | ||
52 | Image = Translate.Image | |
53 | AbstractImage = AbstractArray{Float64,2} | |
54 | Displacement = Translate.Displacement | |
55 | DisplacementFull = Translate.DisplacementFull | |
56 | DisplacementConstant = Translate.DisplacementConstant | |
57 | Gradient = Array{Float64,3} | |
58 | ImageSize = Tuple{Int64,Int64} | |
59 | ||
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
60 | |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
61 | ################################# |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
62 | # Struct for flow |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
63 | ################################# |
35 | 64 | struct DualScaling |
65 | exponent :: Integer | |
66 | threshold :: Real | |
47
70fd92ac9da0
experimental dual scaling
Neil Dizon <neil.dizon@helsinki.fi>
parents:
42
diff
changeset
|
67 | DualScaling(e = 50, t = 1e-12) = new(e, t) |
35 | 68 | end |
69 | ||
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
70 | struct Greedy end |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
71 | struct Rotation end |
36 | 72 | struct ZeroDual end |
73 | struct PrimalOnly end | |
47
70fd92ac9da0
experimental dual scaling
Neil Dizon <neil.dizon@helsinki.fi>
parents:
42
diff
changeset
|
74 | struct ActivatedDual end |
36 | 75 | |
76 | function identifier(::DualScaling) | |
77 | "pdps_known_dualscaling" | |
78 | end | |
79 | ||
80 | function identifier(::Rotation) | |
81 | "pdps_known_rotation" | |
82 | end | |
83 | ||
84 | function identifier(::Greedy) | |
85 | "pdps_known_greedy" | |
86 | end | |
87 | ||
88 | function identifier(::ZeroDual) | |
89 | "pdps_known_zerodual" | |
90 | end | |
91 | ||
92 | function identifier(::PrimalOnly) | |
93 | "pdps_known_primalonly" | |
94 | end | |
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
95 | |
47
70fd92ac9da0
experimental dual scaling
Neil Dizon <neil.dizon@helsinki.fi>
parents:
42
diff
changeset
|
96 | function identifier(::ActivatedDual) |
70fd92ac9da0
experimental dual scaling
Neil Dizon <neil.dizon@helsinki.fi>
parents:
42
diff
changeset
|
97 | "pdps_known_activateddual" |
70fd92ac9da0
experimental dual scaling
Neil Dizon <neil.dizon@helsinki.fi>
parents:
42
diff
changeset
|
98 | end |
70fd92ac9da0
experimental dual scaling
Neil Dizon <neil.dizon@helsinki.fi>
parents:
42
diff
changeset
|
99 | |
0 | 100 | ################################# |
101 | # Displacement field based flow | |
102 | ################################# | |
103 | ||
104 | function flow_interp!(x::AbstractImage, u::Displacement, tmp::AbstractImage; | |
105 | threads = false) | |
106 | tmp .= x | |
107 | Translate.translate_image!(x, tmp, u; threads=threads) | |
108 | end | |
109 | ||
110 | function flow_interp!(x::AbstractImage, u::Displacement; | |
111 | threads = false) | |
112 | tmp = copy(x) | |
113 | Translate.translate_image!(x, tmp, u; threads=threads) | |
114 | end | |
115 | ||
116 | flow! = flow_interp! | |
117 | ||
118 | function pdflow!(x, Δx, y, Δy, u, dual_flow; threads=:none) | |
119 | if dual_flow | |
120 | #flow!((x, @view(y[1, :, :]), @view(y[2, :, :])), diffu, | |
121 | # (Δx, @view(Δy[1, :, :]), @view(Δy[2, :, :]))) | |
122 | @backgroundif (threads==:outer) begin | |
123 | flow!(x, u, Δx; threads=(threads==:inner)) | |
124 | end begin | |
125 | flow!(@view(y[1, :, :]), u, @view(Δy[1, :, :]); threads=(threads==:inner)) | |
126 | flow!(@view(y[2, :, :]), u, @view(Δy[2, :, :]); threads=(threads==:inner)) | |
127 | end | |
128 | else | |
129 | flow!(x, u, Δx) | |
130 | end | |
131 | end | |
132 | ||
36 | 133 | function pdflow!(x, Δx, y, Δy, z, Δz, u, dual_flow :: Bool; threads=:none) |
0 | 134 | if dual_flow |
135 | @backgroundif (threads==:outer) begin | |
136 | flow!(x, u, Δx; threads=(threads==:inner)) | |
137 | flow!(z, u, Δz; threads=(threads==:inner)) | |
138 | end begin | |
139 | flow!(@view(y[1, :, :]), u, @view(Δy[1, :, :]); threads=(threads==:inner)) | |
140 | flow!(@view(y[2, :, :]), u, @view(Δy[2, :, :]); threads=(threads==:inner)) | |
141 | end | |
142 | else | |
143 | flow!(x, u, Δx; threads=(threads==:inner)) | |
144 | flow!(z, u, Δz; threads=(threads==:inner)) | |
145 | end | |
146 | end | |
147 | ||
5 | 148 | # Additional method for Greedy |
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
149 | function pdflow!(x, Δx, y, Δy, u, flow :: Greedy; threads=:none) |
36 | 150 | @assert(size(u)==(2,)) |
5 | 151 | Δx .= x |
152 | Δy .= y | |
153 | flow!(x, u; threads=(threads==:inner)) | |
154 | Dxx = similar(Δy) | |
155 | DΔx = similar(Δy) | |
156 | ∇₂!(Dxx, x) | |
157 | ∇₂!(DΔx, Δx) | |
158 | inds = abs.(Dxx) .≤ 1e-1 | |
159 | Dxx[inds] .= 1 | |
160 | DΔx[inds] .= 1 | |
36 | 161 | y .= y.* DΔx ./ Dxx |
5 | 162 | end |
163 | ||
164 | # Additional method for Rotation | |
36 | 165 | function pdflow!(x, Δx, y, Δy, u, flow :: Rotation; threads=:none) |
5 | 166 | @assert(size(u)==(2,)) |
167 | Δx .= x | |
168 | flow!(x, u; threads=(threads==:inner)) | |
169 | (m,n) = size(x) | |
170 | dx = similar(y) | |
171 | dx_banana = similar(y) | |
172 | ∇₂!(dx, Δx) | |
173 | ∇₂!(dx_banana, x) | |
174 | for i=1:m | |
175 | for j=1:n | |
176 | ndx = @views sum(dx[:, i, j].^2) | |
177 | ndx_banana = @views sum(dx_banana[:, i, j].^2) | |
178 | if ndx > 1e-4 && ndx_banana > 1e-4 | |
179 | A = dx[:, i, j] | |
180 | B = dx_banana[:, i, j] | |
181 | theta = atan(B[1] * A[2] - B[2] * A[1], B[1] * A[1] + B[2] * A[2]) # Oriented angle from A to B | |
182 | cos_theta = cos(theta) | |
183 | sin_theta = sin(theta) | |
184 | a = cos_theta * y[1, i, j] - sin_theta * y[2, i, j] | |
185 | b = sin_theta * y[1, i, j] + cos_theta * y[2, i, j] | |
186 | y[1, i, j] = a | |
187 | y[2, i, j] = b | |
188 | end | |
189 | end | |
190 | end | |
191 | end | |
192 | ||
193 | # Additional method for Dual Scaling | |
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
194 | function pdflow!(x, Δx, y, Δy, u, flow :: DualScaling; threads=:none) |
5 | 195 | @assert(size(u)==(2,)) |
196 | oldx = copy(x) | |
197 | flow!(x, u; threads=(threads==:inner)) | |
198 | C = similar(y) | |
199 | cc = abs.(x-oldx) | |
35 | 200 | cm = max(flow.threshold,maximum(cc)) |
50 | 201 | # c = 1 .* (1 .- cc./ cm) .^flow.exponent |
202 | c = 1.0 .- 0.75.*activation.(cc./cm) | |
5 | 203 | C[1,:,:] .= c |
204 | C[2,:,:] .= c | |
36 | 205 | y .= C.*y |
5 | 206 | end |
207 | ||
50 | 208 | function activation(x :: Real) |
209 | return (1/(1 + exp(-1000(x - 0.05)))) # best for shepp logan | |
210 | #return -abs(x-1)^1/5 + 1 # best for lighthouse and brainphantom | |
48
06f95cdd9abe
activation function trials
Neil Dizon <neil.dizon@helsinki.fi>
parents:
47
diff
changeset
|
211 | # return x^(5) |
06f95cdd9abe
activation function trials
Neil Dizon <neil.dizon@helsinki.fi>
parents:
47
diff
changeset
|
212 | # return (1/(1 + exp(-1000(x - 0.075)))) |
06f95cdd9abe
activation function trials
Neil Dizon <neil.dizon@helsinki.fi>
parents:
47
diff
changeset
|
213 | # return 4*(x-0.5)^3 + 0.5 |
06f95cdd9abe
activation function trials
Neil Dizon <neil.dizon@helsinki.fi>
parents:
47
diff
changeset
|
214 | # return (1/(1 + exp(-1000(x - 0.05)))) |
06f95cdd9abe
activation function trials
Neil Dizon <neil.dizon@helsinki.fi>
parents:
47
diff
changeset
|
215 | # return -3(x-0.5)^2 + 0.75 |
06f95cdd9abe
activation function trials
Neil Dizon <neil.dizon@helsinki.fi>
parents:
47
diff
changeset
|
216 | # return (x-1)^51 + 1 |
06f95cdd9abe
activation function trials
Neil Dizon <neil.dizon@helsinki.fi>
parents:
47
diff
changeset
|
217 | # return -abs(x-1)^1/3 + 1 |
50 | 218 | # return 16*(x-0.5)^5 + 0.5 |
47
70fd92ac9da0
experimental dual scaling
Neil Dizon <neil.dizon@helsinki.fi>
parents:
42
diff
changeset
|
219 | end |
70fd92ac9da0
experimental dual scaling
Neil Dizon <neil.dizon@helsinki.fi>
parents:
42
diff
changeset
|
220 | |
50 | 221 | |
222 | # # Experimental predictor for dual scaling based on activation | |
223 | # function pdflow!(x, Δx, y, Δy, u, flow :: ActivatedDual; threads=:none) | |
224 | # @assert(size(u)==(2,)) | |
225 | # oldx = copy(x) | |
226 | # flow!(x, u; threads=(threads==:inner)) | |
227 | # C = similar(y) | |
228 | # cc = abs.(x-oldx) | |
229 | # cm = max(1e-12,maximum(cc)) | |
230 | # c = 1.0 .- 0.75.*activation.(cc./cm) | |
231 | # C[1,:,:] .= c | |
232 | # C[2,:,:] .= c | |
233 | # y .= C.*y | |
234 | # #y .= y .- C.*y # 0.75 for brain phantom and shepp logan | |
235 | # end | |
47
70fd92ac9da0
experimental dual scaling
Neil Dizon <neil.dizon@helsinki.fi>
parents:
42
diff
changeset
|
236 | |
36 | 237 | function pdflow!(x, Δx, y, Δy, u, :: ZeroDual; threads=:none) |
238 | @assert(size(u)==(2,)) | |
239 | flow!(x, u; threads=(threads==:inner)) | |
240 | y .= 0.0 | |
241 | end | |
242 | ||
243 | function pdflow!(x, Δx, y, Δy, u, :: PrimalOnly; threads=:none) | |
244 | @assert(size(u)==(2,)) | |
245 | flow!(x, u; threads=(threads==:inner)) | |
246 | end | |
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
247 | |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
248 | ########################## |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
249 | # PET |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
250 | ########################## |
36 | 251 | |
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
252 | function petflow_interp!(x::AbstractImage, tmp::AbstractImage, u::DisplacementConstant, theta_known::DisplacementConstant; |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
253 | threads = false) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
254 | tmp .= x |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
255 | center_point = center(x) .+ u |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
256 | tform = recenter(RotMatrix(theta_known[1]), center_point) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
257 | tmp = warp(x, tform, axes(x), fillvalue=Flat()) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
258 | x .= tmp |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
259 | end |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
260 | |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
261 | petflow! = petflow_interp! |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
262 | |
36 | 263 | function petpdflow!(x, Δx, y, Δy, u, theta_known, dual_flow :: Bool; threads=:none) |
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
264 | if dual_flow |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
265 | @backgroundif (threads==:outer) begin |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
266 | petflow!(x, Δx, u, theta_known; threads=(threads==:inner)) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
267 | end begin |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
268 | petflow!(@view(y[1, :, :]), @view(Δy[1, :, :]), u, theta_known; threads=(threads==:inner)) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
269 | petflow!(@view(y[2, :, :]), @view(Δy[2, :, :]), u, theta_known; threads=(threads==:inner)) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
270 | end |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
271 | else |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
272 | petflow!(x, Δx, u, theta_known) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
273 | end |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
274 | end |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
275 | |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
276 | # Method for greedy predictor |
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
277 | function petpdflow!(x, Δx, y, Δy, u, theta_known, flow :: Greedy; threads=:none) |
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
278 | oldx = copy(x) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
279 | center_point = center(x) .+ u |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
280 | tform = recenter(RotMatrix(theta_known[1]), center_point) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
281 | Δx = warp(x, tform, axes(x), fillvalue=Flat()) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
282 | @. x = Δx |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
283 | @. Δy = y |
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
284 | Dxx = copy(Δy) |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
285 | DΔx = copy(Δy) |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
286 | ∇₂!(Dxx, x) |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
287 | ∇₂!(DΔx, oldx) |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
288 | inds = abs.(Dxx) .≤ 1e-2 |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
289 | Dxx[inds] .= 1 |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
290 | DΔx[inds] .= 1 |
36 | 291 | y .= y.* DΔx ./ Dxx |
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
292 | end |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
293 | |
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
294 | # Method for dual scaling predictor |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
295 | function petpdflow!(x, Δx, y, Δy, u, theta_known, flow :: DualScaling; threads=:none) |
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
296 | oldx = copy(x) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
297 | center_point = center(x) .+ u |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
298 | tform = recenter(RotMatrix(theta_known[1]), center_point) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
299 | Δx = warp(x, tform, axes(x), fillvalue=Flat()) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
300 | @. x = Δx |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
301 | C = similar(y) |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
302 | cc = abs.(x-oldx) |
47
70fd92ac9da0
experimental dual scaling
Neil Dizon <neil.dizon@helsinki.fi>
parents:
42
diff
changeset
|
303 | cm = max(flow.threshold,maximum(cc)) |
50 | 304 | # c = 1 .* (1 .- cc./ cm) .^flow.exponent # Original dual scaling |
305 | # c = 1.0 .- 0.75.*activation.(cc./cm) # Best for brain phantom | |
306 | c = 1.0 .- 1.0.*activation.(cc./cm) # Best for shepp logan phantom | |
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
307 | C[1,:,:] .= c |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
308 | C[2,:,:] .= c |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
309 | y .= C.*y |
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
310 | end |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
311 | |
50 | 312 | # # Experimental predictor for dual scaling based on activation |
313 | # function petpdflow!(x, Δx, y, Δy, u, theta_known, flow :: ActivatedDual; threads=:none) | |
314 | # oldx = copy(x) | |
315 | # center_point = center(x) .+ u | |
316 | # tform = recenter(RotMatrix(theta_known[1]), center_point) | |
317 | # Δx = warp(x, tform, axes(x), fillvalue=Flat()) | |
318 | # @. x = Δx | |
319 | # C = similar(y) | |
320 | # cc = abs.(x-oldx) | |
321 | # cm = max(1e-12,maximum(cc)) | |
322 | # c = activation.(cc ./ cm) | |
323 | # C[1,:,:] .= c | |
324 | # C[2,:,:] .= c | |
325 | # # Δx .= activation.(sqrt.(abs.(y[1,:,:]).^2 + abs.(y[2,:,:]).^2))./0.25 | |
326 | # # D = similar(y) | |
327 | # # D[1,:,:] .= Δx | |
328 | # # D[2,:,:] .= Δx | |
329 | # # y .= C.*y | |
330 | # # y .= y .- 1.0.*C.*D.*y | |
331 | # #y .= y .- 1.0.*C.*y | |
332 | # end | |
47
70fd92ac9da0
experimental dual scaling
Neil Dizon <neil.dizon@helsinki.fi>
parents:
42
diff
changeset
|
333 | |
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
334 | # Method for rotation prediction (exploiting property of inverse rotation) |
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
335 | function petpdflow!(x, Δx, y, Δy, u, theta_known, flow :: Rotation; threads=:none) |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
336 | @backgroundif (threads==:outer) begin |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
337 | petflow!(x, Δx, u, theta_known; threads=(threads==:inner)) |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
338 | end begin |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
339 | petflow!(@view(y[1, :, :]), @view(Δy[1, :, :]), u, -theta_known; threads=(threads==:inner)) |
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
340 | petflow!(@view(y[2, :, :]), @view(Δy[2, :, :]), u, -theta_known; threads=(threads==:inner)) |
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
341 | end |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
342 | end |
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
343 | |
36 | 344 | function petpdflow!(x, Δx, y, Δy, u, theta_known, :: ZeroDual; threads=:none) |
345 | petflow!(x, Δx, u, theta_known, threads=(threads==:inner)) | |
346 | y .= 0.0 | |
347 | end | |
348 | ||
349 | function petpdflow!(x, Δx, y, Δy, u, theta_known, :: PrimalOnly; threads=:none) | |
350 | petflow!(x, Δx, u, theta_known, threads=(threads==:inner)) | |
351 | end | |
352 | ||
0 | 353 | ########################## |
354 | # Linearised optical flow | |
355 | ########################## | |
356 | ||
357 | # ⟨⟨u, ∇b⟩⟩ | |
358 | function pointwise_gradiprod_2d!(y::Image, vtmp::Gradient, | |
359 | u::DisplacementFull, b::Image; | |
360 | add = false) | |
361 | ∇₂c!(vtmp, b) | |
362 | ||
363 | u′=reshape(u, (size(u, 1), prod(size(u)[2:end]))) | |
364 | vtmp′=reshape(vtmp, (size(vtmp, 1), prod(size(vtmp)[2:end]))) | |
365 | y′=reshape(y, prod(size(y))) | |
366 | ||
367 | if add | |
368 | @simd for i = 1:length(y′) | |
369 | @inbounds y′[i] += dot(@view(u′[:, i]), @view(vtmp′[:, i])) | |
370 | end | |
371 | else | |
372 | @simd for i = 1:length(y′) | |
373 | @inbounds y′[i] = dot(@view(u′[:, i]), @view(vtmp′[:, i])) | |
374 | end | |
375 | end | |
376 | end | |
377 | ||
378 | function pointwise_gradiprod_2d!(y::Image, vtmp::Gradient, | |
379 | u::DisplacementConstant, b::Image; | |
380 | add = false) | |
381 | ∇₂c!(vtmp, b) | |
382 | ||
383 | vtmp′=reshape(vtmp, (size(vtmp, 1), prod(size(vtmp)[2:end]))) | |
384 | y′=reshape(y, prod(size(y))) | |
385 | ||
386 | if add | |
387 | @simd for i = 1:length(y′) | |
388 | @inbounds y′[i] += dot(u, @view(vtmp′[:, i])) | |
389 | end | |
390 | else | |
391 | @simd for i = 1:length(y′) | |
392 | @inbounds y′[i] = dot(u, @view(vtmp′[:, i])) | |
393 | end | |
394 | end | |
395 | end | |
396 | ||
397 | # ∇b ⋅ y | |
398 | function pointwise_gradiprod_2dᵀ!(u::DisplacementFull, y::Image, b::Image) | |
399 | ∇₂c!(u, b) | |
400 | ||
401 | u′=reshape(u, (size(u, 1), prod(size(u)[2:end]))) | |
402 | y′=reshape(y, prod(size(y))) | |
403 | ||
404 | @simd for i=1:length(y′) | |
405 | @inbounds @. u′[:, i] *= y′[i] | |
406 | end | |
407 | end | |
408 | ||
409 | function pointwise_gradiprod_2dᵀ!(u::DisplacementConstant, y::Image, b::Image) | |
410 | @assert(size(y)==size(b) && size(u)==(2,)) | |
411 | u .= 0 | |
412 | ∇₂cfold!(b, nothing) do g, st, (i, j) | |
413 | @inbounds u .+= g.*y[i, j] | |
414 | return st | |
415 | end | |
416 | # Reweight to be with respect to 𝟙^*𝟙 inner product. | |
417 | u ./= prod(size(b)) | |
418 | end | |
419 | ||
420 | mutable struct ConstantDisplacementHornSchunckData | |
421 | M₀::Array{Float64,2} | |
422 | z::Array{Float64,1} | |
423 | Mv::Array{Float64,2} | |
424 | av::Array{Float64,1} | |
425 | cv::Float64 | |
426 | ||
427 | function ConstantDisplacementHornSchunckData() | |
428 | return new(zeros(2, 2), zeros(2), zeros(2,2), zeros(2), 0) | |
429 | end | |
430 | end | |
431 | ||
432 | # For DisplacementConstant, for the simple prox step | |
433 | # | |
434 | # (1) argmin_u 1/(2τ)|u-ũ|^2 + (θ/2)|b⁺-b+<<u-ŭ,∇b>>|^2 + (λ/2)|u-ŭ|^2, | |
435 | # | |
436 | # construct matrix M₀ and vector z such that we can solve u from | |
437 | # | |
438 | # (2) (I/τ+M₀)u = M₀ŭ + ũ/τ - z | |
439 | # | |
440 | # Note that the problem | |
441 | # | |
442 | # argmin_u 1/(2τ)|u-ũ|^2 + (θ/2)|b⁺-b+<<u-ŭ,∇b>>|^2 + (λ/2)|u-ŭ|^2 | |
443 | # + (θ/2)|b⁺⁺-b⁺+<<uʹ-u,∇b⁺>>|^2 + (λ/2)|u-uʹ|^2 | |
444 | # | |
445 | # has with respect to u the system | |
446 | # | |
447 | # (I/τ+M₀+M₀ʹ)u = M₀ŭ + M₀ʹuʹ + ũ/τ - z + zʹ, | |
448 | # | |
449 | # where the primed variables correspond to (2) for (1) for uʹ in place of u: | |
450 | # | |
451 | # argmin_uʹ 1/(2τ)|uʹ-ũʹ|^2 + (θ/2)|b⁺⁺-b⁺+<<uʹ-u,∇b⁺>>|^2 + (λ/2)|uʹ-u|^2 | |
452 | # | |
453 | function horn_schunck_reg_prox_op!(hs::ConstantDisplacementHornSchunckData, | |
454 | bnext::Image, b::Image, θ, λ, T) | |
455 | @assert(size(b)==size(bnext)) | |
456 | w = prod(size(b)) | |
457 | z = hs.z | |
458 | cv = 0 | |
459 | # Factors of symmetric matrix [a c; c d] | |
460 | a, c, d = 0.0, 0.0, 0.0 | |
461 | # This used to use ∇₂cfold but it is faster to allocate temporary | |
462 | # storage for the full gradient due to probably better memory and SIMD | |
36 | 463 | # instruction usage. |
0 | 464 | g = zeros(2, size(b)...) |
465 | ∇₂c!(g, b) | |
466 | @inbounds for i=1:size(b, 1) | |
467 | for j=1:size(b, 2) | |
468 | δ = bnext[i,j]-b[i,j] | |
469 | @. z += g[:,i,j]*δ | |
470 | cv += δ*δ | |
471 | a += g[1,i,j]*g[1,i,j] | |
472 | c += g[1,i,j]*g[2,i,j] | |
473 | d += g[2,i,j]*g[2,i,j] | |
474 | end | |
475 | end | |
476 | w₀ = λ | |
477 | w₂ = θ/w | |
478 | aʹ = w₀ + w₂*a | |
479 | cʹ = w₂*c | |
480 | dʹ = w₀ + w₂*d | |
481 | hs.M₀ .= [aʹ cʹ; cʹ dʹ] | |
482 | hs.Mv .= [w*λ+θ*a θ*c; θ*c w*λ+θ*d] | |
483 | hs.cv = cv*θ | |
484 | hs.av .= hs.z.*θ | |
485 | hs.z .*= w₂/T | |
486 | end | |
487 | ||
488 | # Solve the 2D system (I/τ+M₀)u = z | |
489 | @inline function mldivide_step_plus_sym2x2!(u, M₀, z, τ) | |
490 | a = 1/τ+M₀[1, 1] | |
491 | c = M₀[1, 2] | |
492 | d = 1/τ+M₀[2, 2] | |
493 | u .= ([d -c; -c a]*z)./(a*d-c*c) | |
494 | end | |
495 | ||
496 | function horn_schunck_reg_prox!(u::DisplacementConstant, bnext::Image, b::Image, | |
497 | θ, λ, T, τ) | |
498 | hs=ConstantDisplacementHornSchunckData() | |
499 | horn_schunck_reg_prox_op!(hs, bnext, b, θ, λ, T) | |
500 | mldivide_step_plus_sym2x2!(u, hs.M₀, (u./τ)-hs.z, τ) | |
501 | end | |
502 | ||
503 | function flow_grad!(x::Image, vtmp::Gradient, u::Displacement; δ=nothing) | |
504 | if !isnothing(δ) | |
505 | u = δ.*u | |
506 | end | |
507 | pointwise_gradiprod_2d!(x, vtmp, u, x; add=true) | |
508 | end | |
509 | ||
510 | # Error b-b_prev+⟨⟨u, ∇b⟩⟩ for Horn–Schunck type penalisation | |
511 | function linearised_optical_flow_error(u::Displacement, b::Image, b_prev::Image) | |
512 | imdim = size(b) | |
513 | vtmp = zeros(2, imdim...) | |
514 | tmp = b-b_prev | |
515 | pointwise_gradiprod_2d!(tmp, vtmp, u, b_prev; add=true) | |
516 | return tmp | |
517 | end | |
518 | ||
519 | ############################################## | |
520 | # Helper to smooth data for Horn–Schunck term | |
521 | ############################################## | |
522 | ||
523 | function filter_hs(b, b_next, b_next_filt, kernel) | |
524 | if kernel==nothing | |
525 | f = x -> x | |
526 | else | |
527 | f = x -> simple_imfilter(x, kernel; threads=true) | |
528 | end | |
529 | ||
36 | 530 | # We already filtered b in the previous step (b_next in that step) |
0 | 531 | b_filt = b_next_filt==nothing ? f(b) : b_next_filt |
532 | b_next_filt = f(b_next) | |
533 | ||
534 | return b_filt, b_next_filt | |
535 | end | |
536 | ||
537 | end # Module |