ViSP  2.9.0
vpTemplateTrackerZone.cpp
1 /****************************************************************************
2  *
3  * $Id: vpTemplateTrackerZone.cpp 4661 2014-02-10 19:34:58Z 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  * Description:
34  * Template tracker.
35  *
36  * Authors:
37  * Amaury Dame
38  * Aurelien Yol
39  * Fabien Spindler
40  *
41  *****************************************************************************/
42 
43 #include <limits> // numeric_limits
44 
45 #include <visp/vpConfig.h>
46 
47 #if VISP_HAVE_OPENCV_VERSION >= 0x020300
48 #include <opencv2/imgproc/imgproc.hpp>
49 #endif
50 
51 #include <visp/vpTemplateTrackerZone.h>
52 
53 
58  : Zone(), min_x(-1), min_y(-1), max_x(-1), max_y(-1)
59 {
60 }
61 
66  : Zone(), min_x(-1), min_y(-1), max_x(-1), max_y(-1)
67 {
68  *this = z;
69 }
70 
75 {
76  min_x=-1;
77  min_y=-1;
78  max_x=-1;
79  max_y=-1;
80 
81  Zone.clear();
82 }
83 
88 {
89  clear();
90 
91  this->copy(z);
92  return (*this);
93 }
94 
116 {
117  Zone.clear();
118 
119  std::vector<vpImagePoint> vip;
120 
121  bool end = false;
122 
123  do {
124  vpImagePoint p;
126  if (vpDisplay::getClick(I, p, button, false) ) {
127  vip.push_back(p);
128 
130 
131  if (vip.size() > 1) {
132  if (delaunay) {
133  // Draw a line between the 2 last points
134  vpDisplay::displayLine(I, p, vip[vip.size()-2], vpColor::blue, 3);
135  }
136  else {
137  if(vip.size() % 3 ==2)
138  // draw line between point 2-1
139  vpDisplay::displayLine(I, p, vip[vip.size()-2], vpColor::blue, 3);
140  else if(vip.size() % 3 ==0) {
141  // draw line between point 3-2
142  vpDisplay::displayLine(I, p, vip[vip.size()-2], vpColor::blue, 3);
143  // draw line between point 3-1
144  vpDisplay::displayLine(I, p, vip[vip.size()-3], vpColor::blue, 3);
145  }
146 
147  }
148  }
149  vpDisplay::flush(I);
150 
151  if (button == vpMouseButton::button3)
152  end = true;
153  }
154 
155  vpTime::wait(20);
156  } while(!end);
157 
158  initFromPoints(I, vip, delaunay);
159 }
160 
172 void vpTemplateTrackerZone::initFromPoints(const vpImage<unsigned char>& I, const std::vector< vpImagePoint > &vip, bool delaunay)
173 {
174  if (delaunay) {
175 #if VISP_HAVE_OPENCV_VERSION >= 0x020300
176  // Init Delaunay
177  cv::Subdiv2D subdiv(cv::Rect(0, 0, (int)I.getWidth(), (int)I.getHeight()));
178  for(size_t i=0; i< vip.size(); i++) {
179  cv::Point2f fp((float)vip[i].get_u(), (float)vip[i].get_v());
180  std::cout << "Click point: " << vip[i] << std::endl;
181  subdiv.insert(fp);
182  }
183 
184  // Compute Delaunay triangulation
185  std::vector<cv::Vec6f> triangleList;
186  subdiv.getTriangleList(triangleList);
187 
188  // Keep only the Delaunay points that are inside the area
189  vpRect rect(vip);
190 
191  std::vector<vpImagePoint> vip_delaunay;
192 
193  for( size_t i = 0; i < triangleList.size(); i++ ) {
194  cv::Vec6f t = triangleList[i];
195  std::vector<vpImagePoint> p(3);
196 
197  p[0].set_uv(t[0], t[1]);
198  p[1].set_uv(t[2], t[3]);
199  p[2].set_uv(t[4], t[5]);
200  if (p[0].inRectangle(rect) && p[1].inRectangle(rect) && p[2].inRectangle(rect)) {
201  vip_delaunay.push_back(p[0]);
202  vip_delaunay.push_back(p[1]);
203  vip_delaunay.push_back(p[2]);
204  }
205  }
206 
207  initFromPoints(I, vip_delaunay, false);
208 #else
209  throw vpException(vpException::functionNotImplementedError,"Delaunay triangulation is not available!");
210 #endif
211  }
212  else {
213  Zone.clear();
214  for(unsigned int i=0; i<vip.size(); i+=3) {
215  vpTemplateTrackerTriangle triangle(vip[i], vip[i+1], vip[i+2]);
216  add(triangle);
217 
218  vpDisplay::displayLine(I, vip[i], vip[i+1], vpColor::green, 1);
219  vpDisplay::displayLine(I, vip[i+1], vip[i+2], vpColor::green, 1);
220  vpDisplay::displayLine(I, vip[i+2], vip[i], vpColor::green,1);
221  vpDisplay::flush(I) ;
222 
223  // Update the bounding box
224  if((triangle.getMinx()<min_x)||(min_x==-1))
225  min_x=(int)triangle.getMinx();
226  if((triangle.getMaxx()>max_x)||(max_x==-1))
227  max_x=(int)triangle.getMaxx();
228  if((triangle.getMiny()<min_y)||(min_y==-1))
229  min_y=(int)triangle.getMiny();
230  if((triangle.getMaxy()>max_y)||(max_y==-1))
231  max_y=(int)triangle.getMaxy();
232  }
233  }
234 }
235 
241 {
242  Zone.push_back(t);
243 
244  // Update the bounding box
245  if((t.getMinx()<min_x)||(min_x==-1))
246  min_x=(int)t.getMinx();
247  if((t.getMaxx()>max_x)||(max_x==-1))
248  max_x=(int)t.getMaxx();
249  if((t.getMiny()<min_y)||(min_y==-1))
250  min_y=(int)t.getMiny();
251  if((t.getMaxy()>max_y)||(max_y==-1))
252  max_y=(int)t.getMaxy();
253 }
254 
260 bool vpTemplateTrackerZone::inZone(const int &i, const int &j) const
261 {
262  std::vector<vpTemplateTrackerTriangle>::const_iterator Iterateurvecteur;
263  for(Iterateurvecteur=Zone.begin();Iterateurvecteur!=Zone.end();Iterateurvecteur++)
264  {
265  if(Iterateurvecteur->inTriangle(i,j))
266  return true;
267  }
268  return false;
269 }
270 
276 bool vpTemplateTrackerZone::inZone(const double &i,const double &j) const
277 {
278  std::vector<vpTemplateTrackerTriangle>::const_iterator Iterateurvecteur;
279  for(Iterateurvecteur=Zone.begin();Iterateurvecteur!=Zone.end();Iterateurvecteur++)
280  {
281  if(Iterateurvecteur->inTriangle(i,j))
282  return true;
283  }
284  return false;
285 }
286 
294 bool vpTemplateTrackerZone::inZone(const int &i,const int &j, unsigned int &id_triangle) const
295 {
296  unsigned int id=0;
297  std::vector<vpTemplateTrackerTriangle>::const_iterator Iterateurvecteur;
298  for(Iterateurvecteur=Zone.begin();Iterateurvecteur!=Zone.end();Iterateurvecteur++)
299  {
300  if(Iterateurvecteur->inTriangle(i,j))
301  {
302  id_triangle=id;
303  return true;
304  }
305  id++;
306  }
307  return false;
308 }
309 
317 bool vpTemplateTrackerZone::inZone(const double &i,const double &j, unsigned int &id_triangle) const
318 {
319  unsigned int id=0;
320  std::vector<vpTemplateTrackerTriangle>::const_iterator Iterateurvecteur;
321  for(Iterateurvecteur=Zone.begin();Iterateurvecteur!=Zone.end();Iterateurvecteur++)
322  {
323  if(Iterateurvecteur->inTriangle(i,j))
324  {
325  id_triangle=id;
326  return true;
327  }
328  id++;
329  }
330  return false;
331 }
332 
350 {
351  if (i > getNbTriangle()-1)
352  throw(vpException(vpException::badValue, "Cannot get triangle with index %u", i));
353 
354  T = Zone[i];
355 }
371 {
372  if (i > getNbTriangle()-1)
373  throw(vpException(vpException::badValue, "Cannot get triangle with index %u", i));
374 
375  return Zone[i];
376 }
382 {
383  double xc=0;
384  double yc=0;
385  int cpt=0;
386  for(int i=min_y;i<max_y;i++)
387  for(int j=min_x;j<max_x;j++)
388  if(inZone(i,j))
389  {
390  xc+=j;
391  yc+=i;
392  cpt ++;
393  }
394  if(! cpt) {
396  "Cannot compute the zone center: size = 0")) ;
397  }
398  xc=xc/cpt;
399  yc=yc/cpt;
400  vpImagePoint ip;
401  ip.set_uv(xc, yc);
402  return ip;
403 }
404 
410 {
411  return max_x;
412 }
418 {
419  return max_y;
420 }
426 {
427  return min_x;
428 }
434 {
435  return min_y;
436 }
437 
443 {
444  vpRect bbox;
447  return bbox;
448 }
449 
456 void vpTemplateTrackerZone::display(const vpImage<unsigned char> &I, const vpColor &col, const unsigned int thickness)
457 {
458  std::vector<vpImagePoint> ip;
459  for (unsigned int i=0; i < Zone.size(); i++) {
460  vpTemplateTrackerTriangle triangle;
461  Zone[i].getCorners(ip);
462  vpDisplay::displayLine(I, ip[0], ip[1], col, thickness);
463  vpDisplay::displayLine(I, ip[1], ip[2], col, thickness);
464  vpDisplay::displayLine(I, ip[2], ip[0], col, thickness);
465  }
466 }
467 
474 void vpTemplateTrackerZone::display(const vpImage<vpRGBa> &I, const vpColor &col, const unsigned int thickness)
475 {
476  std::vector<vpImagePoint> ip;
477  for (unsigned int i=0; i < Zone.size(); i++) {
478  vpTemplateTrackerTriangle triangle;
479  Zone[i].getCorners(ip);
480  vpDisplay::displayLine(I, ip[0], ip[1], col, thickness);
481  vpDisplay::displayLine(I, ip[1], ip[2], col, thickness);
482  vpDisplay::displayLine(I, ip[2], ip[0], col, thickness);
483  }
484 }
485 
490 {
491  clear();
492 }
493 
501 void vpTemplateTrackerZone::fillTriangle(vpImage<unsigned char>& I, unsigned int id,unsigned char gray_level)
502 {
503  assert(id < getNbTriangle());
504  vpTemplateTrackerTriangle triangle;
505  getTriangle(id, triangle);
506  for (int i=0 ; i < (int) I.getHeight() ; i++)
507  {
508  for (int j=0 ; j < (int) I.getWidth() ; j++)
509  {
510  if(triangle.inTriangle(i,j))
511  {
512  I[i][j]=gray_level;
513  }
514  }
515  }
516 }
517 
522 {
523  vpTemplateTrackerZone tempZone;
525  vpTemplateTrackerTriangle TtempDown;
526  for(unsigned int i=0;i<getNbTriangle();i++)
527  {
528  getTriangle(i,Ttemp);
529  TtempDown=Ttemp.getPyramidDown();
530  tempZone.add(TtempDown);
531  }
532  return tempZone;
533 }
534 
541 {
542  vpTemplateTrackerTriangle triangle;
543  for(unsigned int i=0;i<z.getNbTriangle();i++)
544  {
545  z.getTriangle(i, triangle);
546  add(triangle);
547  // Update the bounding box
548  if((triangle.getMinx()<min_x)||(min_x==-1))
549  min_x=(int)triangle.getMinx();
550  if((triangle.getMaxx()>max_x)||(max_x==-1))
551  max_x=(int)triangle.getMaxx();
552  if((triangle.getMiny()<min_y)||(min_y==-1))
553  min_y=(int)triangle.getMiny();
554  if((triangle.getMaxy()>max_y)||(max_y==-1))
555  max_y=(int)triangle.getMaxy();
556  }
557 }
558 
566 vpImagePoint vpTemplateTrackerZone::getCenter(int borne_x, int borne_y) const
567 {
568  int cpt_pt=0;
569  double x_center=0,y_center=0;
570  for(int j=0;j<borne_x;j++)
571  for(int i=0;i<borne_y;i++)
572  if(inZone(i,j))
573  {
574  x_center+=j;
575  y_center+=i;
576  cpt_pt++;
577  }
578 
579  if(! cpt_pt) {
581  "Cannot compute the zone center: size = 0")) ;
582  }
583 
584  x_center=x_center/cpt_pt;
585  y_center=y_center/cpt_pt;
586  vpImagePoint center;
587  center.set_uv(x_center, y_center);
588  return center;
589 }
590 
std::vector< vpTemplateTrackerTriangle > Zone
Vector of triangles that defines the zone.
vpTemplateTrackerTriangle getPyramidDown() const
void getTriangle(unsigned int i, vpTemplateTrackerTriangle &T) const
unsigned int getWidth() const
Definition: vpImage.h:159
int max_y
Bounding box parameter.
Class to define colors available for display functionnalities.
Definition: vpColor.h:125
int min_x
Bounding box parameter.
error that can be emited by ViSP classes.
Definition: vpException.h:76
void initClick(const vpImage< unsigned char > &I, bool delaunay=false)
void display(const vpImage< unsigned char > &I, const vpColor &col=vpColor::green, const unsigned int thickness=3)
vpImagePoint getCenter() const
static int wait(double t0, double t)
Definition: vpTime.cpp:149
static const vpColor green
Definition: vpColor.h:170
static void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:1994
void copy(const vpTemplateTrackerZone &z)
static const vpColor red
Definition: vpColor.h:167
void add(const vpTemplateTrackerTriangle &t)
unsigned int getNbTriangle() const
vpTemplateTrackerZone & operator=(const vpTemplateTrackerZone &z)
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
bool inTriangle(const vpImagePoint &ip) const
void initFromPoints(const vpImage< unsigned char > &I, const std::vector< vpImagePoint > &ip, bool delaunay=false)
int min_y
Bounding box parameter.
void setTopLeft(const vpImagePoint &topLeft)
Definition: vpRect.h:279
bool inZone(const int &i, const int &j) const
int max_x
Bounding box parameter.
vpTemplateTrackerZone getPyramidDown() const
unsigned int getHeight() const
Definition: vpImage.h:150
void set_uv(const double u, const double v)
Definition: vpImagePoint.h:238
Defines a rectangle in the plane.
Definition: vpRect.h:85
virtual bool getClick(bool blocking=true)=0
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:92
virtual void displayLine(const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)=0
void setBottomRight(const vpImagePoint &bottomRight)
Definition: vpRect.h:215
void fillTriangle(vpImage< unsigned char > &I, unsigned int id, unsigned char gray_level)
static const vpColor blue
Definition: vpColor.h:173