Planar tracking support for motion tracking
[blender.git] / extern / libmv / libmv / image / sample.h
1 // Copyright (c) 2007, 2008 libmv authors.
2 //
3 // Permission is hereby granted, free of charge, to any person obtaining a copy
4 // of this software and associated documentation files (the "Software"), to
5 // deal in the Software without restriction, including without limitation the
6 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 // sell copies of the Software, and to permit persons to whom the Software is
8 // furnished to do so, subject to the following conditions:
9 //
10 // The above copyright notice and this permission notice shall be included in
11 // all copies or substantial portions of the Software.
12 //
13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 // IN THE SOFTWARE.
20
21 #ifndef LIBMV_IMAGE_SAMPLE_H_
22 #define LIBMV_IMAGE_SAMPLE_H_
23
24 #include "libmv/image/image.h"
25
26 namespace libmv {
27
28 /// Nearest neighbor interpolation.
29 template<typename T>
30 inline T SampleNearest(const Array3D<T> &image,
31                        float y, float x, int v = 0) {
32   const int i = int(round(y));
33   const int j = int(round(x));
34   return image(i, j, v);
35 }
36
37 inline void LinearInitAxis(float x, int size,
38                            int *x1, int *x2,
39                            float *dx) {
40   const int ix = static_cast<int>(x);
41   if (ix < 0) {
42     *x1 = 0;
43     *x2 = 0;
44     *dx = 1.0;
45   } else if (ix > size - 2) {
46     *x1 = size - 1;
47     *x2 = size - 1;
48     *dx = 1.0;
49   } else {
50     *x1 = ix;
51     *x2 = ix + 1;
52     *dx = *x2 - x;
53   }
54 }
55
56 /// Linear interpolation.
57 template<typename T>
58 inline T SampleLinear(const Array3D<T> &image, float y, float x, int v = 0) {
59   int x1, y1, x2, y2;
60   float dx, dy;
61
62   // Take the upper left corner as integer pixel positions.
63   x -= 0.5;
64   y -= 0.5;
65
66   LinearInitAxis(y, image.Height(), &y1, &y2, &dy);
67   LinearInitAxis(x, image.Width(),  &x1, &x2, &dx);
68
69   const T im11 = image(y1, x1, v);
70   const T im12 = image(y1, x2, v);
71   const T im21 = image(y2, x1, v);
72   const T im22 = image(y2, x2, v);
73
74   return T(     dy  * ( dx * im11 + (1.0 - dx) * im12 ) +
75            (1 - dy) * ( dx * im21 + (1.0 - dx) * im22 ));
76 }
77
78 /// Linear interpolation, of all channels. The sample is assumed to have the
79 /// same size as the number of channels in image.
80 template<typename T>
81 inline void SampleLinear(const Array3D<T> &image, float y, float x, T *sample) {
82   int x1, y1, x2, y2;
83   float dx, dy;
84
85   // Take the upper left corner as integer pixel positions.
86   x -= 0.5;
87   y -= 0.5;
88
89   LinearInitAxis(y, image.Height(), &y1, &y2, &dy);
90   LinearInitAxis(x, image.Width(),  &x1, &x2, &dx);
91
92   for (int i = 0; i < image.Depth(); ++i) {
93     const T im11 = image(y1, x1, i);
94     const T im12 = image(y1, x2, i);
95     const T im21 = image(y2, x1, i);
96     const T im22 = image(y2, x2, i);
97
98     sample[i] = T(     dy  * ( dx * im11 + (1.0 - dx) * im12 ) +
99                   (1 - dy) * ( dx * im21 + (1.0 - dx) * im22 ));
100   }
101 }
102
103 // Downsample all channels by 2. If the image has odd width or height, the last
104 // row or column is ignored.
105 // FIXME(MatthiasF): this implementation shouldn't be in an interface file
106 inline void DownsampleChannelsBy2(const Array3Df &in, Array3Df *out) {
107   int height = in.Height() / 2;
108   int width = in.Width() / 2;
109   int depth = in.Depth();
110
111   out->Resize(height, width, depth);
112
113   // 2x2 box filter downsampling.
114   for (int r = 0; r < height; ++r) {
115     for (int c = 0; c < width; ++c) {
116       for (int k = 0; k < depth; ++k) {
117         (*out)(r, c, k) = (in(2 * r,     2 * c,     k) +
118                            in(2 * r + 1, 2 * c,     k) +
119                            in(2 * r,     2 * c + 1, k) +
120                            in(2 * r + 1, 2 * c + 1, k)) / 4.0f;
121       }
122     }
123   }
124 }
125
126 // Sample a region centered at x,y in image with size extending by half_width
127 // from x,y. Channels specifies the number of channels to sample from.
128 inline void SamplePattern(const FloatImage &image,
129                    double x, double y,
130                    int half_width,
131                    int channels,
132                    FloatImage *sampled) {
133   sampled->Resize(2 * half_width + 1, 2 * half_width + 1, channels);
134   for (int r = -half_width; r <= half_width; ++r) {
135     for (int c = -half_width; c <= half_width; ++c) {
136       for (int i = 0; i < channels; ++i) {
137         (*sampled)(r + half_width, c + half_width, i) =
138             SampleLinear(image, y + r, x + c, i);
139       }
140     }
141   }
142 }
143
144 }  // namespace libmv
145
146 #endif  // LIBMV_IMAGE_SAMPLE_H_