Wed, 24 Apr 2024 16:55:04 +0300
added img folder
| 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!, |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
45 | DualScaling, Greedy, Rotation |
| 0 | 46 | |
| 47 | ############################################### | |
| 48 | # Types (several imported from ImageTools.Translate) | |
| 49 | ############################################### | |
| 50 | ||
| 51 | Image = Translate.Image | |
| 52 | AbstractImage = AbstractArray{Float64,2} | |
| 53 | Displacement = Translate.Displacement | |
| 54 | DisplacementFull = Translate.DisplacementFull | |
| 55 | DisplacementConstant = Translate.DisplacementConstant | |
| 56 | Gradient = Array{Float64,3} | |
| 57 | ImageSize = Tuple{Int64,Int64} | |
| 58 | ||
|
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
59 | |
|
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 | # Struct for flow |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
62 | ################################# |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
63 | struct DualScaling end |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
64 | struct Greedy end |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
65 | struct Rotation end |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
66 | |
| 0 | 67 | ################################# |
| 68 | # Displacement field based flow | |
| 69 | ################################# | |
| 70 | ||
| 71 | function flow_interp!(x::AbstractImage, u::Displacement, tmp::AbstractImage; | |
| 72 | threads = false) | |
| 73 | tmp .= x | |
| 74 | Translate.translate_image!(x, tmp, u; threads=threads) | |
| 75 | end | |
| 76 | ||
| 77 | function flow_interp!(x::AbstractImage, u::Displacement; | |
| 78 | threads = false) | |
| 79 | tmp = copy(x) | |
| 80 | Translate.translate_image!(x, tmp, u; threads=threads) | |
| 81 | end | |
| 82 | ||
| 83 | flow! = flow_interp! | |
| 84 | ||
| 85 | function pdflow!(x, Δx, y, Δy, u, dual_flow; threads=:none) | |
| 86 | if dual_flow | |
| 87 | #flow!((x, @view(y[1, :, :]), @view(y[2, :, :])), diffu, | |
| 88 | # (Δx, @view(Δy[1, :, :]), @view(Δy[2, :, :]))) | |
| 89 | @backgroundif (threads==:outer) begin | |
| 90 | flow!(x, u, Δx; threads=(threads==:inner)) | |
| 91 | end begin | |
| 92 | flow!(@view(y[1, :, :]), u, @view(Δy[1, :, :]); threads=(threads==:inner)) | |
| 93 | flow!(@view(y[2, :, :]), u, @view(Δy[2, :, :]); threads=(threads==:inner)) | |
| 94 | end | |
| 95 | else | |
| 96 | flow!(x, u, Δx) | |
| 97 | end | |
| 98 | end | |
| 99 | ||
| 100 | function pdflow!(x, Δx, y, Δy, z, Δz, u, dual_flow; threads=:none) | |
| 101 | if dual_flow | |
| 102 | @backgroundif (threads==:outer) begin | |
| 103 | flow!(x, u, Δx; threads=(threads==:inner)) | |
| 104 | flow!(z, u, Δz; threads=(threads==:inner)) | |
| 105 | end begin | |
| 106 | flow!(@view(y[1, :, :]), u, @view(Δy[1, :, :]); threads=(threads==:inner)) | |
| 107 | flow!(@view(y[2, :, :]), u, @view(Δy[2, :, :]); threads=(threads==:inner)) | |
| 108 | end | |
| 109 | else | |
| 110 | flow!(x, u, Δx; threads=(threads==:inner)) | |
| 111 | flow!(z, u, Δz; threads=(threads==:inner)) | |
| 112 | end | |
| 113 | end | |
| 114 | ||
| 5 | 115 | # Additional method for Greedy |
|
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
116 | function pdflow!(x, Δx, y, Δy, u, flow :: Greedy; threads=:none) |
| 5 | 117 | @assert(size(u)==(2,)) |
| 118 | Δx .= x | |
| 119 | Δy .= y | |
| 120 | flow!(x, u; threads=(threads==:inner)) | |
| 121 | Dxx = similar(Δy) | |
| 122 | DΔx = similar(Δy) | |
| 123 | ∇₂!(Dxx, x) | |
| 124 | ∇₂!(DΔx, Δx) | |
| 125 | inds = abs.(Dxx) .≤ 1e-1 | |
| 126 | Dxx[inds] .= 1 | |
| 127 | DΔx[inds] .= 1 | |
| 128 | y .= y.* DΔx ./ Dxx | |
| 129 | end | |
| 130 | ||
| 131 | # Additional method for Rotation | |
|
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
132 | function pdflow!(x, Δx, y, Δy, u, flow :: Rotation; threads=:none) |
| 5 | 133 | @assert(size(u)==(2,)) |
| 134 | Δx .= x | |
| 135 | flow!(x, u; threads=(threads==:inner)) | |
| 136 | (m,n) = size(x) | |
| 137 | dx = similar(y) | |
| 138 | dx_banana = similar(y) | |
| 139 | ∇₂!(dx, Δx) | |
| 140 | ∇₂!(dx_banana, x) | |
| 141 | for i=1:m | |
| 142 | for j=1:n | |
| 143 | ndx = @views sum(dx[:, i, j].^2) | |
| 144 | ndx_banana = @views sum(dx_banana[:, i, j].^2) | |
| 145 | if ndx > 1e-4 && ndx_banana > 1e-4 | |
| 146 | A = dx[:, i, j] | |
| 147 | B = dx_banana[:, i, j] | |
| 148 | theta = atan(B[1] * A[2] - B[2] * A[1], B[1] * A[1] + B[2] * A[2]) # Oriented angle from A to B | |
| 149 | cos_theta = cos(theta) | |
| 150 | sin_theta = sin(theta) | |
| 151 | a = cos_theta * y[1, i, j] - sin_theta * y[2, i, j] | |
| 152 | b = sin_theta * y[1, i, j] + cos_theta * y[2, i, j] | |
| 153 | y[1, i, j] = a | |
| 154 | y[2, i, j] = b | |
| 155 | end | |
| 156 | end | |
| 157 | end | |
| 158 | end | |
| 159 | ||
| 160 | # Additional method for Dual Scaling | |
|
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
161 | function pdflow!(x, Δx, y, Δy, u, flow :: DualScaling; threads=:none) |
| 5 | 162 | @assert(size(u)==(2,)) |
| 163 | oldx = copy(x) | |
| 164 | flow!(x, u; threads=(threads==:inner)) | |
| 165 | C = similar(y) | |
| 166 | cc = abs.(x-oldx) | |
| 167 | cm = max(1e-12,maximum(cc)) | |
| 168 | c = 1 .* (1 .- cc./ cm) .^(10) | |
| 169 | C[1,:,:] .= c | |
| 170 | C[2,:,:] .= c | |
| 171 | y .= C.*y | |
| 172 | end | |
| 173 | ||
|
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
174 | |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
175 | ########################## |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
176 | # PET |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
177 | ########################## |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
178 | 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
|
179 | threads = false) |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
180 | tmp .= x |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
181 | center_point = center(x) .+ u |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
182 | tform = recenter(RotMatrix(theta_known[1]), center_point) |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
183 | tmp = warp(x, tform, axes(x), fillvalue=Flat()) |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
184 | x .= tmp |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
185 | end |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
186 | |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
187 | petflow! = petflow_interp! |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
188 | |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
189 | function petpdflow!(x, Δx, y, Δy, u, theta_known, dual_flow; threads=:none) |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
190 | if dual_flow |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
191 | @backgroundif (threads==:outer) begin |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
192 | 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
|
193 | end begin |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
194 | 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
|
195 | 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
|
196 | end |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
197 | else |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
198 | petflow!(x, Δx, u, theta_known) |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
199 | end |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
200 | end |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
201 | |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
202 | # Method for greedy predictor |
|
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
203 | 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
|
204 | oldx = copy(x) |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
205 | center_point = center(x) .+ u |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
206 | tform = recenter(RotMatrix(theta_known[1]), center_point) |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
207 | Δx = warp(x, tform, axes(x), fillvalue=Flat()) |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
208 | @. x = Δx |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
209 | @. Δy = y |
|
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
210 | Dxx = copy(Δy) |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
211 | DΔx = copy(Δy) |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
212 | ∇₂!(Dxx, x) |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
213 | ∇₂!(DΔx, oldx) |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
214 | inds = abs.(Dxx) .≤ 1e-2 |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
215 | Dxx[inds] .= 1 |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
216 | DΔx[inds] .= 1 |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
217 | y .= y.* DΔx ./ Dxx |
|
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
218 | end |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
219 | |
|
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
220 | # Method for dual scaling predictor |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
221 | 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
|
222 | oldx = copy(x) |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
223 | center_point = center(x) .+ u |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
224 | tform = recenter(RotMatrix(theta_known[1]), center_point) |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
225 | Δx = warp(x, tform, axes(x), fillvalue=Flat()) |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
226 | @. x = Δx |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
227 | C = similar(y) |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
228 | cc = abs.(x-oldx) |
|
26
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
229 | cm = max(1e-12,maximum(cc)) |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
230 | c = 1 .* (1 .- cc./ cm) .^(10) |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
231 | C[1,:,:] .= c |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
232 | C[2,:,:] .= c |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
233 | y .= C.*y |
|
8
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
234 | end |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
235 | |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
236 | # 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
|
237 | 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
|
238 | @backgroundif (threads==:outer) begin |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
239 | 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
|
240 | end begin |
|
ccd22bbbb02f
added dummy structs for different flows
Neil Dizon <neil.dizon@helsinki.fi>
parents:
8
diff
changeset
|
241 | 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
|
242 | 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
|
243 | end |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
244 | end |
|
e4ad8f7ce671
Added PET and updated README
Neil Dizon <neil.dizon@helsinki.fi>
parents:
5
diff
changeset
|
245 | |
| 0 | 246 | ########################## |
| 247 | # Linearised optical flow | |
| 248 | ########################## | |
| 249 | ||
| 250 | # ⟨⟨u, ∇b⟩⟩ | |
| 251 | function pointwise_gradiprod_2d!(y::Image, vtmp::Gradient, | |
| 252 | u::DisplacementFull, b::Image; | |
| 253 | add = false) | |
| 254 | ∇₂c!(vtmp, b) | |
| 255 | ||
| 256 | u′=reshape(u, (size(u, 1), prod(size(u)[2:end]))) | |
| 257 | vtmp′=reshape(vtmp, (size(vtmp, 1), prod(size(vtmp)[2:end]))) | |
| 258 | y′=reshape(y, prod(size(y))) | |
| 259 | ||
| 260 | if add | |
| 261 | @simd for i = 1:length(y′) | |
| 262 | @inbounds y′[i] += dot(@view(u′[:, i]), @view(vtmp′[:, i])) | |
| 263 | end | |
| 264 | else | |
| 265 | @simd for i = 1:length(y′) | |
| 266 | @inbounds y′[i] = dot(@view(u′[:, i]), @view(vtmp′[:, i])) | |
| 267 | end | |
| 268 | end | |
| 269 | end | |
| 270 | ||
| 271 | function pointwise_gradiprod_2d!(y::Image, vtmp::Gradient, | |
| 272 | u::DisplacementConstant, b::Image; | |
| 273 | add = false) | |
| 274 | ∇₂c!(vtmp, b) | |
| 275 | ||
| 276 | vtmp′=reshape(vtmp, (size(vtmp, 1), prod(size(vtmp)[2:end]))) | |
| 277 | y′=reshape(y, prod(size(y))) | |
| 278 | ||
| 279 | if add | |
| 280 | @simd for i = 1:length(y′) | |
| 281 | @inbounds y′[i] += dot(u, @view(vtmp′[:, i])) | |
| 282 | end | |
| 283 | else | |
| 284 | @simd for i = 1:length(y′) | |
| 285 | @inbounds y′[i] = dot(u, @view(vtmp′[:, i])) | |
| 286 | end | |
| 287 | end | |
| 288 | end | |
| 289 | ||
| 290 | # ∇b ⋅ y | |
| 291 | function pointwise_gradiprod_2dᵀ!(u::DisplacementFull, y::Image, b::Image) | |
| 292 | ∇₂c!(u, b) | |
| 293 | ||
| 294 | u′=reshape(u, (size(u, 1), prod(size(u)[2:end]))) | |
| 295 | y′=reshape(y, prod(size(y))) | |
| 296 | ||
| 297 | @simd for i=1:length(y′) | |
| 298 | @inbounds @. u′[:, i] *= y′[i] | |
| 299 | end | |
| 300 | end | |
| 301 | ||
| 302 | function pointwise_gradiprod_2dᵀ!(u::DisplacementConstant, y::Image, b::Image) | |
| 303 | @assert(size(y)==size(b) && size(u)==(2,)) | |
| 304 | u .= 0 | |
| 305 | ∇₂cfold!(b, nothing) do g, st, (i, j) | |
| 306 | @inbounds u .+= g.*y[i, j] | |
| 307 | return st | |
| 308 | end | |
| 309 | # Reweight to be with respect to 𝟙^*𝟙 inner product. | |
| 310 | u ./= prod(size(b)) | |
| 311 | end | |
| 312 | ||
| 313 | mutable struct ConstantDisplacementHornSchunckData | |
| 314 | M₀::Array{Float64,2} | |
| 315 | z::Array{Float64,1} | |
| 316 | Mv::Array{Float64,2} | |
| 317 | av::Array{Float64,1} | |
| 318 | cv::Float64 | |
| 319 | ||
| 320 | function ConstantDisplacementHornSchunckData() | |
| 321 | return new(zeros(2, 2), zeros(2), zeros(2,2), zeros(2), 0) | |
| 322 | end | |
| 323 | end | |
| 324 | ||
| 325 | # For DisplacementConstant, for the simple prox step | |
| 326 | # | |
| 327 | # (1) argmin_u 1/(2τ)|u-ũ|^2 + (θ/2)|b⁺-b+<<u-ŭ,∇b>>|^2 + (λ/2)|u-ŭ|^2, | |
| 328 | # | |
| 329 | # construct matrix M₀ and vector z such that we can solve u from | |
| 330 | # | |
| 331 | # (2) (I/τ+M₀)u = M₀ŭ + ũ/τ - z | |
| 332 | # | |
| 333 | # Note that the problem | |
| 334 | # | |
| 335 | # argmin_u 1/(2τ)|u-ũ|^2 + (θ/2)|b⁺-b+<<u-ŭ,∇b>>|^2 + (λ/2)|u-ŭ|^2 | |
| 336 | # + (θ/2)|b⁺⁺-b⁺+<<uʹ-u,∇b⁺>>|^2 + (λ/2)|u-uʹ|^2 | |
| 337 | # | |
| 338 | # has with respect to u the system | |
| 339 | # | |
| 340 | # (I/τ+M₀+M₀ʹ)u = M₀ŭ + M₀ʹuʹ + ũ/τ - z + zʹ, | |
| 341 | # | |
| 342 | # where the primed variables correspond to (2) for (1) for uʹ in place of u: | |
| 343 | # | |
| 344 | # argmin_uʹ 1/(2τ)|uʹ-ũʹ|^2 + (θ/2)|b⁺⁺-b⁺+<<uʹ-u,∇b⁺>>|^2 + (λ/2)|uʹ-u|^2 | |
| 345 | # | |
| 346 | function horn_schunck_reg_prox_op!(hs::ConstantDisplacementHornSchunckData, | |
| 347 | bnext::Image, b::Image, θ, λ, T) | |
| 348 | @assert(size(b)==size(bnext)) | |
| 349 | w = prod(size(b)) | |
| 350 | z = hs.z | |
| 351 | cv = 0 | |
| 352 | # Factors of symmetric matrix [a c; c d] | |
| 353 | a, c, d = 0.0, 0.0, 0.0 | |
| 354 | # This used to use ∇₂cfold but it is faster to allocate temporary | |
| 355 | # storage for the full gradient due to probably better memory and SIMD | |
| 356 | # instruction usage. | |
| 357 | g = zeros(2, size(b)...) | |
| 358 | ∇₂c!(g, b) | |
| 359 | @inbounds for i=1:size(b, 1) | |
| 360 | for j=1:size(b, 2) | |
| 361 | δ = bnext[i,j]-b[i,j] | |
| 362 | @. z += g[:,i,j]*δ | |
| 363 | cv += δ*δ | |
| 364 | a += g[1,i,j]*g[1,i,j] | |
| 365 | c += g[1,i,j]*g[2,i,j] | |
| 366 | d += g[2,i,j]*g[2,i,j] | |
| 367 | end | |
| 368 | end | |
| 369 | w₀ = λ | |
| 370 | w₂ = θ/w | |
| 371 | aʹ = w₀ + w₂*a | |
| 372 | cʹ = w₂*c | |
| 373 | dʹ = w₀ + w₂*d | |
| 374 | hs.M₀ .= [aʹ cʹ; cʹ dʹ] | |
| 375 | hs.Mv .= [w*λ+θ*a θ*c; θ*c w*λ+θ*d] | |
| 376 | hs.cv = cv*θ | |
| 377 | hs.av .= hs.z.*θ | |
| 378 | hs.z .*= w₂/T | |
| 379 | end | |
| 380 | ||
| 381 | # Solve the 2D system (I/τ+M₀)u = z | |
| 382 | @inline function mldivide_step_plus_sym2x2!(u, M₀, z, τ) | |
| 383 | a = 1/τ+M₀[1, 1] | |
| 384 | c = M₀[1, 2] | |
| 385 | d = 1/τ+M₀[2, 2] | |
| 386 | u .= ([d -c; -c a]*z)./(a*d-c*c) | |
| 387 | end | |
| 388 | ||
| 389 | function horn_schunck_reg_prox!(u::DisplacementConstant, bnext::Image, b::Image, | |
| 390 | θ, λ, T, τ) | |
| 391 | hs=ConstantDisplacementHornSchunckData() | |
| 392 | horn_schunck_reg_prox_op!(hs, bnext, b, θ, λ, T) | |
| 393 | mldivide_step_plus_sym2x2!(u, hs.M₀, (u./τ)-hs.z, τ) | |
| 394 | end | |
| 395 | ||
| 396 | function flow_grad!(x::Image, vtmp::Gradient, u::Displacement; δ=nothing) | |
| 397 | if !isnothing(δ) | |
| 398 | u = δ.*u | |
| 399 | end | |
| 400 | pointwise_gradiprod_2d!(x, vtmp, u, x; add=true) | |
| 401 | end | |
| 402 | ||
| 403 | # Error b-b_prev+⟨⟨u, ∇b⟩⟩ for Horn–Schunck type penalisation | |
| 404 | function linearised_optical_flow_error(u::Displacement, b::Image, b_prev::Image) | |
| 405 | imdim = size(b) | |
| 406 | vtmp = zeros(2, imdim...) | |
| 407 | tmp = b-b_prev | |
| 408 | pointwise_gradiprod_2d!(tmp, vtmp, u, b_prev; add=true) | |
| 409 | return tmp | |
| 410 | end | |
| 411 | ||
| 412 | ############################################## | |
| 413 | # Helper to smooth data for Horn–Schunck term | |
| 414 | ############################################## | |
| 415 | ||
| 416 | function filter_hs(b, b_next, b_next_filt, kernel) | |
| 417 | if kernel==nothing | |
| 418 | f = x -> x | |
| 419 | else | |
| 420 | f = x -> simple_imfilter(x, kernel; threads=true) | |
| 421 | end | |
| 422 | ||
| 423 | # We already filtered b in the previous step (b_next in that step) | |
| 424 | b_filt = b_next_filt==nothing ? f(b) : b_next_filt | |
| 425 | b_next_filt = f(b_next) | |
| 426 | ||
| 427 | return b_filt, b_next_filt | |
| 428 | end | |
| 429 | ||
| 430 | end # Module |