Mon, 18 Nov 2019 17:37:23 -0500
Added missing main file
0 | 1 | ###################################### |
2 | # Image subpixel accuracy translation | |
3 | ###################################### | |
4 | ||
5 | module Translate | |
6 | ||
7 | ########## | |
8 | # Exports | |
9 | ########## | |
10 | ||
11 | export interpolate2d, | |
12 | interpolate2d_quadrants, | |
13 | extract_subimage!, | |
14 | translate_image!, | |
15 | DisplacementFull, | |
16 | DisplacementConstant, | |
17 | Displacement, | |
18 | Image | |
19 | ||
20 | ################## | |
21 | # Types | |
22 | ################## | |
23 | ||
24 | # Two different types of displacement data supported: | |
25 | # a) given in each pixel | |
26 | # b) constant in space | |
27 | Image = Array{Float64,2} | |
28 | DisplacementFull = Array{Float64,3} | |
29 | DisplacementConstant = Array{Float64,1} | |
30 | Displacement = Union{DisplacementFull,DisplacementConstant} | |
31 | ||
32 | ############################# | |
33 | # Base interpolation routine | |
34 | ############################# | |
35 | ||
36 | @inline function interpolate2d_quadrants(v, (x, y)) | |
37 | (m, n) = size(v) | |
38 | clipx = xʹ -> max(1, min(xʹ, m)) | |
39 | clipy = yʹ -> max(1, min(yʹ, n)) | |
40 | ||
41 | xfℤ = clipx(floor(Int, x)) | |
42 | xcℤ = clipx(ceil(Int, x)) | |
43 | yfℤ = clipy(floor(Int, y)) | |
44 | ycℤ = clipy(ceil(Int, y)) | |
45 | ||
46 | xf = convert(Float64, xfℤ) | |
47 | xc = convert(Float64, xcℤ) | |
48 | yf = convert(Float64, yfℤ) | |
49 | yc = convert(Float64, ycℤ) | |
50 | xm = (xf+xc)/2 | |
51 | ym = (yf+yc)/2 | |
52 | ||
53 | vff = @inbounds v[xfℤ, yfℤ] | |
54 | vfc = @inbounds v[xfℤ, ycℤ] | |
55 | vcf = @inbounds v[xcℤ, yfℤ] | |
56 | vcc = @inbounds v[xcℤ, ycℤ] | |
57 | vmm = (vff+vfc+vcf+vcc)/4 | |
58 | ||
59 | if xfℤ==xcℤ | |
60 | if yfℤ==ycℤ | |
61 | # Completely degenerate case | |
62 | v = vmm | |
63 | else | |
64 | # Degenerate x | |
65 | v = vff+(y-yf)/(yc-yf)*(vfc-vff) | |
66 | end | |
67 | elseif yfℤ==ycℤ | |
68 | # Degenerate y | |
69 | v = vff + (x-xf)/(xc-xf)*(vcf-vff) | |
70 | elseif y-ym ≥ x-xm | |
71 | # top-left half | |
72 | if (y-ym) + (x-xm) ≥ 0 | |
73 | # top quadrant | |
74 | v = vfc + (x-xf)/(xc-xf)*(vcc-vfc) + (y-yc)/(ym-yc)*(vmm-(vcc+vfc)/2) | |
75 | else | |
76 | # left quadrant | |
77 | v = vff + (y-yf)/(yc-yf)*(vfc-vff) + (x-xf)/(xm-xf)*(vmm-(vfc+vff)/2) | |
78 | end | |
79 | else | |
80 | # bottom-left half | |
81 | if (y-ym) + (x-xm) ≥ 0 | |
82 | # right quadrant | |
83 | v = vcf + (y-yf)/(yc-yf)*(vcc-vcf) + (x-xc)/(xm-xc)*(vmm-(vcc+vcf)/2) | |
84 | else | |
85 | # bottom quadrant | |
86 | v = vff + (x-xf)/(xc-xf)*(vcf-vff) + (y-yf)/(ym-yf)*(vmm-(vcf+vff)/2) | |
87 | end | |
88 | end | |
89 | ||
90 | return v | |
91 | end | |
92 | ||
93 | interpolate2d = interpolate2d_quadrants | |
94 | ||
95 | ############## | |
96 | # Translation | |
97 | ############## | |
98 | ||
99 | @polly function translate_image!(x, z, u::DisplacementFull) | |
100 | @assert(size(u, 1)==2 && size(x)==size(u)[2:end] && size(x)==size(z)) | |
101 | ||
102 | @inbounds @simd for i=1:size(x, 1) | |
103 | @simd for j=1:size(x, 2) | |
104 | pt = (i - u[1, i, j], j - u[2, i, j]) | |
105 | x[i, j] = interpolate2d(z, pt) | |
106 | end | |
107 | end | |
108 | end | |
109 | ||
110 | @polly function translate_image!(x, z, u::DisplacementConstant) | |
111 | @assert(size(u)==(2,) && size(x)==size(z)) | |
112 | ||
113 | @inbounds @simd for i=1:size(x, 1) | |
114 | @simd for j=1:size(x, 2) | |
115 | pt = (i - u[1], j - u[2]) | |
116 | x[i, j] = interpolate2d(z, pt) | |
117 | end | |
118 | end | |
119 | end | |
120 | ||
121 | ###################### | |
122 | # Subimage extraction | |
123 | ###################### | |
124 | ||
125 | @polly function extract_subimage!(b, im, v::DisplacementConstant) | |
126 | (imx, imy) = size(im) | |
127 | (bx, by) = size(b) | |
128 | ||
129 | # Translation from target to source coordinates | |
2 | 130 | vxʹ = (imx-bx)/2 - v[1] |
131 | vyʹ = (imy-by)/2 - v[2] | |
0 | 132 | |
133 | # Target image indices within source image | |
134 | px = ceil(Int, max(1, vxʹ + 1) - vxʹ) | |
135 | py = ceil(Int, max(1, vyʹ + 1) - vyʹ) | |
136 | qx = floor(Int, min(imx, vxʹ + bx) - vxʹ) | |
137 | qy = floor(Int, min(imy, vyʹ + by) - vyʹ) | |
138 | ||
139 | b .= 0 | |
140 | ||
141 | @inbounds @simd for i=px:qx | |
142 | for j=py:qy | |
143 | b[i, j] = interpolate2d(im, (i+vxʹ, j+vyʹ)) | |
144 | end | |
145 | end | |
146 | end | |
147 | ||
148 | end |