Blender V4.3
trklt_region_tracker.cc
Go to the documentation of this file.
1// Copyright (c) 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"
28
29namespace libmv {
30
31// TODO(keir): Switch this to use the smarter LM loop like in ESM.
32
33// Computes U and e from the Ud = e equation (number 14) from the paper.
34static void ComputeTrackingEquation(const Array3Df& image_and_gradient1,
35 const Array3Df& image_and_gradient2,
36 double x1,
37 double y1,
38 double x2,
39 double y2,
40 int half_width,
41 double lambda,
42 Mat2f* U,
43 Vec2f* e) {
44 Mat2f A, B, C, D;
45 A = B = C = D = Mat2f::Zero();
46
47 Vec2f R, S, V, W;
48 R = S = V = W = Vec2f::Zero();
49
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
57 float I = SampleLinear(image_and_gradient1, yy1, xx1, 0);
58 float J = SampleLinear(image_and_gradient2, yy2, xx2, 0);
59
60 Vec2f gI, gJ;
61 gI << SampleLinear(image_and_gradient1, yy1, xx1, 1),
62 SampleLinear(image_and_gradient1, yy1, xx1, 2);
63 gJ << SampleLinear(image_and_gradient2, yy2, xx2, 1),
64 SampleLinear(image_and_gradient2, yy2, xx2, 2);
65
66 // Equation 15 from the paper.
67 A += gI * gI.transpose();
68 B += gI * gJ.transpose();
69 C += gJ * gJ.transpose();
70 R += I * gI;
71 S += J * gI;
72 V += I * gJ;
73 W += J * gJ;
74 }
75 }
76
77 // In the paper they show a D matrix, but it is just B transpose, so use that
78 // instead of explicitly computing D.
79 Mat2f Di = B.transpose().inverse();
80
81 // Equation 14 from the paper.
82 *U = A * Di * C + lambda * Di * C - 0.5 * B;
83 *e = (A + lambda * Mat2f::Identity()) * Di * (V - W) + 0.5 * (S - R);
84}
85
86static bool RegionIsInBounds(const FloatImage& image1,
87 double x,
88 double y,
89 int half_window_size) {
90 // Check the minimum coordinates.
91 int min_x = floor(x) - half_window_size - 1;
92 int min_y = floor(y) - half_window_size - 1;
93 if (min_x < 0.0 || min_y < 0.0) {
94 return false;
95 }
96
97 // Check the maximum coordinates.
98 int max_x = ceil(x) + half_window_size + 1;
99 int max_y = ceil(y) + half_window_size + 1;
100 if (max_x > image1.cols() || max_y > image1.rows()) {
101 return false;
102 }
103
104 // Ok, we're good.
105 return true;
106}
107
109 const FloatImage& image2,
110 double x1,
111 double y1,
112 double* x2,
113 double* y2) const {
114 if (!RegionIsInBounds(image1, x1, y1, half_window_size)) {
115 LG << "Fell out of image1's window with x1=" << x1 << ", y1=" << y1
116 << ", hw=" << half_window_size << ".";
117 return false;
118 }
119
120 Array3Df image_and_gradient1;
121 Array3Df image_and_gradient2;
122 BlurredImageAndDerivativesChannels(image1, sigma, &image_and_gradient1);
123 BlurredImageAndDerivativesChannels(image2, sigma, &image_and_gradient2);
124
125 int i;
126 Vec2f d = Vec2f::Zero();
127 for (i = 0; i < max_iterations; ++i) {
128 // Check that the entire image patch is within the bounds of the images.
129 if (!RegionIsInBounds(image2, *x2, *y2, half_window_size)) {
130 LG << "Fell out of image2's window with x2=" << *x2 << ", y2=" << *y2
131 << ", hw=" << half_window_size << ".";
132 return false;
133 }
134
135 // Compute gradient matrix and error vector.
136 Mat2f U;
137 Vec2f e;
138 ComputeTrackingEquation(image_and_gradient1,
139 image_and_gradient2,
140 x1,
141 y1,
142 *x2,
143 *y2,
145 lambda,
146 &U,
147 &e);
148
149 // Solve the linear system for the best update to x2 and y2.
150 d = U.lu().solve(e);
151
152 // Update the position with the solved displacement.
153 *x2 += d[0];
154 *y2 += d[1];
155
156 // Check for the quality of the solution, but not until having already
157 // updated the position with our best estimate. The reason to do the update
158 // anyway is that the user already knows the position is bad, so we may as
159 // well try our best.
160 float determinant = U.determinant();
162 // The determinant, which indicates the trackiness of the point, is too
163 // small, so fail out.
164 LG << "Determinant " << determinant << " is too small; failing tracking.";
165 return false;
166 }
167 LG << "x=" << *x2 << ", y=" << *y2 << ", dx=" << d[0] << ", dy=" << d[1]
168 << ", det=" << determinant;
169
170 // If the update is small, then we probably found the target.
171 if (d.squaredNorm() < min_update_squared_distance) {
172 LG << "Successful track in " << i << " iterations.";
173 return true;
174 }
175 }
176 // Getting here means we hit max iterations, so tracking failed.
177 LG << "Too many iterations; max is set to " << max_iterations << ".";
178 return false;
179}
180
181} // namespace libmv
#define D
#define C
Definition RandGen.cpp:29
#define U
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
#define A
unsigned int U
Definition btGjkEpa3.h:78
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 float2 fabs(const float2 a)
ccl_device_inline float3 ceil(const float3 a)
#define B
#define R
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)
Eigen::Matrix< float, 2, 2 > Mat2f
Definition numeric.h:79
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
Eigen::Vector2f Vec2f
Definition numeric.h:125
#define I
virtual bool Track(const FloatImage &image1, const FloatImage &image2, double x1, double y1, double *x2, double *y2) const
CCL_NAMESPACE_BEGIN struct Window V