Mon, 23 Dec 2019 21:30:38 +0200
Short channel
| 0 | 1 | ###################################### |
| 2 | # Image subpixel accuracy translation | |
| 3 | ###################################### | |
| 4 | ||
|
7
ab7d59b47140
Add __precompile__() for whatever it is worth
Tuomo Valkonen <tuomov@iki.fi>
parents:
6
diff
changeset
|
5 | __precompile__() |
|
ab7d59b47140
Add __precompile__() for whatever it is worth
Tuomo Valkonen <tuomov@iki.fi>
parents:
6
diff
changeset
|
6 | |
| 0 | 7 | module Translate |
| 8 | ||
| 9 | ########## | |
| 10 | # Exports | |
| 11 | ########## | |
| 12 | ||
| 13 | export interpolate2d, | |
| 14 | interpolate2d_quadrants, | |
| 15 | extract_subimage!, | |
| 16 | translate_image!, | |
| 17 | DisplacementFull, | |
| 18 | DisplacementConstant, | |
| 19 | Displacement, | |
| 20 | Image | |
| 21 | ||
| 22 | ################## | |
| 23 | # Types | |
| 24 | ################## | |
| 25 | ||
| 26 | # Two different types of displacement data supported: | |
| 27 | # a) given in each pixel | |
| 28 | # b) constant in space | |
| 29 | Image = Array{Float64,2} | |
| 30 | DisplacementFull = Array{Float64,3} | |
| 31 | DisplacementConstant = Array{Float64,1} | |
| 32 | Displacement = Union{DisplacementFull,DisplacementConstant} | |
| 33 | ||
| 34 | ############################# | |
| 35 | # Base interpolation routine | |
| 36 | ############################# | |
| 37 | ||
| 38 | @inline function interpolate2d_quadrants(v, (x, y)) | |
| 39 | (m, n) = size(v) | |
| 40 | clipx = xʹ -> max(1, min(xʹ, m)) | |
| 41 | clipy = yʹ -> max(1, min(yʹ, n)) | |
| 42 | ||
| 43 | xfℤ = clipx(floor(Int, x)) | |
| 44 | xcℤ = clipx(ceil(Int, x)) | |
| 45 | yfℤ = clipy(floor(Int, y)) | |
| 46 | ycℤ = clipy(ceil(Int, y)) | |
| 47 | ||
| 48 | xf = convert(Float64, xfℤ) | |
| 49 | xc = convert(Float64, xcℤ) | |
| 50 | yf = convert(Float64, yfℤ) | |
| 51 | yc = convert(Float64, ycℤ) | |
| 52 | xm = (xf+xc)/2 | |
| 53 | ym = (yf+yc)/2 | |
| 54 | ||
| 55 | vff = @inbounds v[xfℤ, yfℤ] | |
| 56 | vfc = @inbounds v[xfℤ, ycℤ] | |
| 57 | vcf = @inbounds v[xcℤ, yfℤ] | |
| 58 | vcc = @inbounds v[xcℤ, ycℤ] | |
| 59 | vmm = (vff+vfc+vcf+vcc)/4 | |
| 60 | ||
| 61 | if xfℤ==xcℤ | |
| 62 | if yfℤ==ycℤ | |
| 63 | # Completely degenerate case | |
| 64 | v = vmm | |
| 65 | else | |
| 66 | # Degenerate x | |
| 67 | v = vff+(y-yf)/(yc-yf)*(vfc-vff) | |
| 68 | end | |
| 69 | elseif yfℤ==ycℤ | |
| 70 | # Degenerate y | |
| 71 | v = vff + (x-xf)/(xc-xf)*(vcf-vff) | |
| 72 | elseif y-ym ≥ x-xm | |
| 73 | # top-left half | |
| 74 | if (y-ym) + (x-xm) ≥ 0 | |
| 75 | # top quadrant | |
| 76 | v = vfc + (x-xf)/(xc-xf)*(vcc-vfc) + (y-yc)/(ym-yc)*(vmm-(vcc+vfc)/2) | |
| 77 | else | |
| 78 | # left quadrant | |
| 79 | v = vff + (y-yf)/(yc-yf)*(vfc-vff) + (x-xf)/(xm-xf)*(vmm-(vfc+vff)/2) | |
| 80 | end | |
| 81 | else | |
| 82 | # bottom-left half | |
| 83 | if (y-ym) + (x-xm) ≥ 0 | |
| 84 | # right quadrant | |
| 85 | v = vcf + (y-yf)/(yc-yf)*(vcc-vcf) + (x-xc)/(xm-xc)*(vmm-(vcc+vcf)/2) | |
| 86 | else | |
| 87 | # bottom quadrant | |
| 88 | v = vff + (x-xf)/(xc-xf)*(vcf-vff) + (y-yf)/(ym-yf)*(vmm-(vcf+vff)/2) | |
| 89 | end | |
| 90 | end | |
| 91 | ||
| 92 | return v | |
| 93 | end | |
| 94 | ||
| 95 | ############## | |
| 96 | # Translation | |
| 97 | ############## | |
| 98 | ||
| 17 | 99 | function translate_image!(x, z, u::DisplacementFull) |
| 0 | 100 | @assert(size(u, 1)==2 && size(x)==size(u)[2:end] && size(x)==size(z)) |
| 101 | ||
| 17 | 102 | @inbounds Threads.@threads for i=1:size(x, 1) |
| 0 | 103 | @simd for j=1:size(x, 2) |
| 104 | pt = (i - u[1, i, j], j - u[2, i, j]) | |
|
6
cd3ca6286daa
For inlining to work we cannot do function assignments
Tuomo Valkonen <tuomov@iki.fi>
parents:
5
diff
changeset
|
105 | x[i, j] = interpolate2d_quadrants(z, pt) |
| 0 | 106 | end |
| 107 | end | |
| 108 | end | |
| 109 | ||
| 17 | 110 | function translate_image!(x, z, u::DisplacementConstant) |
| 0 | 111 | @assert(size(u)==(2,) && size(x)==size(z)) |
| 112 | ||
| 20 | 113 | a, b = u[1], u[2] |
| 114 | ||
| 17 | 115 | @inbounds Threads.@threads for i=1:size(x, 1) |
| 0 | 116 | @simd for j=1:size(x, 2) |
| 20 | 117 | x[i, j] = interpolate2d_quadrants(z, (i - a, j - b)) |
| 0 | 118 | end |
| 119 | end | |
| 120 | end | |
| 121 | ||
| 122 | ###################### | |
| 123 | # Subimage extraction | |
| 124 | ###################### | |
| 125 | ||
| 17 | 126 | function extract_subimage!(b, im, v::DisplacementConstant) |
| 0 | 127 | (imx, imy) = size(im) |
| 128 | (bx, by) = size(b) | |
| 129 | ||
| 130 | # Translation from target to source coordinates | |
| 2 | 131 | vxʹ = (imx-bx)/2 - v[1] |
| 132 | vyʹ = (imy-by)/2 - v[2] | |
| 0 | 133 | |
| 134 | # Target image indices within source image | |
| 23 | 135 | px = max(ceil(Int, max(1, vxʹ + 1) - vxʹ), 1) |
| 136 | py = max(ceil(Int, max(1, vyʹ + 1) - vyʹ), 1) | |
| 137 | qx = min(floor(Int, min(imx, vxʹ + bx) - vxʹ), bx) | |
| 138 | qy = min(floor(Int, min(imy, vyʹ + by) - vyʹ), by) | |
| 0 | 139 | |
| 20 | 140 | @inbounds begin |
| 141 | b[1:px-1, :] .= 0 | |
| 142 | b[qx+1:end, :] .= 0 | |
| 0 | 143 | |
| 20 | 144 | Threads.@threads for i=px:qx |
| 145 | b[i, 1:py-1] .= 0 | |
| 146 | b[i, qy+1:end] .= 0 | |
| 147 | @simd for j=py:qy | |
| 148 | b[i, j] = interpolate2d_quadrants(im, (i+vxʹ, j+vyʹ)) | |
| 149 | end | |
| 0 | 150 | end |
| 151 | end | |
| 152 | end | |
| 153 | ||
|
5
29b38780d52b
Add precompilation hints. Do they help or not?
Tuomo Valkonen <tuomov@iki.fi>
parents:
2
diff
changeset
|
154 | ##################################################### |
|
29b38780d52b
Add precompilation hints. Do they help or not?
Tuomo Valkonen <tuomov@iki.fi>
parents:
2
diff
changeset
|
155 | # Precompilation hints to speed up compilation time |
|
29b38780d52b
Add precompilation hints. Do they help or not?
Tuomo Valkonen <tuomov@iki.fi>
parents:
2
diff
changeset
|
156 | # for projects depending on this package (hopefully). |
|
29b38780d52b
Add precompilation hints. Do they help or not?
Tuomo Valkonen <tuomov@iki.fi>
parents:
2
diff
changeset
|
157 | ###################################################### |
|
29b38780d52b
Add precompilation hints. Do they help or not?
Tuomo Valkonen <tuomov@iki.fi>
parents:
2
diff
changeset
|
158 | |
|
29b38780d52b
Add precompilation hints. Do they help or not?
Tuomo Valkonen <tuomov@iki.fi>
parents:
2
diff
changeset
|
159 | precompile(translate_image!, (Array{Float64,2}, Array{Float64,2}, Array{Float64,1})) |
|
29b38780d52b
Add precompilation hints. Do they help or not?
Tuomo Valkonen <tuomov@iki.fi>
parents:
2
diff
changeset
|
160 | precompile(translate_image!, (Array{Float64,2}, Array{Float64,2}, Array{Float64,3})) |
|
29b38780d52b
Add precompilation hints. Do they help or not?
Tuomo Valkonen <tuomov@iki.fi>
parents:
2
diff
changeset
|
161 | precompile(extract_subimage!, (Array{Float64,2}, Array{Float64,2}, Array{Float64,1})) |
|
29b38780d52b
Add precompilation hints. Do they help or not?
Tuomo Valkonen <tuomov@iki.fi>
parents:
2
diff
changeset
|
162 | |
| 0 | 163 | end |