Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpTemplateTrackerMIESM.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 * Example of template tracking.
32 *
33 * Authors:
34 * Amaury Dame
35 * Aurelien Yol
36 */
37
38#include <visp3/tt_mi/vpTemplateTrackerMIESM.h>
39
40#ifdef VISP_HAVE_OPENMP
41#include <omp.h>
42#endif
43
48{
49 useCompositionnal = false;
50 useInverse = false;
51 if (!Warp->isESMcompatible()) {
52 throw(vpException(vpException::badValue, "The selected warp function is not appropriate for the ESM algorithm..."));
53 }
54}
55
57{
59
60 dW = 0;
61
62 int Nbpoint = 0;
63
64 double i2, j2;
65 double IW, dx, dy;
66 int i, j;
67 int cr, ct;
68 double er, et;
69
70 Nbpoint = 0;
71
72 if (blur)
74
76
77 vpColVector tptemp(nbParam);
78
79 Warp->computeCoeff(p);
80 for (unsigned int point = 0; point < templateSize; point++) {
81 i = ptTemplate[point].y;
82 j = ptTemplate[point].x;
83 X1[0] = j;
84 X1[1] = i;
85
86 Warp->computeDenom(X1, p);
87 Warp->warpX(X1, X2, p);
88
89 j2 = X2[0];
90 i2 = X2[1];
91
92 if ((i2 >= 0) && (j2 >= 0) && (i2 < I.getHeight() - 1) && (j2 < I.getWidth() - 1)) {
93 Nbpoint++;
94
95 if (blur)
96 IW = BI.getValue(i2, j2);
97 else
98 IW = I.getValue(i2, j2);
99
100 ct = ptTemplateSupp[point].ct;
101 et = ptTemplateSupp[point].et;
102 cr = static_cast<int>((IW * (Nc - 1)) / 255.);
103 er = (IW * (Nc - 1)) / 255. - cr;
104
105 vpTemplateTrackerMIBSpline::computeProbabilities(PrtTout, cr, er, ct, et, Nc, ptTemplate[point].dW, nbParam,
106 bspline, ApproxHessian, false);
107 }
108 }
109
110 double MI;
111 computeProba(Nbpoint);
112 computeMI(MI);
114
122 }
123
124 Nbpoint = 0;
126
127 Warp->computeCoeff(p);
128 for (unsigned int point = 0; point < templateSize; point++) {
129 i = ptTemplate[point].y;
130 j = ptTemplate[point].x;
131 X1[0] = j;
132 X1[1] = i;
133
134 Warp->computeDenom(X1, p);
135 Warp->warpX(X1, X2, p);
136
137 j2 = X2[0];
138 i2 = X2[1];
139
140 if ((i2 >= 0) && (j2 >= 0) && (i2 < I.getHeight()) && (j2 < I.getWidth())) {
141 Nbpoint++;
142
143 if (!blur)
144 IW = I.getValue(i2, j2);
145 else
146 IW = BI.getValue(i2, j2);
147
148 dx = dIx.getValue(i2, j2) * (Nc - 1) / 255.;
149 dy = dIy.getValue(i2, j2) * (Nc - 1) / 255.;
150
151 cr = ptTemplateSupp[point].ct;
152 er = ptTemplateSupp[point].et;
153 ct = static_cast<int>((IW * (Nc - 1)) / 255.);
154 et = (IW * (Nc - 1)) / 255. - ct;
155
156 Warp->dWarpCompo(X1, X2, p, ptTemplateCompo[point].dW, dW);
157
158 for (unsigned int it = 0; it < nbParam; it++)
159 tptemp[it] = dW[0][it] * dx + dW[1][it] * dy;
160
161 vpTemplateTrackerMIBSpline::computeProbabilities(PrtTout, cr, er, ct, et, Nc, tptemp.data, nbParam, bspline,
162 ApproxHessian, false);
163 }
164 }
165
166 computeProba(Nbpoint);
167 computeMI(MI);
169
171
173
175
176 HLMdesireInverse = HLMdesire.inverseByLU();
177}
178
180{
181 HDirect.resize(nbParam, nbParam);
182 HInverse.resize(nbParam, nbParam);
185 GDirect.resize(nbParam);
186 GInverse.resize(nbParam);
187
188 ptTemplateSupp = new vpTemplateTrackerPointSuppMIInv[templateSize];
190 for (unsigned int point = 0; point < templateSize; point++) {
191 int i = ptTemplate[point].y;
192 int j = ptTemplate[point].x;
193 X1[0] = j;
194 X1[1] = i;
195 Warp->computeDenom(X1, p);
196
197 ptTemplateCompo[point].dW = new double[2 * nbParam];
198 Warp->getdWdp0(i, j, ptTemplateCompo[point].dW);
199
200 ptTemplate[point].dW = new double[nbParam];
201 double dx = ptTemplate[point].dx * (Nc - 1) / 255.;
202 double dy = ptTemplate[point].dy * (Nc - 1) / 255.;
203 Warp->getdW0(i, j, dy, dx, ptTemplate[point].dW);
204
205 double Tij = ptTemplate[point].val;
206 int ct = static_cast<int>((Tij * (Nc - 1)) / 255.);
207 double et = (Tij * (Nc - 1)) / 255. - ct;
208 ptTemplateSupp[point].et = et;
209 ptTemplateSupp[point].ct = ct;
210 ptTemplateSupp[point].Bt = new double[4];
211 ptTemplateSupp[point].dBt = new double[4];
212 for (char it = -1; it <= 2; it++) {
213 ptTemplateSupp[point].Bt[it + 1] = vpTemplateTrackerBSpline::Bspline4(-it + et);
214 ptTemplateSupp[point].dBt[it + 1] = vpTemplateTrackerMIBSpline::dBspline4(-it + et);
215 }
216 }
217 CompoInitialised = true;
218}
219
221{
222 if (!CompoInitialised) {
223 std::cout << "Compositionnal tracking not initialised.\nUse initCompInverse() function." << std::endl;
224 }
225 dW = 0;
226
227 if (blur)
231
232 int point;
233
235
237
238 double i2, j2;
239 double IW;
240 int cr, ct;
241 double er, et;
242
243 vpColVector dpinv(nbParam);
244
245 double alpha = 2.;
246
247 int i, j;
248 unsigned int iteration = 0;
249 vpColVector tptemp(nbParam);
250
251 do {
252 int Nbpoint = 0;
253 double MI = 0;
254
256
258 // Inverse
259 Warp->computeCoeff(p);
260 for (point = 0; point < static_cast<int>(templateSize); point++) {
261 i = ptTemplate[point].y;
262 j = ptTemplate[point].x;
263 X1[0] = j;
264 X1[1] = i;
265
266 Warp->computeDenom(X1, p);
267 Warp->warpX(X1, X2, p);
268
269 j2 = X2[0];
270 i2 = X2[1];
271
272 if ((i2 >= 0) && (j2 >= 0) && (i2 < I.getHeight() - 1) && (j2 < I.getWidth() - 1)) {
273 Nbpoint++;
274
275 if (!blur)
276 IW = I.getValue(i2, j2);
277 else
278 IW = BI.getValue(i2, j2);
279
280 ct = ptTemplateSupp[point].ct;
281 et = ptTemplateSupp[point].et;
282 cr = static_cast<int>((IW * (Nc - 1)) / 255.);
283 er = (IW * (Nc - 1)) / 255. - cr;
284
285 vpTemplateTrackerMIBSpline::computeProbabilities(PrtTout, cr, er, ct, et, Nc, ptTemplate[point].dW, nbParam,
288 }
289 }
290
291 if (Nbpoint == 0) {
292 diverge = true;
293 MI = 0;
294 throw(vpTrackingException(vpTrackingException::notEnoughPointError, "No points in the template"));
295 }
296 else {
297 computeProba(Nbpoint);
298 computeMI(MI);
301 }
303 GInverse = G;
304
306 // DIRECT
307
308 Nbpoint = 0;
309 MI = 0;
310
312
313 Warp->computeCoeff(p);
314#ifdef VISP_HAVE_OPENMP
315 int nthreads = omp_get_num_procs();
316 // std::cout << "file: " __FILE__ << " line: " << __LINE__ << "
317 // function: " << __FUNCTION__ << " nthread: " << nthreads << std::endl;
318 omp_set_num_threads(nthreads);
319#pragma omp parallel for private(i, j, i2, j2) default(shared)
320#endif
321 for (point = 0; point < static_cast<int>(templateSize); point++) {
322 i = ptTemplate[point].y;
323 j = ptTemplate[point].x;
324 X1[0] = j;
325 X1[1] = i;
326 Warp->computeDenom(X1, p);
327 Warp->warpX(i, j, i2, j2, p);
328 X2[0] = j2;
329 X2[1] = i2;
330
331 if ((i2 >= 0) && (j2 >= 0) && (i2 < I.getHeight() - 1) && (j2 < I.getWidth() - 1)) {
332 Nbpoint++;
333
334 if (!blur)
335 IW = I.getValue(i2, j2);
336 else
337 IW = BI.getValue(i2, j2);
338
339 double dx = dIx.getValue(i2, j2) * (Nc - 1) / 255.;
340 double dy = dIy.getValue(i2, j2) * (Nc - 1) / 255.;
341
342 ct = static_cast<int>((IW * (Nc - 1)) / 255.);
343 et = (IW * (Nc - 1)) / 255. - ct;
344 cr = ptTemplateSupp[point].ct;
345 er = ptTemplateSupp[point].et;
346 Warp->dWarpCompo(X1, X2, p, ptTemplateCompo[point].dW, dW);
347
348 for (unsigned int it = 0; it < nbParam; it++)
349 tptemp[it] = dW[0][it] * dx + dW[1][it] * dy;
350
351 vpTemplateTrackerMIBSpline::computeProbabilities(PrtTout, cr, er, ct, et, Nc, tptemp.data, nbParam, bspline,
353 }
354 }
355
356 computeProba(Nbpoint);
357 computeMI(MI);
361 GDirect = G;
362
364 H = HDirect + HInverse;
366 }
367 G = GDirect - GInverse;
368
369 try {
371 dp = -gain * 0.3 * G;
372 else {
373 switch (hessianComputation) {
376 break;
378 if (HLM.cond() > HLMdesire.cond()) {
380 }
381 else {
382 dp = gain * 0.3 * HLM.inverseByLU() * G;
383 }
384 break;
385 default:
386 dp = gain * 0.3 * HLM.inverseByLU() * G;
387 break;
388 }
389 }
390 }
391 catch (const vpException &e) {
392 throw(e);
393 }
394
396 dp = -dp;
397
398 if (useBrent) {
399 alpha = 2.;
400 computeOptimalBrentGain(I, p, -MI, dp, alpha);
401 dp = alpha * dp;
402 }
403 p += dp;
404
405 iteration++;
406 }
407 } while ((iteration < iterationMax));
408
412 }
413
414 nbIteration = iteration;
415}
416END_VISP_NAMESPACE
Type * data
Address of the first element of the data array.
Definition vpArray2D.h:149
Implementation of column vector and the associated operations.
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
static void computeHLM(const vpMatrix &H, const double &alpha, vpMatrix &HLM)
void trackNoPyr(const vpImage< unsigned char > &I)
void initHessienDesired(const vpImage< unsigned char > &I)
vpMinimizationTypeMIESM minimizationMethod
vpTemplateTrackerMIESM()
Default constructor.
vpHessienApproximationType ApproxHessian
vpImage< double > d2Ix
vpHessienType hessianComputation
double getCost(const vpImage< unsigned char > &I, const vpColVector &tp) VP_OVERRIDE
void computeProba(int &nbpoint)
void computeHessien(vpMatrix &H)
vpImage< double > d2Ixy
vpTemplateTrackerMI(const vpTemplateTrackerMI &)=delete
vpImage< double > d2Iy
vpImage< double > dIx
vpImage< double > dIy
void computeOptimalBrentGain(const vpImage< unsigned char > &I, vpColVector &tp, double tMI, vpColVector &direction, double &alpha)
unsigned int iterationMax
vpTemplateTrackerPoint * ptTemplate
vpTemplateTrackerWarp * Warp
vpImage< double > BI
unsigned int templateSize
vpTemplateTrackerPointCompo * ptTemplateCompo
Error that can be emitted by the vpTracker class and its derivatives.
@ notEnoughPointError
Not enough point to track.