Visual Servoing Platform  version 3.6.1 under development (2024-07-27)
vpFeatureEllipse.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See https://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * 2D ellipse visual feature.
33  *
34 *****************************************************************************/
35 
41 #include <visp3/visual_features/vpBasicFeature.h>
42 #include <visp3/visual_features/vpFeatureEllipse.h>
43 
44 // Exception
45 #include <visp3/core/vpException.h>
46 #include <visp3/visual_features/vpFeatureException.h>
47 
48 // Debug trace
49 #include <visp3/core/vpDebug.h>
50 
51 // math
52 #include <visp3/core/vpMath.h>
53 
54 #include <visp3/core/vpFeatureDisplay.h>
55 
56 /*
57 
58 attributes and members directly related to the vpBasicFeature needs
59 other functionalities ar useful but not mandatory
60 
61 */
62 
64 
66 {
67  // feature dimension
68  dim_s = 5;
69  nbParameters = 8;
70 
71  // memory allocation
72  s.resize(dim_s);
73  if (flags == nullptr)
74  flags = new bool[nbParameters];
75  for (unsigned int i = 0; i < nbParameters; i++)
76  flags[i] = false;
77 
78  // default depth values
79  A = B = 0;
80  C = 1;
81 }
82 
83 vpFeatureEllipse::vpFeatureEllipse() : A(0), B(0), C(0) { init(); }
84 vpFeatureEllipse::vpFeatureEllipse(double x, double y, double n20, double n11, double n02) { this->build(x, y, n20, n11, n02); }
85 
86 
89 {
90  vpMatrix L;
91 
92  L.resize(0, 6);
93 
95  for (unsigned int i = 0; i < nbParameters; i++) {
96  if (flags[i] == false) {
97  switch (i) {
98  case 0:
99  vpTRACE("Warning !!! The interaction matrix is computed but x was "
100  "not set yet");
101  break;
102  case 1:
103  vpTRACE("Warning !!! The interaction matrix is computed but y was "
104  "not set yet");
105  break;
106  case 2:
107  vpTRACE("Warning !!! The interaction matrix is computed but n20 "
108  "was not set yet");
109  break;
110  case 3:
111  vpTRACE("Warning !!! The interaction matrix is computed but n11 "
112  "was not set yet");
113  break;
114  case 4:
115  vpTRACE("Warning !!! The interaction matrix is computed but n02 "
116  "was not set yet");
117  break;
118  case 5:
119  vpTRACE("Warning !!! The interaction matrix is computed but A was "
120  "not set yet");
121  break;
122  case 6:
123  vpTRACE("Warning !!! The interaction matrix is computed but B was "
124  "not set yet");
125  break;
126  case 7:
127  vpTRACE("Warning !!! The interaction matrix is computed but C was "
128  "not set yet");
129  break;
130  default:
131  vpTRACE("Problem during the reading of the variable flags");
132  }
133  }
134  }
135  resetFlags();
136  }
137 
138  double xc = s[0];
139  double yc = s[1];
140  double n20 = s[2];
141  double n11 = s[3];
142  double n02 = s[4];
143 
144  double Zinv = A * xc + B * yc + C;
145 
146  if (vpFeatureEllipse::selectX() & select) {
147  vpMatrix H(1, 6);
148  H = 0;
149  // Eq (14) of Chaumette 2004 TRO paper on moments
150  H[0][0] = -Zinv;
151  H[0][1] = 0;
152  H[0][2] = xc * Zinv + 4.0 * (A * n20 + B * n11);
153  H[0][3] = xc * yc + 4.0 * n11;
154  H[0][4] = -1 - vpMath::sqr(xc) - 4.0 * n20;
155  H[0][5] = yc;
156 
157  L = vpMatrix::stack(L, H);
158  }
159 
160  if (vpFeatureEllipse::selectY() & select) {
161  vpMatrix H(1, 6);
162  H = 0;
163  // Eq (14) of Chaumette 2004 TRO paper on moments
164  H[0][0] = 0;
165  H[0][1] = -Zinv;
166  H[0][2] = yc * Zinv + 4.0 * (A * n11 + B * n02);
167  H[0][3] = 1 + vpMath::sqr(yc) + 4.0 * n02;
168  H[0][4] = -xc * yc - 4.0 * n11;
169  H[0][5] = -xc;
170 
171  L = vpMatrix::stack(L, H);
172  }
173 
174  if (vpFeatureEllipse::select_n20() & select) {
175  vpMatrix H(1, 6);
176  H = 0;
177  // Eq (26) of Chaumette 2004 TRO paper on moments
178  H[0][0] = -2.0 * (A * n20 + B * n11);
179  H[0][1] = 0;
180  H[0][2] = 2 * ((Zinv + A * xc) * n20 + B * xc * n11);
181  H[0][3] = 2 * (yc * n20 + xc * n11);
182  H[0][4] = -4 * n20 * xc;
183  H[0][5] = 2 * n11;
184 
185  L = vpMatrix::stack(L, H);
186  }
187 
188  if (vpFeatureEllipse::select_n11() & select) {
189  vpMatrix H(1, 6);
190  H = 0;
191  // Eq (26) of Chaumette 2004 TRO paper on moments
192  H[0][0] = -A * n11 - B * n02;
193  H[0][1] = -A * n20 - B * n11;
194  H[0][2] = A * yc * n20 + (3 * Zinv - C) * n11 + B * xc * n02;
195  H[0][3] = 3 * yc * n11 + xc * n02;
196  H[0][4] = -yc * n20 - 3 * xc * n11;
197  H[0][5] = n02 - n20;
198 
199  L = vpMatrix::stack(L, H);
200  }
201 
202  if (vpFeatureEllipse::select_n02() & select) {
203  vpMatrix H(1, 6);
204  H = 0;
205  // Eq (26) of Chaumette 2004 TRO paper on moments
206  H[0][0] = 0;
207  H[0][1] = -2 * (A * n11 + B * n02);
208  H[0][2] = 2 * ((Zinv + B * yc) * n02 + A * yc * n11);
209  H[0][3] = 4 * yc * n02;
210  H[0][4] = -2 * (yc * n11 + xc * n02);
211  H[0][5] = -2 * n11;
212  L = vpMatrix::stack(L, H);
213  }
214 
215  return L;
216 }
217 
220 vpColVector vpFeatureEllipse::error(const vpBasicFeature &s_star, unsigned int select)
221 {
222  vpColVector e(0);
223 
224  try {
225  if (vpFeatureEllipse::selectX() & select) {
226  vpColVector ex(1);
227  ex[0] = s[0] - s_star[0];
228 
229  e = vpColVector::stack(e, ex);
230  }
231 
232  if (vpFeatureEllipse::selectY() & select) {
233  vpColVector ey(1);
234  ey[0] = s[1] - s_star[1];
235  e = vpColVector::stack(e, ey);
236  }
237 
238  if (vpFeatureEllipse::select_n20() & select) {
239  vpColVector ex(1);
240  ex[0] = s[2] - s_star[2];
241 
242  e = vpColVector::stack(e, ex);
243  }
244 
245  if (vpFeatureEllipse::select_n11() & select) {
246  vpColVector ey(1);
247  ey[0] = s[3] - s_star[3];
248  e = vpColVector::stack(e, ey);
249  }
250 
251  if (vpFeatureEllipse::select_n02() & select) {
252  vpColVector ey(1);
253  ey[0] = s[4] - s_star[4];
254  e = vpColVector::stack(e, ey);
255  }
256 
257  }
258  catch (...) {
259  throw;
260  }
261 
262  return e;
263 }
264 
265 void vpFeatureEllipse::print(unsigned int select) const
266 {
267 
268  std::cout << "Ellipse: " << std::endl;
269  if (vpFeatureEllipse::selectX() & select)
270  std::cout << " x=" << s[0] << std::endl;
271  ;
272  if (vpFeatureEllipse::selectY() & select)
273  std::cout << " y=" << s[1] << std::endl;
274  if (vpFeatureEllipse::select_n20() & select)
275  std::cout << " n20=" << s[2] << std::endl;
276  if (vpFeatureEllipse::select_n11() & select)
277  std::cout << " n11=" << s[3] << std::endl;
278  if (vpFeatureEllipse::select_n02() & select)
279  std::cout << " n02=" << s[4] << std::endl;
280  std::cout << "A = " << A << " B = " << B << " C = " << C << std::endl;
281 }
282 
283 #ifdef VISP_BUILD_DEPRECATED_FUNCTIONS
287 void vpFeatureEllipse::buildFrom(double x, double y, double n20, double n11, double n02)
288 {
289  build(x, y, n20, n11, n02);
290 }
291 
295 void vpFeatureEllipse::buildFrom(double x, double y, double n20, double n11, double n02, double a, double b, double c)
296 {
297  build(x, y, n20, n11, n02, a, b, c);
298 }
299 #endif
300 
301 vpFeatureEllipse &vpFeatureEllipse::build(const double &x, const double &y, const double &n20, const double &n11, const double &n02)
302 {
303  s[0] = x;
304  s[1] = y;
305  s[2] = n20;
306  s[3] = n11;
307  s[4] = n02;
308 
309  for (int i = 0; i < 5; ++i) {
310  flags[i] = true;
311  }
312  return *this;
313 }
314 
315 vpFeatureEllipse &vpFeatureEllipse::build(const double &x, const double &y, const double &n20, const double &n11, const double &n02, const double &a, const double &b, const double &c)
316 {
317  s[0] = x;
318  s[1] = y;
319  s[2] = n20;
320  s[3] = n11;
321  s[4] = n02;
322 
323  this->A = a;
324  this->B = b;
325  this->C = c;
326 
327  for (unsigned int i = 0; i < nbParameters; ++i) {
328  flags[i] = true;
329  }
330  return *this;
331 }
332 
334 {
335  s[0] = x;
336  flags[0] = true;
337 }
338 
340 {
341  s[1] = y;
342  flags[1] = true;
343 }
344 
345 void vpFeatureEllipse::set_xy(double x, double y)
346 {
347  s[0] = x;
348  s[1] = y;
349  for (int i = 0; i < 2; i++)
350  flags[i] = true;
351 }
352 
353 void vpFeatureEllipse::setABC(double a, double b, double c)
354 {
355  this->A = a;
356  this->B = b;
357  this->C = c;
358  for (unsigned int i = 5; i < nbParameters; i++)
359  flags[i] = true;
360 }
361 
368 void vpFeatureEllipse::setMoments(double n20, double n11, double n02)
369 {
370  s[2] = n20;
371  s[3] = n11;
372  s[4] = n02;
373  for (int i = 2; i < 5; i++)
374  flags[i] = true;
375 }
376 
377 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
384 void vpFeatureEllipse::setMu(double mu20, double mu11, double mu02) { setMoments(mu20, mu11, mu02); }
385 #endif
386 
397  unsigned int thickness) const
398 {
399  double x = s[0];
400  double y = s[1];
401 
402  double n20 = s[2];
403  double n11 = s[3];
404  double n02 = s[4];
405 
406  vpFeatureDisplay::displayEllipse(x, y, n20, n11, n02, cam, I, color, thickness);
407 }
408 
418 void vpFeatureEllipse::display(const vpCameraParameters &cam, const vpImage<vpRGBa> &I, const vpColor &color,
419  unsigned int thickness) const
420 {
421  double x = s[0];
422  double y = s[1];
423 
424  double n20 = s[2];
425  double n11 = s[3];
426  double n02 = s[4];
427 
428  vpFeatureDisplay::displayEllipse(x, y, n20, n11, n02, cam, I, color, thickness);
429 }
430 
433 {
434  vpFeatureEllipse *feature = new vpFeatureEllipse;
435  return feature;
436 }
437 
441 unsigned int vpFeatureEllipse::selectX() { return FEATURE_LINE[0]; }
445 unsigned int vpFeatureEllipse::selectY() { return FEATURE_LINE[1]; }
446 
451 unsigned int vpFeatureEllipse::select_n20() { return FEATURE_LINE[2]; }
456 unsigned int vpFeatureEllipse::select_n11() { return FEATURE_LINE[3]; }
461 unsigned int vpFeatureEllipse::select_n02() { return FEATURE_LINE[4]; }
462 
463 #if defined(VISP_BUILD_DEPRECATED_FUNCTIONS)
470 VP_DEPRECATED unsigned int vpFeatureEllipse::selectMu20() { return FEATURE_LINE[2]; }
477 VP_DEPRECATED unsigned int vpFeatureEllipse::selectMu11() { return FEATURE_LINE[3]; }
484 VP_DEPRECATED unsigned int vpFeatureEllipse::selectMu02() { return FEATURE_LINE[4]; }
485 #endif
486 END_VISP_NAMESPACE
class that defines what is a visual feature
vpColVector s
State of the visual feature.
unsigned int nbParameters
Number of parameters needed to compute the interaction matrix.
unsigned int dim_s
Dimension of the visual feature.
static const unsigned int FEATURE_LINE[32]
vpBasicFeatureDeallocatorType deallocate
Generic class defining intrinsic camera parameters.
Implementation of column vector and the associated operations.
Definition: vpColVector.h:191
void stack(double d)
void resize(unsigned int i, bool flagNullify=true)
Definition: vpColVector.h:1143
Class to define RGB colors available for display functionalities.
Definition: vpColor.h:157
static void displayEllipse(double x, double y, double n20, double n11, double n02, const vpCameraParameters &cam, const vpImage< unsigned char > &I, const vpColor &color=vpColor::green, unsigned int thickness=1)
Class that defines 2D ellipse visual feature.
static VP_DEPRECATED unsigned int selectMu20()
void set_x(double x)
void print(unsigned int select=FEATURE_ALL) const VP_OVERRIDE
Print the name of the feature.
static unsigned int selectX()
void init() VP_OVERRIDE
Default initialization.
vpFeatureEllipse & build(const double &x, const double &y, const double &n20, const double &n11, const double &n02)
static VP_DEPRECATED unsigned int selectMu02()
void set_y(double y)
vpFeatureEllipse()
Default constructor.
void display(const vpCameraParameters &cam, const vpImage< unsigned char > &I, const vpColor &color=vpColor::green, unsigned int thickness=1) const VP_OVERRIDE
static unsigned int selectY()
void setABC(double A, double B, double C)
vpFeatureEllipse * duplicate() const VP_OVERRIDE
Feature duplication.
VP_DEPRECATED void setMu(double mu20, double mu11, double mu02)
static unsigned int select_n20()
static VP_DEPRECATED unsigned int selectMu11()
void setMoments(double n20, double n11, double n02)
vpMatrix interaction(unsigned int select=FEATURE_ALL) VP_OVERRIDE
compute the interaction matrix from a subset a the possible features
static unsigned int select_n02()
static unsigned int select_n11()
vpColVector error(const vpBasicFeature &s_star, unsigned int select=FEATURE_ALL) VP_OVERRIDE
void set_xy(double x, double y)
void buildFrom(double x, double y, double n20, double n11, double n02)
static double sqr(double x)
Definition: vpMath.h:203
Implementation of a matrix and operations on matrices.
Definition: vpMatrix.h:169
void stack(const vpMatrix &A)
#define vpTRACE
Definition: vpDebug.h:436