ViSP  2.7.0
vpMbtKltPolygon.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMbtKltPolygon.cpp 4107 2013-02-06 10:04:49Z fspindle $
4  *
5  * Copyright (C) 2005 - 2013 Inria. All rights reserved.
6  *
7  * This software was developed at:
8  * IRISA/INRIA Rennes
9  * Projet Lagadic
10  * Campus Universitaire de Beaulieu
11  * 35042 Rennes Cedex
12  * http://www.irisa.fr/lagadic
13  *
14  * This file is part of the ViSP toolkit
15  *
16  * This file may be distributed under the terms of the Q Public License
17  * as defined by Trolltech AS of Norway and appearing in the file
18  * LICENSE included in the packaging of this file.
19  *
20  * Licensees holding valid ViSP Professional Edition licenses may
21  * use this file in accordance with the ViSP Commercial License
22  * Agreement provided with the Software.
23  *
24  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
25  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
26  *
27  * Contact visp@irisa.fr if any conditions of this licensing are
28  * not clear to you.
29  *
30  * Description:
31  * Generic model polygon, containing points of interest.
32  *
33  * Authors:
34  * Romain Tallonneau
35  * Aurelien Yol
36  *
37  *****************************************************************************/
38 
39 
40 #include <visp/vpMbtKltPolygon.h>
41 
42 #ifdef VISP_HAVE_OPENCV
43 
49 {
50  minNbPoint = 4;
51  enoughPoints = false;
52 
53  nbPointsInit = 0;
54  nbPointsCur = 0;
55  initPoints = std::map<int, vpImagePoint>();
56  curPoints = std::map<int, vpImagePoint>();
57  curPointsInd = std::map<int, int>();
58 
59  isvisible = false;
60 }
61 
67 {}
68 
76 void
78 {
79  // extract ids of the points in the face
80  nbPointsInit = 0;
81  nbPointsCur = 0;
82  initPoints = std::map<int, vpImagePoint>();
83  curPoints = std::map<int, vpImagePoint>();
84  curPointsInd = std::map<int, int>();
85 
86  for (unsigned int i = 0; i < static_cast<unsigned int>(_tracker.getNbFeatures()); i ++){
87  int id;
88  float x_tmp, y_tmp;
89  _tracker.getFeature((int)i, id, x_tmp, y_tmp);
90 
91  if(isInside(getRoi(cam), y_tmp, x_tmp)){
92  initPoints[id] = vpImagePoint(y_tmp, x_tmp);
93  curPoints[id] = vpImagePoint(y_tmp, x_tmp);
94  curPointsInd[id] = (int)i;
95  nbPointsInit++;
96  nbPointsCur++;
97  }
98  }
99 
100  // initialisation of the value for the computation in SE3
101  vpPlane plan(p[0], p[1], p[2]);
102 
103  d0 = plan.getD();
104  N = plan.getNormal();
105 
106  N.normalize();
107  N_cur = N;
108  invd0 = 1.0 / d0;
109 }
110 
118 unsigned int
120 {
121  int id;
122  float x, y;
123  nbPointsCur = 0;
124  curPoints = std::map<int, vpImagePoint>();
125  curPointsInd = std::map<int, int>();
126 
127  for (unsigned int i = 0; i < static_cast<unsigned int>(_tracker.getNbFeatures()); i++){
128  _tracker.getFeature((int)i, id, x, y);
129  if(isTrackedFeature(id)){
130  curPoints[id] = vpImagePoint(static_cast<double>(y),static_cast<double>(x));
131  curPointsInd[id] = (int)i;
132  nbPointsCur++;
133  }
134  }
135 
136  if(nbPointsCur >= minNbPoint) enoughPoints = true;
137  else enoughPoints = false;
138 
139  return nbPointsCur;
140 }
141 
152 void
154 {
155  unsigned int index = 0;
156 
157  std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
158  for( ; iter != curPoints.end(); iter++){
159  int id(iter->first);
160  double i_cur(iter->second.get_i()), j_cur(iter->second.get_j());
161 
162  double x_cur(0), y_cur(0);
163  vpPixelMeterConversion::convertPoint(cam, j_cur, i_cur, x_cur, y_cur);
164 
165  vpImagePoint iP0 = initPoints[id];
166  double x0(0), y0(0);
167  vpPixelMeterConversion::convertPoint(cam, iP0, x0, y0);
168 
169  double x0_transform, y0_transform ;// equivalent x and y in the first image (reference)
170  computeP_mu_t(x0, y0, x0_transform, y0_transform, H );
171 
172  double invZ = compute_1_over_Z(x_cur, y_cur);
173 
174  _J[2*index][0] = - invZ;
175  _J[2*index][1] = 0;
176  _J[2*index][2] = x_cur * invZ;
177  _J[2*index][3] = x_cur * y_cur;
178  _J[2*index][4] = -(1+x_cur*x_cur);
179  _J[2*index][5] = y_cur;
180 
181  _J[2*index+1][0] = 0;
182  _J[2*index+1][1] = - invZ;
183  _J[2*index+1][2] = y_cur * invZ;
184  _J[2*index+1][3] = (1+y_cur*y_cur);
185  _J[2*index+1][4] = - y_cur * x_cur;
186  _J[2*index+1][5] = - x_cur;
187 
188  _R[2*index] = (x0_transform - x_cur);
189  _R[2*index+1] = (y0_transform - y_cur);
190  index++;
191  }
192 }
193 
194 double
195 vpMbtKltPolygon::compute_1_over_Z(const double x, const double y)
196 {
197  double num = cRc0_0n[0] * x + cRc0_0n[1] * y + cRc0_0n[2];
198  double den = -(d0 - dt);
199  return num/den;
200 }
201 
214 inline void
215 vpMbtKltPolygon::computeP_mu_t(const double x_in, const double y_in, double& x_out, double& y_out, const vpMatrix& _cHc0)
216 {
217  double p_mu_t_2 = x_in * _cHc0[2][0] + y_in * _cHc0[2][1] + _cHc0[2][2];
218 
219  if( fabs(p_mu_t_2) < std::numeric_limits<double>::epsilon()){
220  x_out = 0.0;
221  y_out = 0.0;
222  throw vpException(vpException::divideByZeroError, "the depth of the point is calculated to zero");
223  }
224 
225  x_out = (x_in * _cHc0[0][0] + y_in * _cHc0[0][1] + _cHc0[0][2]) / p_mu_t_2;
226  y_out = (x_in * _cHc0[1][0] + y_in * _cHc0[1][1] + _cHc0[1][2]) / p_mu_t_2;
227 }
228 
241 void
243 {
244  vpRotationMatrix cRc0;
245  vpTranslationVector ctransc0;
246 
247  _cTc0.extract(cRc0);
248  _cTc0.extract(ctransc0);
249 
250 // vpGEMM(cRc0, 1.0, invd0, cRc0, -1.0, _cHc0, VP_GEMM_A_T);
251  vpGEMM(ctransc0, N, -invd0, cRc0, 1.0, _cHc0, VP_GEMM_B_T);
252  _cHc0 /= _cHc0[2][2];
253 
254  H = _cHc0;
255 
256 // vpQuaternionVector NQuat(N[0], N[1], N[2], 0.0);
257 // vpQuaternionVector RotQuat(cRc0);
258 // vpQuaternionVector RotQuatConj(-RotQuat.x(), -RotQuat.y(), -RotQuat.z(), RotQuat.w());
259 // vpQuaternionVector partial = RotQuat * NQuat;
260 // vpQuaternionVector resQuat = (partial * RotQuatConj);
261 //
262 // cRc0_0n = vpColVector(3);
263 // cRc0_0n[0] = resQuat.x();
264 // cRc0_0n[1] = resQuat.y();
265 // cRc0_0n[2] = resQuat.z();
266 
267  cRc0_0n = cRc0*N;
268 
269 // vpPlane p(corners[0], corners[1], corners[2]);
270 // vpColVector Ncur = p.getNormal();
271 // Ncur.normalize();
272  N_cur = cRc0_0n;
273  dt = 0.0;
274  for (unsigned int i = 0; i < 3; i += 1){
275  dt += ctransc0[i] * (N_cur[i]);
276  }
277 }
278 
286 bool
287 vpMbtKltPolygon::isTrackedFeature(const int _id)
288 {
289 // std::map<int, vpImagePoint>::const_iterator iter = initPoints.begin();
290 // while(iter != initPoints.end()){
291 // if(iter->first == _id){
292 // return true;
293 // }
294 // iter++;
295 // }
296 
297  std::map<int, vpImagePoint>::iterator iter = initPoints.find(_id);
298  if(iter != initPoints.end())
299  return true;
300  return false;
301 }
302 
311 void
312 vpMbtKltPolygon::updateMask(IplImage* _mask, unsigned int _nb, unsigned int _shiftBorder)
313 {
314  int width = _mask->width;
315  int i_min, i_max, j_min, j_max;
316  std::vector<vpImagePoint> roi = getRoi(cam);
317  vpMbtPolygon::getMinMaxRoi(roi, i_min, i_max, j_min,j_max);
318 
319  /* check image boundaries */
320  if(i_min > _mask->height){ //underflow
321  i_min = 0;
322  }
323  if(i_max > _mask->height){
324  i_max = _mask->height;
325  }
326  if(j_min > _mask->width){ //underflow
327  j_min = 0;
328  }
329  if(j_max > _mask->width){
330  j_max = _mask->width;
331  }
332  double shiftBorder_d = (double) _shiftBorder;
333  char* ptrData = _mask->imageData + i_min*width+j_min;
334  for(int i=i_min; i< i_max; i++){
335  double i_d = (double) i;
336  for(int j=j_min; j< j_max; j++){
337  double j_d = (double) j;
338  if(_shiftBorder != 0){
339  if( vpMbtKltPolygon::isInside(roi, i_d, j_d)
340  && vpMbtKltPolygon::isInside(roi, i_d+shiftBorder_d, j_d+shiftBorder_d)
341  && vpMbtKltPolygon::isInside(roi, i_d-shiftBorder_d, j_d+shiftBorder_d)
342  && vpMbtKltPolygon::isInside(roi, i_d+shiftBorder_d, j_d-shiftBorder_d)
343  && vpMbtKltPolygon::isInside(roi, i_d-shiftBorder_d, j_d-shiftBorder_d) ){
344  *(ptrData++) = _nb;
345  }
346  else{
347  ptrData++;
348  }
349  }
350  else{
351  if(vpMbtKltPolygon::isInside(roi, i, j)){
352  *(ptrData++) = _nb;
353  }
354  else{
355  ptrData++;
356  }
357  }
358  }
359  ptrData += width - j_max + j_min;
360  }
361 }
362 
370 void
371 vpMbtKltPolygon::removeOutliers(const vpColVector& _w, const double &threshold_outlier)
372 {
373  std::map<int, vpImagePoint> tmp;
374  std::map<int, int> tmp2;
375  unsigned int nbSupp = 0;
376  unsigned int k = 0;
377 
378  nbPointsCur = 0;
379  std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
380  for( ; iter != curPoints.end(); iter++){
381  if(_w[k] > threshold_outlier && _w[k+1] > threshold_outlier){
382 // if(_w[k] > threshold_outlier || _w[k+1] > threshold_outlier){
383  tmp[iter->first] = vpImagePoint(iter->second.get_i(), iter->second.get_j());
384  tmp2[iter->first] = curPointsInd[iter->first];
385  nbPointsCur++;
386  }
387  else{
388  nbSupp++;
389  initPoints.erase(iter->first);
390  }
391 
392  k+=2;
393  }
394 
395  if(nbSupp != 0){
396  curPoints = std::map<int, vpImagePoint>();
397  curPointsInd = std::map<int, int>();
398 
399  curPoints = tmp;
400  curPointsInd = tmp2;
401  if(nbPointsCur >= minNbPoint) enoughPoints = true;
402  else enoughPoints = false;
403  }
404 }
405 
411 void
413 {
414  std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
415  for( ; iter != curPoints.end(); iter++){
416  int id(iter->first);
417  vpImagePoint iP;
418  iP.set_i(static_cast<double>(iter->second.get_i()));
419  iP.set_j(static_cast<double>(iter->second.get_j()));
420 
422 
423  iP.set_i( vpMath::round( iP.get_i() + 7 ) );
424  iP.set_j( vpMath::round( iP.get_j() + 7 ) );
425  char ide[10];
426  sprintf(ide, "%ld", static_cast<long int>(id));
428  }
429 }
430 
436 void
438 {
439  std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
440  for( ; iter != curPoints.end(); iter++){
441  int id(iter->first);
442  vpImagePoint iP;
443  iP.set_i(static_cast<double>(iter->second.get_i()));
444  iP.set_j(static_cast<double>(iter->second.get_j()));
445 
447 
448  iP.set_i( vpMath::round( iP.get_i() + 7 ) );
449  iP.set_j( vpMath::round( iP.get_j() + 7 ) );
450  char ide[10];
451  sprintf(ide, "%ld", static_cast<long int>(id));
453  }
454 }
455 
456 //###################################
457 // Static functions
458 //###################################
459 
460 bool vpMbtKltPolygon::intersect(const vpImagePoint& p1, const vpImagePoint& p2, const double i_test, const double j_test, const double i, const double j)
461 {
462  /* denominator */
463  double dx = p2.get_j() - p1.get_j();
464  double dy = p2.get_i() - p1.get_i();
465  double ex = j - j_test;
466  double ey = i - i_test;
467 
468 
469  int den = (int)(dx * ey - dy * ex) ;
470  double t = 0, u = 0;
471  if(den != 0){
472  t = -( p1.get_j() * ey - j_test*ey - ex * p1.get_i() + ex * i_test ) / den;
473  u = -( -dx*p1.get_i() + dx * i_test + dy * p1.get_j() - dy * j_test ) / den;
474  }
475  else{
476  throw vpException(vpException::divideByZeroError, "denominator null");
477  }
478  return ( t >=0 && t < 1 && u >= 0 && u < 1);
479 }
480 
481 bool vpMbtKltPolygon::isInside(const std::vector<vpImagePoint>& roi, const double i, const double j)
482 {
483  double i_test = 1000000.;
484  double j_test = 1000000.;
485  unsigned int nbInter = 0;
486  bool computeAgain = true;
487 
488  if(computeAgain){
489  computeAgain = false;
490  for(unsigned int k=0; k< roi.size(); k++){
491  try{
492  if(vpMbtKltPolygon::intersect(roi[k], roi[(k+1)%roi.size()], i, j, i_test, j_test)){
493  nbInter++;
494  }
495  }
496  catch(...){
497  computeAgain = true;
498  break;
499  }
500  }
501 
502  if(computeAgain){
503  i_test += 100;
504  j_test -= 100;
505  nbInter = 0;
506  }
507  }
508  return ((nbInter%2) == 1);
509 }
510 
511 #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:71
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)
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:165
The vpRotationMatrix considers the particular case of a rotation matrix.
This class aims to compute the homography wrt.two images.
Definition: vpHomography.h:174
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
std::vector< vpImagePoint > getRoi(const vpCameraParameters &_cam)
void extract(vpRotationMatrix &R) const
void computeHomography(const vpHomogeneousMatrix &_cTc0, vpHomography &cHc0)
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 with OpenCV.
Definition: vpKltOpencv.h:141
int getNbFeatures() const
Get the current number of features.
Definition: vpKltOpencv.h:297
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:75
vpColVector & normalize()
normalise the vector
Class that consider the case of a translation vector.
double getD() const
Definition: vpPlane.h:118
vpPoint * p
corners in the object frame
Definition: vpMbtPolygon.h:79