Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpTemplateTrackerZNCCInverseCompositional.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Template tracker.
32 *
33 * Authors:
34 * Amaury Dame
35 * Aurelien Yol
36 */
37#include <limits> // numeric_limits
38
39#include <visp3/core/vpImageFilter.h>
40#include <visp3/tt/vpTemplateTrackerZNCCInverseCompositional.h>
41
48
50{
53
54 for (unsigned int point = 0; point < templateSize; point++) {
55 int i = ptTemplate[point].y;
56 int j = ptTemplate[point].x;
57
58 ptTemplate[point].dW = new double[nbParam];
59
60 double dx = ptTemplate[point].dx;
61 double dy = ptTemplate[point].dy;
62
63 Warp->getdW0(i, j, dy, dx, ptTemplate[point].dW);
64 }
65 compoInitialised = true;
66}
67
69{
71
72 if (blur)
76
77 vpImage<double> dIxx, dIxy, dIyx, dIyy;
80
83
84 Warp->computeCoeff(p);
85 double Ic, dIcx = 0., dIcy = 0.;
86 double Iref;
87 int i, j;
88 double i2, j2;
89 int Nbpoint = 0;
90
91 double moyIref = 0;
92 double moyIc = 0;
93 double denom = 0;
94 double *tempt = new double[nbParam];
95
96 moydIrefdp.resize(nbParam);
97 moydIrefdp = 0;
98 vpMatrix moyd2Iref(nbParam, nbParam);
99 moyd2Iref = 0;
100
101 for (unsigned int point = 0; point < templateSize; point++) {
102 i = ptTemplate[point].y;
103 j = ptTemplate[point].x;
104 X1[0] = j;
105 X1[1] = i;
106 X2[0] = j;
107 X2[1] = i;
108
109 j2 = X2[0];
110 i2 = X2[1];
111
112 if ((i2 >= 0) && (j2 >= 0) && (i2 < I.getHeight() - 1) && (j2 < I.getWidth() - 1)) {
113 Iref = ptTemplate[point].val;
114
115 if (!blur)
116 Ic = I.getValue(i2, j2);
117 else
118 Ic = BI.getValue(i2, j2);
119
120 Nbpoint++;
121 moyIref += Iref;
122 moyIc += Ic;
123
124 for (unsigned int it = 0; it < nbParam; it++)
125 moydIrefdp[it] += ptTemplate[point].dW[it];
126
127 Warp->dWarp(X1, X2, p, dW);
128 for (unsigned int it = 0; it < nbParam; it++)
129 tempt[it] = dW[0][it] * dIcx + dW[1][it] * dIcy;
130 double d_Ixx = dIxx.getValue(i2, j2);
131 double d_Iyy = dIyy.getValue(i2, j2);
132 double d_Ixy = dIxy.getValue(i2, j2);
133
134 for (unsigned int it = 0; it < nbParam; it++)
135 for (unsigned int jt = 0; jt < nbParam; jt++) {
136 moyd2Iref[it][jt] += (dW[0][it] * (dW[0][jt] * d_Ixx + dW[1][jt] * d_Ixy) +
137 dW[1][it] * (dW[0][jt] * d_Ixy + dW[1][jt] * d_Iyy));
138 }
139 }
140 }
141
142 moyIref = moyIref / Nbpoint;
143 moydIrefdp = moydIrefdp / Nbpoint;
144 moyd2Iref = moyd2Iref / Nbpoint;
145 moyIc = moyIc / Nbpoint;
146 Hdesire = 0;
147 double covarIref = 0, covarIc = 0;
148 double sIcIref = 0;
149 vpColVector sIcdIref(nbParam);
150 sIcdIref = 0;
151 vpMatrix sIcd2Iref(nbParam, nbParam);
152 sIcd2Iref = 0;
153 vpMatrix sdIrefdIref(nbParam, nbParam);
154 sdIrefdIref = 0;
155 for (unsigned int point = 0; point < templateSize; point++) {
156 i = ptTemplate[point].y;
157 j = ptTemplate[point].x;
158 X1[0] = j;
159 X1[1] = i;
160 X2[0] = j;
161 X2[1] = i;
162
163 Warp->computeDenom(X1, p);
164
165 j2 = X2[0];
166 i2 = X2[1];
167
168 if ((i2 >= 0) && (j2 >= 0) && (i2 < I.getHeight() - 1) && (j2 < I.getWidth() - 1)) {
169 Iref = ptTemplate[point].val;
170
171 if (!blur)
172 Ic = I.getValue(i2, j2);
173 else
174 Ic = BI.getValue(i2, j2);
175
176 dIcx = dIx.getValue(i2, j2);
177 dIcy = dIy.getValue(i2, j2);
178
179 Warp->dWarp(X1, X2, p, dW);
180
181 for (unsigned int it = 0; it < nbParam; it++) {
182 tempt[it] = dW[0][it] * dIcx + dW[1][it] * dIcy;
183 }
184
185 double prodIc = (Ic - moyIc);
186
187 double d_Ixx = dIxx.getValue(i2, j2);
188 double d_Iyy = dIyy.getValue(i2, j2);
189 double d_Ixy = dIxy.getValue(i2, j2);
190
191 for (unsigned int it = 0; it < nbParam; it++) {
192 for (unsigned int jt = 0; jt < nbParam; jt++) {
193 sIcd2Iref[it][jt] += prodIc * (dW[0][it] * (dW[0][jt] * d_Ixx + dW[1][jt] * d_Ixy) +
194 dW[1][it] * (dW[0][jt] * d_Ixy + dW[1][jt] * d_Iyy) - moyd2Iref[it][jt]);
195 sdIrefdIref[it][jt] +=
196 (ptTemplate[point].dW[it] - moydIrefdp[it]) * (ptTemplate[point].dW[jt] - moydIrefdp[jt]);
197 }
198 }
199
200 for (unsigned int it = 0; it < nbParam; it++)
201 sIcdIref[it] += prodIc * (ptTemplate[point].dW[it] - moydIrefdp[it]);
202
203 covarIref += (Iref - moyIref) * (Iref - moyIref);
204 covarIc += (Ic - moyIc) * (Ic - moyIc);
205 sIcIref += (Iref - moyIref) * (Ic - moyIc);
206 }
207 }
208 delete[] tempt;
209
210 covarIref = sqrt(covarIref);
211 covarIc = sqrt(covarIc);
212
213 denom = covarIref * covarIc;
214
215 double NCC = sIcIref / denom;
216 vpColVector dcovarIref(nbParam);
217 dcovarIref = -sIcdIref / covarIref;
218
219 vpColVector dNCC(nbParam);
220 dNCC = (sIcdIref / denom - NCC * dcovarIref / covarIref);
221 vpMatrix d2covarIref(nbParam, nbParam);
222 d2covarIref = -(sIcd2Iref - sdIrefdIref + dcovarIref * dcovarIref.t()) / covarIref;
223#ifdef APPROX_NCC
224 Hdesire = sIcd2Iref / denom;
225#else
226 Hdesire = (sIcd2Iref - sdIrefdIref + dcovarIref * dcovarIref.t()) / denom;
227#endif
229 HLMdesireInverse = HLMdesire.inverseByLU();
230}
231
233{
234 if (blur)
236
237 vpColVector dpinv(nbParam);
238 double Ic;
239 double Iref;
240 unsigned int iteration = 0;
241 int i, j;
242 double i2, j2;
244
245 double evolRMS_init = 0;
246 double evolRMS_prec = 0;
247 double evolRMS_delta;
248
249 do {
250 unsigned int Nbpoint = 0;
251 G = 0;
252 Warp->computeCoeff(p);
253 double moyIref = 0;
254 double moyIc = 0;
255 for (unsigned int point = 0; point < templateSize; point++) {
256 i = ptTemplate[point].y;
257 j = ptTemplate[point].x;
258 X1[0] = j;
259 X1[1] = i;
260
261 Warp->computeDenom(X1, p);
262 Warp->warpX(X1, X2, p);
263
264 j2 = X2[0];
265 i2 = X2[1];
266 if ((i2 >= 0) && (j2 >= 0) && (i2 < I.getHeight() - 1) && (j2 < I.getWidth() - 1)) {
267 Iref = ptTemplate[point].val;
268
269 if (!blur)
270 Ic = I.getValue(i2, j2);
271 else
272 Ic = BI.getValue(i2, j2);
273
274 Nbpoint++;
275 moyIref += Iref;
276 moyIc += Ic;
277 }
278 }
279 if (Nbpoint > 0) {
280 moyIref = moyIref / Nbpoint;
281 moyIc = moyIc / Nbpoint;
282 double sIcIref = 0;
283 double covarIref = 0, covarIc = 0;
284 vpColVector sIcdIref(nbParam);
285 sIcdIref = 0;
286 vpColVector sIrefdIref(nbParam);
287 sIrefdIref = 0;
288
289 for (unsigned int point = 0; point < templateSize; point++) {
290 i = ptTemplate[point].y;
291 j = ptTemplate[point].x;
292 X1[0] = j;
293 X1[1] = i;
294
295 Warp->computeDenom(X1, p);
296 Warp->warpX(X1, X2, p);
297
298 j2 = X2[0];
299 i2 = X2[1];
300 if ((i2 >= 0) && (j2 >= 0) && (i2 < I.getHeight() - 1) && (j2 < I.getWidth() - 1)) {
301 Iref = ptTemplate[point].val;
302
303 if (!blur)
304 Ic = I.getValue(i2, j2);
305 else
306 Ic = BI.getValue(i2, j2);
307
308 double prod = (Ic - moyIc);
309 for (unsigned int it = 0; it < nbParam; it++)
310 sIcdIref[it] += prod * (ptTemplate[point].dW[it] - moydIrefdp[it]);
311 for (unsigned int it = 0; it < nbParam; it++)
312 sIrefdIref[it] += (Iref - moyIref) * (ptTemplate[point].dW[it] - moydIrefdp[it]);
313
314 covarIref += (Iref - moyIref) * (Iref - moyIref);
315 covarIc += (Ic - moyIc) * (Ic - moyIc);
316 sIcIref += (Iref - moyIref) * (Ic - moyIc);
317 }
318 }
319 covarIref = sqrt(covarIref);
320 covarIc = sqrt(covarIc);
321 double denom = covarIref * covarIc;
322
323 if (std::fabs(denom) <= std::numeric_limits<double>::epsilon()) {
324 diverge = true;
325 }
326 else {
327 double NCC = sIcIref / denom;
328 vpColVector dcovarIref(nbParam);
329 dcovarIref = sIrefdIref / covarIref;
330 G = (sIcdIref / denom - NCC * dcovarIref / covarIref);
331
332 try {
333 dp = -HLMdesireInverse * G;
334 }
335 catch (const vpException &e) {
336 throw(e);
337 }
338
339 Warp->getParamInverse(dp, dpinv);
340 Warp->pRondp(p, dpinv, p);
341
343 }
344 }
345 else
346 diverge = true;
347
348 if (iteration == 0) {
349 evolRMS_init = evolRMS;
350 }
351 iteration++;
352
353 evolRMS_delta = std::fabs(evolRMS - evolRMS_prec);
354 evolRMS_prec = evolRMS;
355
356 } while ((!diverge && (evolRMS_delta > std::fabs(evolRMS_init) * evolRMS_eps) && (iteration < iterationMax)));
357
358 nbIteration = iteration;
359}
360END_VISP_NAMESPACE
Implementation of column vector and the associated operations.
vpRowVector t() const
error that can be emitted by ViSP classes.
Definition vpException.h:60
static void getGradX(const vpImage< unsigned char > &I, vpImage< FilterType > &dIx, const vpImage< bool > *p_mask=nullptr)
static void getGradXGauss2D(const vpImage< ImageType > &I, vpImage< FilterType > &dIx, const FilterType *gaussianKernel, const FilterType *gaussianDerivativeKernel, unsigned int size, const vpImage< bool > *p_mask=nullptr)
static void filter(const vpImage< ImageType > &I, vpImage< FilterType > &If, const vpArray2D< FilterType > &M, bool convolve=false, const vpImage< bool > *p_mask=nullptr)
static void getGradYGauss2D(const vpImage< ImageType > &I, vpImage< FilterType > &dIy, const FilterType *gaussianKernel, const FilterType *gaussianDerivativeKernel, unsigned int size, const vpImage< bool > *p_mask=nullptr)
static void getGradY(const vpImage< unsigned char > &I, vpImage< FilterType > &dIy, const vpImage< bool > *p_mask=nullptr)
Definition of the vpImage class member functions.
Definition vpImage.h:131
Type getValue(unsigned int i, unsigned int j) const
Implementation of a matrix and operations on matrices.
Definition vpMatrix.h:175
static void computeHLM(const vpMatrix &H, const double &alpha, vpMatrix &HLM)
VP_EXPLICIT vpTemplateTrackerZNCCInverseCompositional(vpTemplateTrackerWarp *warp)
VP_EXPLICIT vpTemplateTrackerZNCC(vpTemplateTrackerWarp *warp)
vpImage< double > dIx
vpImage< double > dIy
void computeEvalRMS(const vpColVector &p)
unsigned int iterationMax
void initPosEvalRMS(const vpColVector &p)
vpTemplateTrackerPoint * ptTemplate
vpTemplateTrackerWarp * Warp
vpImage< double > BI
unsigned int templateSize