ViSP  2.10.0
vpTemplateTrackerZone.cpp
1 /****************************************************************************
2  *
3  * $Id: vpTemplateTrackerZone.cpp 5119 2015-01-05 10:02:46Z 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 
150  if (button == vpMouseButton::button3)
151  end = true;
152  }
153 
154  vpTime::wait(20);
155  vpDisplay::flush(I);
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(vip.size() == 3) {
176  initFromPoints(I, vip, false);
177  }
178  else if(vip.size() == 4) {
179  std::vector<vpImagePoint> vip_delaunay;
180  vip_delaunay.push_back(vip[0]);
181  vip_delaunay.push_back(vip[1]);
182  vip_delaunay.push_back(vip[2]);
183  vip_delaunay.push_back(vip[2]);
184  vip_delaunay.push_back(vip[3]);
185  vip_delaunay.push_back(vip[0]);
186  initFromPoints(I, vip_delaunay, false);
187  }
188  else {
189 #if VISP_HAVE_OPENCV_VERSION >= 0x020300
190  // Init Delaunay
191  cv::Subdiv2D subdiv(cv::Rect(0, 0, (int)I.getWidth(), (int)I.getHeight()));
192  for(size_t i=0; i< vip.size(); i++) {
193  cv::Point2f fp((float)vip[i].get_u(), (float)vip[i].get_v());
194  //std::cout << "Click point: " << vip[i] << std::endl;
195  subdiv.insert(fp);
196  }
197 
198  // Compute Delaunay triangulation
199  std::vector<cv::Vec6f> triangleList;
200  subdiv.getTriangleList(triangleList);
201 
202  // Keep only the Delaunay points that are inside the area
203  vpRect rect(0, 0, I.getWidth(), I.getHeight());
204 
205  std::vector<vpImagePoint> vip_delaunay;
206  for( size_t i = 0; i < triangleList.size(); i++ ) {
207  cv::Vec6f t = triangleList[i];
208  std::vector<vpImagePoint> p(3);
209 
210  p[0].set_uv(t[0], t[1]);
211  p[1].set_uv(t[2], t[3]);
212  p[2].set_uv(t[4], t[5]);
213 
214  if (p[0].inRectangle(rect) && p[1].inRectangle(rect) && p[2].inRectangle(rect)) {
215  vip_delaunay.push_back(p[0]);
216  vip_delaunay.push_back(p[1]);
217  vip_delaunay.push_back(p[2]);
218  }
219  }
220 
221  initFromPoints(I, vip_delaunay, false);
222 #else
223  throw vpException(vpException::functionNotImplementedError,"Delaunay triangulation is not available!");
224 #endif
225  }
226  }
227  else {
228  Zone.clear();
229  for(unsigned int i=0; i<vip.size(); i+=3) {
230  vpTemplateTrackerTriangle triangle(vip[i], vip[i+1], vip[i+2]);
231  add(triangle);
232 
233 // vpDisplay::displayLine(I, vip[i], vip[i+1], vpColor::green, 1);
234 // vpDisplay::displayLine(I, vip[i+1], vip[i+2], vpColor::green, 1);
235 // vpDisplay::displayLine(I, vip[i+2], vip[i], vpColor::green,1);
236 // vpDisplay::flush(I) ;
237 
238  // Update the bounding box
239  if((triangle.getMinx()<min_x)||(min_x==-1))
240  min_x=(int)triangle.getMinx();
241  if((triangle.getMaxx()>max_x)||(max_x==-1))
242  max_x=(int)triangle.getMaxx();
243  if((triangle.getMiny()<min_y)||(min_y==-1))
244  min_y=(int)triangle.getMiny();
245  if((triangle.getMaxy()>max_y)||(max_y==-1))
246  max_y=(int)triangle.getMaxy();
247  }
248  }
249 }
250 
256 {
257  Zone.push_back(t);
258 
259  // Update the bounding box
260  if((t.getMinx()<min_x)||(min_x==-1))
261  min_x=(int)t.getMinx();
262  if((t.getMaxx()>max_x)||(max_x==-1))
263  max_x=(int)t.getMaxx();
264  if((t.getMiny()<min_y)||(min_y==-1))
265  min_y=(int)t.getMiny();
266  if((t.getMaxy()>max_y)||(max_y==-1))
267  max_y=(int)t.getMaxy();
268 }
269 
275 bool vpTemplateTrackerZone::inZone(const int &i, const int &j) const
276 {
277  std::vector<vpTemplateTrackerTriangle>::const_iterator Iterateurvecteur;
278  for(Iterateurvecteur=Zone.begin();Iterateurvecteur!=Zone.end();Iterateurvecteur++)
279  {
280  if(Iterateurvecteur->inTriangle(i,j))
281  return true;
282  }
283  return false;
284 }
285 
291 bool vpTemplateTrackerZone::inZone(const double &i,const double &j) const
292 {
293  std::vector<vpTemplateTrackerTriangle>::const_iterator Iterateurvecteur;
294  for(Iterateurvecteur=Zone.begin();Iterateurvecteur!=Zone.end();Iterateurvecteur++)
295  {
296  if(Iterateurvecteur->inTriangle(i,j))
297  return true;
298  }
299  return false;
300 }
301 
309 bool vpTemplateTrackerZone::inZone(const int &i,const int &j, unsigned int &id_triangle) const
310 {
311  unsigned int id=0;
312  std::vector<vpTemplateTrackerTriangle>::const_iterator Iterateurvecteur;
313  for(Iterateurvecteur=Zone.begin();Iterateurvecteur!=Zone.end();Iterateurvecteur++)
314  {
315  if(Iterateurvecteur->inTriangle(i,j))
316  {
317  id_triangle=id;
318  return true;
319  }
320  id++;
321  }
322  return false;
323 }
324 
332 bool vpTemplateTrackerZone::inZone(const double &i,const double &j, unsigned int &id_triangle) const
333 {
334  unsigned int id=0;
335  std::vector<vpTemplateTrackerTriangle>::const_iterator Iterateurvecteur;
336  for(Iterateurvecteur=Zone.begin();Iterateurvecteur!=Zone.end();Iterateurvecteur++)
337  {
338  if(Iterateurvecteur->inTriangle(i,j))
339  {
340  id_triangle=id;
341  return true;
342  }
343  id++;
344  }
345  return false;
346 }
347 
365 {
366  if (i > getNbTriangle()-1)
367  throw(vpException(vpException::badValue, "Cannot get triangle with index %u", i));
368 
369  T = Zone[i];
370 }
386 {
387  if (i > getNbTriangle()-1)
388  throw(vpException(vpException::badValue, "Cannot get triangle with index %u", i));
389 
390  return Zone[i];
391 }
397 {
398  double xc=0;
399  double yc=0;
400  int cpt=0;
401  for(int i=min_y;i<max_y;i++)
402  for(int j=min_x;j<max_x;j++)
403  if(inZone(i,j))
404  {
405  xc+=j;
406  yc+=i;
407  cpt ++;
408  }
409  if(! cpt) {
411  "Cannot compute the zone center: size = 0")) ;
412  }
413  xc=xc/cpt;
414  yc=yc/cpt;
415  vpImagePoint ip;
416  ip.set_uv(xc, yc);
417  return ip;
418 }
419 
425 {
426  return max_x;
427 }
433 {
434  return max_y;
435 }
441 {
442  return min_x;
443 }
449 {
450  return min_y;
451 }
452 
458 {
459  vpRect bbox;
462  return bbox;
463 }
464 
471 void vpTemplateTrackerZone::display(const vpImage<unsigned char> &I, const vpColor &col, const unsigned int thickness)
472 {
473  std::vector<vpImagePoint> ip;
474  for (unsigned int i=0; i < Zone.size(); i++) {
475  vpTemplateTrackerTriangle triangle;
476  Zone[i].getCorners(ip);
477  vpDisplay::displayLine(I, ip[0], ip[1], col, thickness);
478  vpDisplay::displayLine(I, ip[1], ip[2], col, thickness);
479  vpDisplay::displayLine(I, ip[2], ip[0], col, thickness);
480  }
481 }
482 
489 void vpTemplateTrackerZone::display(const vpImage<vpRGBa> &I, const vpColor &col, const unsigned int thickness)
490 {
491  std::vector<vpImagePoint> ip;
492  for (unsigned int i=0; i < Zone.size(); i++) {
493  vpTemplateTrackerTriangle triangle;
494  Zone[i].getCorners(ip);
495  vpDisplay::displayLine(I, ip[0], ip[1], col, thickness);
496  vpDisplay::displayLine(I, ip[1], ip[2], col, thickness);
497  vpDisplay::displayLine(I, ip[2], ip[0], col, thickness);
498  }
499 }
500 
505 {
506  clear();
507 }
508 
516 void vpTemplateTrackerZone::fillTriangle(vpImage<unsigned char>& I, unsigned int id,unsigned char gray_level)
517 {
518  assert(id < getNbTriangle());
519  vpTemplateTrackerTriangle triangle;
520  getTriangle(id, triangle);
521  for (int i=0 ; i < (int) I.getHeight() ; i++)
522  {
523  for (int j=0 ; j < (int) I.getWidth() ; j++)
524  {
525  if(triangle.inTriangle(i,j))
526  {
527  I[i][j]=gray_level;
528  }
529  }
530  }
531 }
532 
537 {
538  vpTemplateTrackerZone tempZone;
540  vpTemplateTrackerTriangle TtempDown;
541  for(unsigned int i=0;i<getNbTriangle();i++)
542  {
543  getTriangle(i,Ttemp);
544  TtempDown=Ttemp.getPyramidDown();
545  tempZone.add(TtempDown);
546  }
547  return tempZone;
548 }
549 
556 {
557  vpTemplateTrackerTriangle triangle;
558  for(unsigned int i=0;i<z.getNbTriangle();i++)
559  {
560  z.getTriangle(i, triangle);
561  add(triangle);
562  // Update the bounding box
563  if((triangle.getMinx()<min_x)||(min_x==-1))
564  min_x=(int)triangle.getMinx();
565  if((triangle.getMaxx()>max_x)||(max_x==-1))
566  max_x=(int)triangle.getMaxx();
567  if((triangle.getMiny()<min_y)||(min_y==-1))
568  min_y=(int)triangle.getMiny();
569  if((triangle.getMaxy()>max_y)||(max_y==-1))
570  max_y=(int)triangle.getMaxy();
571  }
572 }
573 
581 vpImagePoint vpTemplateTrackerZone::getCenter(int borne_x, int borne_y) const
582 {
583  int cpt_pt=0;
584  double x_center=0,y_center=0;
585  for(int j=0;j<borne_x;j++)
586  for(int i=0;i<borne_y;i++)
587  if(inZone(i,j))
588  {
589  x_center+=j;
590  y_center+=i;
591  cpt_pt++;
592  }
593 
594  if(! cpt_pt) {
596  "Cannot compute the zone center: size = 0")) ;
597  }
598 
599  x_center=x_center/cpt_pt;
600  y_center=y_center/cpt_pt;
601  vpImagePoint center;
602  center.set_uv(x_center, y_center);
603  return center;
604 }
605 
610 {
611  double area = 0;
612  vpTemplateTrackerTriangle triangle;
613  for (unsigned int i=0; i < getNbTriangle(); i++) {
614  getTriangle(i, triangle);
615  area += triangle.getArea();
616  }
617  return area;
618 }
619 
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:161
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 void flush(const vpImage< unsigned char > &I)
Definition: vpDisplay.cpp:2232
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:289
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:152
void set_uv(const double u, const double v)
Definition: vpImagePoint.h:239
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:93
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:225
void fillTriangle(vpImage< unsigned char > &I, unsigned int id, unsigned char gray_level)
static const vpColor blue
Definition: vpColor.h:173