Blender V4.3
klt_region_tracker.cc
Go to the documentation of this file.
1// Copyright (c) 2007, 2008, 2009, 2011 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
22
24#include "libmv/image/image.h"
25#include "libmv/image/sample.h"
27
28namespace libmv {
29
30// Compute the gradient matrix noted by Z and the error vector e. See Good
31// Features to Track.
32//
33// TODO(keir): The calls to SampleLinear() do boundary checking that should
34// instead happen outside the loop. Since this is the innermost loop, the extra
35// bounds checking hurts performance.
36static void ComputeTrackingEquation(const Array3Df& image_and_gradient1,
37 const Array3Df& image_and_gradient2,
38 double x1,
39 double y1,
40 double x2,
41 double y2,
42 int half_width,
43 float* gxx,
44 float* gxy,
45 float* gyy,
46 float* ex,
47 float* ey) {
48 *gxx = *gxy = *gyy = 0;
49 *ex = *ey = 0;
50 for (int r = -half_width; r <= half_width; ++r) {
51 for (int c = -half_width; c <= half_width; ++c) {
52 float xx1 = x1 + c;
53 float yy1 = y1 + r;
54 float xx2 = x2 + c;
55 float yy2 = y2 + r;
56 float I = SampleLinear(image_and_gradient1, yy1, xx1, 0);
57 float J = SampleLinear(image_and_gradient2, yy2, xx2, 0);
58 float gx = SampleLinear(image_and_gradient2, yy2, xx2, 1);
59 float gy = SampleLinear(image_and_gradient2, yy2, xx2, 2);
60 *gxx += gx * gx;
61 *gxy += gx * gy;
62 *gyy += gy * gy;
63 *ex += (I - J) * gx;
64 *ey += (I - J) * gy;
65 }
66 }
67}
68
69static bool RegionIsInBounds(const FloatImage& image1,
70 double x,
71 double y,
72 int half_window_size) {
73 // Check the minimum coordinates.
74 int min_x = floor(x) - half_window_size - 1;
75 int min_y = floor(y) - half_window_size - 1;
76 if (min_x < 0.0 || min_y < 0.0) {
77 return false;
78 }
79
80 // Check the maximum coordinates.
81 int max_x = ceil(x) + half_window_size + 1;
82 int max_y = ceil(y) + half_window_size + 1;
83 if (max_x > image1.cols() || max_y > image1.rows()) {
84 return false;
85 }
86
87 // Ok, we're good.
88 return true;
89}
90
92 const FloatImage& image2,
93 double x1,
94 double y1,
95 double* x2,
96 double* y2) const {
97 if (!RegionIsInBounds(image1, x1, y1, half_window_size)) {
98 LG << "Fell out of image1's window with x1=" << x1 << ", y1=" << y1
99 << ", hw=" << half_window_size << ".";
100 return false;
101 }
102
103 Array3Df image_and_gradient1;
104 Array3Df image_and_gradient2;
105 BlurredImageAndDerivativesChannels(image1, sigma, &image_and_gradient1);
106 BlurredImageAndDerivativesChannels(image2, sigma, &image_and_gradient2);
107
108 int i;
109 float dx = 0, dy = 0;
110 for (i = 0; i < max_iterations; ++i) {
111 // Check that the entire image patch is within the bounds of the images.
112 if (!RegionIsInBounds(image2, *x2, *y2, half_window_size)) {
113 LG << "Fell out of image2's window with x2=" << *x2 << ", y2=" << *y2
114 << ", hw=" << half_window_size << ".";
115 return false;
116 }
117
118 // Compute gradient matrix and error vector.
119 float gxx, gxy, gyy, ex, ey;
120 ComputeTrackingEquation(image_and_gradient1,
121 image_and_gradient2,
122 x1,
123 y1,
124 *x2,
125 *y2,
127 &gxx,
128 &gxy,
129 &gyy,
130 &ex,
131 &ey);
132
133 // Solve the tracking equation
134 //
135 // [gxx gxy] [dx] = [ex]
136 // [gxy gyy] [dy] = [ey]
137 //
138 // for dx and dy. Borrowed from Stan Birchfield's KLT implementation.
139 float determinant = gxx * gyy - gxy * gxy;
140 dx = (gyy * ex - gxy * ey) / determinant;
141 dy = (gxx * ey - gxy * ex) / determinant;
142
143 // Update the position with the solved displacement.
144 *x2 += dx;
145 *y2 += dy;
146
147 // Check for the quality of the solution, but not until having already
148 // updated the position with our best estimate. The reason to do the update
149 // anyway is that the user already knows the position is bad, so we may as
150 // well try our best.
152 // The determinant, which indicates the trackiness of the point, is too
153 // small, so fail out.
154 LG << "Determinant " << determinant << " is too small; failing tracking.";
155 return false;
156 }
157 LG << "x=" << *x2 << ", y=" << *y2 << ", dx=" << dx << ", dy=" << dy
158 << ", det=" << determinant;
159
160 // If the update is small, then we probably found the target.
161 if (dx * dx + dy * dy < min_update_squared_distance) {
162 LG << "Successful track in " << i << " iterations.";
163 return true;
164 }
165 }
166 // Getting here means we hit max iterations, so tracking failed.
167 LG << "Too many iterations; max is set to " << max_iterations << ".";
168 return false;
169}
170
171} // namespace libmv
btScalar determinant() const
Return the determinant of the matrix.
3D array (row, column, channel).
Definition array_nd.h:332
int rows() const
Definition array_nd.h:351
int cols() const
Definition array_nd.h:352
#define LG
ccl_device_inline float2 floor(const float2 a)
ccl_device_inline float3 ceil(const float3 a)
static void ComputeTrackingEquation(const Array3Df &image_and_gradient1, const Array3Df &image_and_gradient2, double x1, double y1, double x2, double y2, int half_width, float *gxx, float *gxy, float *gyy, float *ex, float *ey)
static bool RegionIsInBounds(const FloatImage &image1, double x, double y, int half_window_size)
T SampleLinear(const Array3D< T > &image, float y, float x, int v=0)
Linear interpolation.
void BlurredImageAndDerivativesChannels(const Array3Df &in, double sigma, Array3Df *blurred_and_gradxy)
Definition convolve.cc:233
#define I
virtual bool Track(const FloatImage &image1, const FloatImage &image2, double x1, double y1, double *x2, double *y2) const