ViSP  2.10.0
vpMbtMeEllipse.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMbtMeEllipse.cpp 4706 2014-03-28 07:52:00Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2014 by INRIA. All rights reserved.
7  *
8  * This software is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * ("GPL") version 2 as published by the Free Software Foundation.
11  * See the file LICENSE.txt at the root directory of this source
12  * distribution for additional information about the GNU GPL.
13  *
14  * For using ViSP with software that can not be combined with the GNU
15  * GPL, please contact INRIA about acquiring a ViSP Professional
16  * Edition License.
17  *
18  * See http://www.irisa.fr/lagadic/visp/visp.html for more information.
19  *
20  * This software was developed at:
21  * INRIA Rennes - Bretagne Atlantique
22  * Campus Universitaire de Beaulieu
23  * 35042 Rennes Cedex
24  * France
25  * http://www.irisa.fr/lagadic
26  *
27  * If you have questions regarding the use of this file, please contact
28  * INRIA at visp@inria.fr
29  *
30  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
31  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
32  *
33  *
34  * Description:
35  * Moving edges.
36  *
37  * Authors:
38  * Eric Marchand
39  *
40  *****************************************************************************/
41 
42 #ifndef DOXYGEN_SHOULD_SKIP_THIS
43 
44 #include <visp/vpMbtMeEllipse.h>
45 
46 #include <visp/vpMe.h>
47 #include <visp/vpRobust.h>
48 #include <visp/vpTrackingException.h>
49 #include <visp/vpDebug.h>
50 #include <visp/vpImagePoint.h>
51 
52 #include <cmath> // std::fabs
53 #include <limits> // numeric_limits
54 
55 
59 vpMbtMeEllipse::vpMbtMeEllipse()
60  : iPc(), a(0.), b(0.), e(0.),
61  ce(0.), se(0.), mu11(0.), mu20(0.), mu02(0.), thresholdWeight(0.), expecteddensity(0.)
62 {
63 }
64 
68 vpMbtMeEllipse::vpMbtMeEllipse(const vpMbtMeEllipse &meellipse)
69  : vpMeTracker(meellipse), iPc(), a(0.), b(0.), e(0.),
70  ce(0.), se(0.), mu11(0.), mu20(0.), mu02(0.), thresholdWeight(0.), expecteddensity(0.)
71 {
72  iPc = meellipse.iPc;
73  a = meellipse.a;
74  b = meellipse.b;
75  e = meellipse.e;
76 
77  ce = meellipse.ce;
78  se = meellipse.se;
79 
80  mu11 = meellipse.mu11;
81  mu20 = meellipse.mu20;
82  mu02 = meellipse.mu02;
83 
84  expecteddensity = meellipse.expecteddensity;
85 }
86 
90 vpMbtMeEllipse::~vpMbtMeEllipse()
91 {
92  list.clear();
93 }
94 
105 void
106 vpMbtMeEllipse::sample(const vpImage<unsigned char> & I)
107 {
108  if (!me) {
109  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
111  "Moving edges not initialized")) ;
112  }
113 
114  int height = (int)I.getHeight() ;
115  int width = (int)I.getWidth() ;
116 
117  //if (me->getSampleStep()==0)
118  if (std::fabs(me->getSampleStep()) <= std::numeric_limits<double>::epsilon())
119  {
120  std::cout << "In vpMbtMeEllipse::sample: " ;
121  std::cout << "function called with sample step = 0" ;
122  //return fatalError ;
123  }
124 
125  double j, i;//, j11, i11;
126  vpImagePoint iP11;
127  j = i = 0.0 ;
128 
129  // Approximation of the circumference of an ellipse:
130  // [Ramanujan, S., "Modular Equations and Approximations to ,"
131  // Quart. J. Pure. Appl. Math., vol. 45 (1913-1914), pp. 350-372]
132  double t = (a-b)/(a+b);
133  double circumference = M_PI*(a+b)*(1 + 3*vpMath::sqr(t)/(10 + sqrt(4 - 3*vpMath::sqr(t))));
134  int nb_points_to_track = (int)(circumference / me->getSampleStep());
135  double incr = 2*M_PI/nb_points_to_track;
136 
137  expecteddensity = 0;//nb_points_to_track;
138 
139  // Delete old list
140  list.clear();
141 
142  // sample positions
143  double k = 0 ;
144  double iP_i, iP_j;
145  for (int pt=0; pt < nb_points_to_track; pt++)
146  {
147  j = a *cos(k) ; // equation of an ellipse
148  i = b *sin(k) ; // equation of an ellipse
149 
150  iP_j = iPc.get_j() + ce *j - se *i;
151  iP_i = iPc.get_i() + se *j + ce *i;
152 
153  //vpColor col = vpColor::red ;
154  //vpDisplay::displayCross(I, vpImagePoint(iP_i, iP_j), 5, col) ; //debug only
155 
156  // If point is in the image, add to the sample list
157  if(!outOfImage(vpMath::round(iP_i), vpMath::round(iP_j), 0, height, width))
158  {
159  // The tangent angle to the ellipse at a site
160  double theta = atan( (-mu02*iP_j + mu02*iPc.get_j() + mu11*iP_i - mu11*iPc.get_i())
161  / (mu20*iP_i - mu11*iP_j + mu11*iPc.get_j() - mu20*iPc.get_i()))
162  - M_PI/2;
163 
164  vpMeSite pix ;
165  pix.init((int)iP_i, (int)iP_j, theta) ;
166  pix.setDisplay(selectDisplay) ;
168 
169  list.push_back(pix);
170  expecteddensity ++;
171  }
172  k += incr ;
173 
174  }
175 
177 }
178 
179 
194 void
195 vpMbtMeEllipse::reSample(const vpImage<unsigned char> &I)
196 {
197  if (!me) {
198  vpDERROR_TRACE(2, "Tracking error: Moving edges not initialized");
200  "Moving edges not initialized")) ;
201  }
202 
203  unsigned int n = numberOfSignal() ;
204  if ((double)n<0.9*expecteddensity){
205  sample(I) ;
206  vpMeTracker::track(I) ;
207  }
208 }
209 
215 void
216 vpMbtMeEllipse::updateTheta()
217 {
218  vpMeSite p_me;
219  double theta;
220  for(std::list<vpMeSite>::iterator it=list.begin(); it!=list.end(); ++it){
221  p_me = *it;
222  vpImagePoint iP;
223  iP.set_i(p_me.ifloat);
224  iP.set_j(p_me.jfloat);
225 
226  // The tangent angle to the ellipse at a site
227  theta = atan( (-mu02*p_me.jfloat + mu02*iPc.get_j() + mu11*p_me.ifloat - mu11*iPc.get_i())
228  / (mu20*p_me.ifloat - mu11*p_me.jfloat + mu11*iPc.get_j() - mu20*iPc.get_i()))
229  - M_PI/2;
230 
231  p_me.alpha = theta ;
232  *it = p_me;
233  }
234 }
235 
239 void
240 vpMbtMeEllipse::suppressPoints()
241 {
242  // Loop through list of sites to track
243  for(std::list<vpMeSite>::iterator itList=list.begin(); itList!=list.end();){
244  vpMeSite s = *itList;//current reference pixel
246  itList = list.erase(itList);
247  else
248  ++itList;
249  }
250 }
251 
261 void
262 vpMbtMeEllipse::display(const vpImage<unsigned char> &I, vpColor col)
263 {
264  vpDisplay::displayEllipse(I, iPc, mu20, mu11, mu02, true, col);
265 }
266 
267 void
268 vpMbtMeEllipse::initTracking(const vpImage<unsigned char> &I, const vpImagePoint &ic,
269  double mu20_p, double mu11_p, double mu02_p)
270 {
271  iPc = ic;
272  mu20 = mu20_p;
273  mu11 = mu11_p;
274  mu02 = mu02_p;
275 
276  if (std::fabs(mu11_p) > std::numeric_limits<double>::epsilon()) {
277 
278  double val_p = sqrt(vpMath::sqr(mu20_p-mu02_p) + 4*vpMath::sqr(mu11_p));
279  a = sqrt((mu20_p + mu02_p + val_p)/2);
280  b = sqrt((mu20_p + mu02_p - val_p)/2);
281 
282  e = (mu02_p - mu20_p + val_p)/(2*mu11_p);
283  }
284  else {
285  a = sqrt(mu20_p);
286  b = sqrt(mu02_p);
287  e = 0.;
288  }
289 
290  e = atan(e);
291 
292  ce = cos(e);
293  se = sin(e);
294 
295  sample(I) ;
296 
298 
299  try{
300  track(I) ;
301  }
302  catch(vpException &exception)
303  {
304  throw(exception) ;
305  }
306 }
307 
313 void
314 vpMbtMeEllipse::track(const vpImage<unsigned char> &I)
315 {
316  try{
317  vpMeTracker::track(I) ;
318  }
319  catch(vpException &exception)
320  {
321  throw(exception) ;
322  }
323 }
324 
325 void
326 vpMbtMeEllipse::updateParameters(const vpImage<unsigned char> &I, const vpImagePoint &ic, double mu20_p, double mu11_p, double mu02_p)
327 {
328  iPc = ic;
329  mu20 = mu20_p;
330  mu11 = mu11_p;
331  mu02 = mu02_p;
332 
333  if (std::fabs(mu11_p) > std::numeric_limits<double>::epsilon()) {
334 
335  double val_p = sqrt(vpMath::sqr(mu20_p-mu02_p) + 4*vpMath::sqr(mu11_p));
336  a = sqrt((mu20_p + mu02_p + val_p)/2);
337  b = sqrt((mu20_p + mu02_p - val_p)/2);
338 
339  e = (mu02_p - mu20_p + val_p)/(2*mu11_p);
340  }
341  else {
342  a = sqrt(mu20_p);
343  b = sqrt(mu02_p);
344  e = 0.;
345  }
346 
347  e = atan(e);
348 
349  ce = cos(e);
350  se = sin(e);
351 
352  suppressPoints();
353  reSample(I);
354 
355  // remet a jour l'angle delta pour chaque point de la liste
356  updateTheta();
357 }
358 
359 #endif // #ifndef DOXYGEN_SHOULD_SKIP_THIS
static void displayEllipse(const vpImage< unsigned char > &I, const vpImagePoint &center, const double &coef1, const double &coef2, const double &coef3, bool use_centered_moments, const vpColor &color, unsigned int thickness=1)
Definition: vpDisplay.cpp:3608
void init()
Definition: vpMeSite.cpp:73
unsigned int getWidth() const
Definition: vpImage.h:161
double jfloat
Definition: vpMeSite.h:100
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'...
Definition: vpMeSite.h:76
Class to define colors available for display functionnalities.
Definition: vpColor.h:125
double alpha
Definition: vpMeSite.h:104
error that can be emited by ViSP classes.
Definition: vpException.h:76
#define vpDERROR_TRACE
Definition: vpDebug.h:459
static int round(const double x)
Definition: vpMath.h:228
vpMeSiteState getState() const
Definition: vpMeSite.h:202
double ifloat
Definition: vpMeSite.h:100
void set_i(const double ii)
Definition: vpImagePoint.h:159
Error that can be emited by the vpTracker class and its derivates.
static double sqr(double x)
Definition: vpMath.h:106
void setDisplay(vpMeSiteDisplayType select)
Definition: vpMeSite.h:152
void track(const vpImage< unsigned char > &I)
Track sampled pixels.
Contains abstract elements for a Distance to Feature type feature.
Definition: vpMeTracker.h:71
void setState(const vpMeSiteState &flag)
Definition: vpMeSite.h:189
void set_j(const double jj)
Definition: vpImagePoint.h:170
void initTracking(const vpImage< unsigned char > &I)
unsigned int getHeight() const
Definition: vpImage.h:152
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:93