ViSP  2.8.0
vpMbtKltPolygon.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMbtKltPolygon.cpp 4318 2013-07-17 09:47:51Z fspindle $
4  *
5  * This file is part of the ViSP software.
6  * Copyright (C) 2005 - 2013 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  * Generic model polygon, containing points of interest.
35  *
36  * Authors:
37  * Romain Tallonneau
38  * Aurelien Yol
39  *
40  *****************************************************************************/
41 
42 
43 #include <visp/vpMbtKltPolygon.h>
44 
45 #ifdef VISP_HAVE_OPENCV
46 
52 {
53  minNbPoint = 4;
54  enoughPoints = false;
55 
56  nbPointsInit = 0;
57  nbPointsCur = 0;
58  initPoints = std::map<int, vpImagePoint>();
59  curPoints = std::map<int, vpImagePoint>();
60  curPointsInd = std::map<int, int>();
61 
62  isvisible = false;
63 }
64 
70 {}
71 
79 void
81 {
82  // extract ids of the points in the face
83  nbPointsInit = 0;
84  nbPointsCur = 0;
85  initPoints = std::map<int, vpImagePoint>();
86  curPoints = std::map<int, vpImagePoint>();
87  curPointsInd = std::map<int, int>();
88  std::vector<vpImagePoint> roi;
89  getRoiClipped(cam, roi);
90 
91  for (unsigned int i = 0; i < static_cast<unsigned int>(_tracker.getNbFeatures()); i ++){
92  int id;
93  float x_tmp, y_tmp;
94  _tracker.getFeature((int)i, id, x_tmp, y_tmp);
95 
96  if(isInside(roi, y_tmp, x_tmp)){
97  initPoints[id] = vpImagePoint(y_tmp, x_tmp);
98  curPoints[id] = vpImagePoint(y_tmp, x_tmp);
99  curPointsInd[id] = (int)i;
100  nbPointsInit++;
101  nbPointsCur++;
102  }
103  }
104 
105  // initialisation of the value for the computation in SE3
106  vpPlane plan(p[0], p[1], p[2]);
107 
108  d0 = plan.getD();
109  N = plan.getNormal();
110 
111  N.normalize();
112  N_cur = N;
113  invd0 = 1.0 / d0;
114 }
115 
123 unsigned int
125 {
126  int id;
127  float x, y;
128  nbPointsCur = 0;
129  curPoints = std::map<int, vpImagePoint>();
130  curPointsInd = std::map<int, int>();
131 
132  for (unsigned int i = 0; i < static_cast<unsigned int>(_tracker.getNbFeatures()); i++){
133  _tracker.getFeature((int)i, id, x, y);
134  if(isTrackedFeature(id)){
135  curPoints[id] = vpImagePoint(static_cast<double>(y),static_cast<double>(x));
136  curPointsInd[id] = (int)i;
137  nbPointsCur++;
138  }
139  }
140 
141  if(nbPointsCur >= minNbPoint) enoughPoints = true;
142  else enoughPoints = false;
143 
144  return nbPointsCur;
145 }
146 
157 void
159 {
160  unsigned int index = 0;
161 
162  std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
163  for( ; iter != curPoints.end(); iter++){
164  int id(iter->first);
165  double i_cur(iter->second.get_i()), j_cur(iter->second.get_j());
166 
167  double x_cur(0), y_cur(0);
168  vpPixelMeterConversion::convertPoint(cam, j_cur, i_cur, x_cur, y_cur);
169 
170  vpImagePoint iP0 = initPoints[id];
171  double x0(0), y0(0);
172  vpPixelMeterConversion::convertPoint(cam, iP0, x0, y0);
173 
174  double x0_transform, y0_transform ;// equivalent x and y in the first image (reference)
175  computeP_mu_t(x0, y0, x0_transform, y0_transform, H );
176 
177  double invZ = compute_1_over_Z(x_cur, y_cur);
178 
179  _J[2*index][0] = - invZ;
180  _J[2*index][1] = 0;
181  _J[2*index][2] = x_cur * invZ;
182  _J[2*index][3] = x_cur * y_cur;
183  _J[2*index][4] = -(1+x_cur*x_cur);
184  _J[2*index][5] = y_cur;
185 
186  _J[2*index+1][0] = 0;
187  _J[2*index+1][1] = - invZ;
188  _J[2*index+1][2] = y_cur * invZ;
189  _J[2*index+1][3] = (1+y_cur*y_cur);
190  _J[2*index+1][4] = - y_cur * x_cur;
191  _J[2*index+1][5] = - x_cur;
192 
193  _R[2*index] = (x0_transform - x_cur);
194  _R[2*index+1] = (y0_transform - y_cur);
195  index++;
196  }
197 }
198 
199 double
200 vpMbtKltPolygon::compute_1_over_Z(const double x, const double y)
201 {
202  double num = cRc0_0n[0] * x + cRc0_0n[1] * y + cRc0_0n[2];
203  double den = -(d0 - dt);
204  return num/den;
205 }
206 
219 inline void
220 vpMbtKltPolygon::computeP_mu_t(const double x_in, const double y_in, double& x_out, double& y_out, const vpMatrix& _cHc0)
221 {
222  double p_mu_t_2 = x_in * _cHc0[2][0] + y_in * _cHc0[2][1] + _cHc0[2][2];
223 
224  if( fabs(p_mu_t_2) < std::numeric_limits<double>::epsilon()){
225  x_out = 0.0;
226  y_out = 0.0;
227  throw vpException(vpException::divideByZeroError, "the depth of the point is calculated to zero");
228  }
229 
230  x_out = (x_in * _cHc0[0][0] + y_in * _cHc0[0][1] + _cHc0[0][2]) / p_mu_t_2;
231  y_out = (x_in * _cHc0[1][0] + y_in * _cHc0[1][1] + _cHc0[1][2]) / p_mu_t_2;
232 }
233 
246 void
248 {
249  vpRotationMatrix cRc0;
250  vpTranslationVector ctransc0;
251 
252  _cTc0.extract(cRc0);
253  _cTc0.extract(ctransc0);
254 
255 // vpGEMM(cRc0, 1.0, invd0, cRc0, -1.0, _cHc0, VP_GEMM_A_T);
256  vpGEMM(ctransc0, N, -invd0, cRc0, 1.0, _cHc0, VP_GEMM_B_T);
257  _cHc0 /= _cHc0[2][2];
258 
259  H = _cHc0;
260 
261 // vpQuaternionVector NQuat(N[0], N[1], N[2], 0.0);
262 // vpQuaternionVector RotQuat(cRc0);
263 // vpQuaternionVector RotQuatConj(-RotQuat.x(), -RotQuat.y(), -RotQuat.z(), RotQuat.w());
264 // vpQuaternionVector partial = RotQuat * NQuat;
265 // vpQuaternionVector resQuat = (partial * RotQuatConj);
266 //
267 // cRc0_0n = vpColVector(3);
268 // cRc0_0n[0] = resQuat.x();
269 // cRc0_0n[1] = resQuat.y();
270 // cRc0_0n[2] = resQuat.z();
271 
272  cRc0_0n = cRc0*N;
273 
274 // vpPlane p(corners[0], corners[1], corners[2]);
275 // vpColVector Ncur = p.getNormal();
276 // Ncur.normalize();
277  N_cur = cRc0_0n;
278  dt = 0.0;
279  for (unsigned int i = 0; i < 3; i += 1){
280  dt += ctransc0[i] * (N_cur[i]);
281  }
282 }
283 
291 bool
292 vpMbtKltPolygon::isTrackedFeature(const int _id)
293 {
294 // std::map<int, vpImagePoint>::const_iterator iter = initPoints.begin();
295 // while(iter != initPoints.end()){
296 // if(iter->first == _id){
297 // return true;
298 // }
299 // iter++;
300 // }
301 
302  std::map<int, vpImagePoint>::iterator iter = initPoints.find(_id);
303  if(iter != initPoints.end())
304  return true;
305 
306  return false;
307 }
308 
317 void
318 vpMbtKltPolygon::updateMask(IplImage* _mask, unsigned int _nb, unsigned int _shiftBorder)
319 {
320  int width = _mask->width;
321  int i_min, i_max, j_min, j_max;
322  cam.computeFov((unsigned)_mask->width, (unsigned)_mask->height);
323  computeRoiClipped(cam);
324  std::vector<vpImagePoint> roi;
325  getRoiClipped(cam, roi);
326  vpMbtPolygon::getMinMaxRoi(roi, i_min, i_max, j_min,j_max);
327 
328  /* check image boundaries */
329  if(i_min > _mask->height){ //underflow
330  i_min = 0;
331  }
332  if(i_max > _mask->height){
333  i_max = _mask->height;
334  }
335  if(j_min > _mask->width){ //underflow
336  j_min = 0;
337  }
338  if(j_max > _mask->width){
339  j_max = _mask->width;
340  }
341 
342  double shiftBorder_d = (double) _shiftBorder;
343  char* ptrData = _mask->imageData + i_min*width+j_min;
344  for(int i=i_min; i< i_max; i++){
345  double i_d = (double) i;
346  for(int j=j_min; j< j_max; j++){
347  double j_d = (double) j;
348  if(_shiftBorder != 0){
349  if( vpMbtKltPolygon::isInside(roi, i_d, j_d)
350  && vpMbtKltPolygon::isInside(roi, i_d+shiftBorder_d, j_d+shiftBorder_d)
351  && vpMbtKltPolygon::isInside(roi, i_d-shiftBorder_d, j_d+shiftBorder_d)
352  && vpMbtKltPolygon::isInside(roi, i_d+shiftBorder_d, j_d-shiftBorder_d)
353  && vpMbtKltPolygon::isInside(roi, i_d-shiftBorder_d, j_d-shiftBorder_d) ){
354  *(ptrData++) = _nb;
355  }
356  else{
357  ptrData++;
358  }
359  }
360  else{
361  if(vpMbtKltPolygon::isInside(roi, i, j)){
362  *(ptrData++) = _nb;
363  }
364  else{
365  ptrData++;
366  }
367  }
368  }
369  ptrData += width - j_max + j_min;
370  }
371 
372 }
373 
381 void
382 vpMbtKltPolygon::removeOutliers(const vpColVector& _w, const double &threshold_outlier)
383 {
384  std::map<int, vpImagePoint> tmp;
385  std::map<int, int> tmp2;
386  unsigned int nbSupp = 0;
387  unsigned int k = 0;
388 
389  nbPointsCur = 0;
390  std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
391  for( ; iter != curPoints.end(); iter++){
392  if(_w[k] > threshold_outlier && _w[k+1] > threshold_outlier){
393 // if(_w[k] > threshold_outlier || _w[k+1] > threshold_outlier){
394  tmp[iter->first] = vpImagePoint(iter->second.get_i(), iter->second.get_j());
395  tmp2[iter->first] = curPointsInd[iter->first];
396  nbPointsCur++;
397  }
398  else{
399  nbSupp++;
400  initPoints.erase(iter->first);
401  }
402 
403  k+=2;
404  }
405 
406  if(nbSupp != 0){
407  curPoints = std::map<int, vpImagePoint>();
408  curPointsInd = std::map<int, int>();
409 
410  curPoints = tmp;
411  curPointsInd = tmp2;
412  if(nbPointsCur >= minNbPoint) enoughPoints = true;
413  else enoughPoints = false;
414  }
415 }
416 
422 void
424 {
425  std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
426  for( ; iter != curPoints.end(); iter++){
427  int id(iter->first);
428  vpImagePoint iP;
429  iP.set_i(static_cast<double>(iter->second.get_i()));
430  iP.set_j(static_cast<double>(iter->second.get_j()));
431 
433 
434  iP.set_i( vpMath::round( iP.get_i() + 7 ) );
435  iP.set_j( vpMath::round( iP.get_j() + 7 ) );
436  char ide[10];
437  sprintf(ide, "%ld", static_cast<long int>(id));
439  }
440 }
441 
447 void
449 {
450  std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
451  for( ; iter != curPoints.end(); iter++){
452  int id(iter->first);
453  vpImagePoint iP;
454  iP.set_i(static_cast<double>(iter->second.get_i()));
455  iP.set_j(static_cast<double>(iter->second.get_j()));
456 
458 
459  iP.set_i( vpMath::round( iP.get_i() + 7 ) );
460  iP.set_j( vpMath::round( iP.get_j() + 7 ) );
461  char ide[10];
462  sprintf(ide, "%ld", static_cast<long int>(id));
464  }
465 }
466 
467 //###################################
468 // Static functions
469 //###################################
470 
471 bool vpMbtKltPolygon::intersect(const vpImagePoint& p1, const vpImagePoint& p2, const double i_test, const double j_test, const double i, const double j)
472 {
473  double dx = p2.get_j() - p1.get_j();
474  double dy = p2.get_i() - p1.get_i();
475  double ex = j - j_test;
476  double ey = i - i_test;
477 
478  double den = dx * ey - dy * ex;
479  double t = 0, u = 0;
480  if(den != 0){
481  t = -( ey * ( p1.get_j() - j_test ) + ex * ( -p1.get_i() + i_test ) ) / den;
482  u = -( dx * ( -p1.get_i() + i_test ) + dy * ( p1.get_j() - j_test ) ) / den;
483  }
484  else{
485  throw vpException(vpException::divideByZeroError, "denominator null");
486  }
487  return ( t >= std::numeric_limits<double>::epsilon() && t < 1.0 && u >= std::numeric_limits<double>::epsilon() && u < 1.0);
488 }
489 
490 bool vpMbtKltPolygon::isInside(const std::vector<vpImagePoint>& roi, const double i, const double j)
491 {
492  double i_test = 100000.;
493  double j_test = 100000.;
494  unsigned int nbInter = 0;
495  bool computeAgain = true;
496 
497  if(computeAgain){
498  computeAgain = false;
499  for(unsigned int k=0; k< roi.size(); k++){
500  try{
501  if(vpMbtKltPolygon::intersect(roi[k], roi[(k+1)%roi.size()], i, j, i_test, j_test)){
502  nbInter++;
503  }
504  }
505  catch(...){
506  computeAgain = true;
507  break;
508  }
509  }
510 
511  if(computeAgain){
512  i_test += 100;
513  j_test -= 100;
514  nbInter = 0;
515  }
516  }
517  return ((nbInter%2) == 1);
518 }
519 
520 #endif // VISP_HAVE_OPENCV
void set_j(const double j)
Definition: vpImagePoint.h:156
Definition of the vpMatrix class.
Definition: vpMatrix.h:96
void init(const vpKltOpencv &_tracker)
double get_i() const
Definition: vpImagePoint.h:181
The class provides a data structure for the homogeneous matrices as well as a set of operations on th...
void set_i(const double i)
Definition: vpImagePoint.h:145
int index
Index of the polygon. Cannot be unsigned int because deafult value is -1.
Definition: vpMbtPolygon.h:85
error that can be emited by ViSP classes.
Definition: vpException.h:75
void displayPrimitive(const vpImage< unsigned char > &_I)
static void convertPoint(const vpCameraParameters &cam, const double &u, const double &v, double &x, double &y)
Point coordinates conversion from pixel coordinates to normalized coordinates in meter...
void removeOutliers(const vpColVector &weight, const double &threshold_outlier)
void getRoiClipped(const vpCameraParameters &cam, std::vector< vpImagePoint > &roi)
static int round(const double x)
Definition: vpMath.h:228
double get_j() const
Definition: vpImagePoint.h:192
static const vpColor red
Definition: vpColor.h:167
The vpRotationMatrix considers the particular case of a rotation matrix.
This class aims to compute the homography wrt.two images.
Definition: vpHomography.h:173
unsigned int computeNbDetectedCurrent(const vpKltOpencv &_tracker)
void computeInteractionMatrixAndResidu(vpColVector &_R, vpMatrix &_J)
void getFeature(int index, int &id, float &x, float &y) const
virtual ~vpMbtKltPolygon()
void updateMask(IplImage *_mask, unsigned int _nb=255, unsigned int _shiftBorder=0)
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
void extract(vpRotationMatrix &R) const
void computeHomography(const vpHomogeneousMatrix &_cTc0, vpHomography &cHc0)
void computeRoiClipped(const vpCameraParameters &cam=vpCameraParameters())
vpColVector getNormal() const
Definition: vpPlane.cpp:226
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
virtual void displayCharString(const vpImagePoint &ip, const char *text, const vpColor &color=vpColor::green)=0
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV.
Definition: vpKltOpencv.h:103
int getNbFeatures() const
Get the current number of features.
Definition: vpKltOpencv.h:187
static void getMinMaxRoi(const std::vector< vpImagePoint > &roi, int &i_min, int &i_max, int &j_min, int &j_max)
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:92
This class defines the container for a plane geometrical structure.
Definition: vpPlane.h:67
bool isvisible
flag to specify whether the face is visible or not
Definition: vpMbtPolygon.h:91
vpColVector & normalize()
normalise the vector
Class that consider the case of a translation vector.
double getD() const
Definition: vpPlane.h:118
void computeFov(const unsigned int &w, const unsigned int &h)
vpPoint * p
corners in the object frame
Definition: vpMbtPolygon.h:95