ViSP  2.10.0
vpMbtDistanceKltPoints.cpp
1 /****************************************************************************
2  *
3  * $Id: vpMbtDistanceKltPoints.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  * Klt polygon, containing points of interest.
35  *
36  * Authors:
37  * Romain Tallonneau
38  * Aurelien Yol
39  *
40  *****************************************************************************/
41 
42 #include <visp/vpMbtDistanceKltPoints.h>
43 
44 #if (defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020100))
45 
51  : H(), N(), N_cur(), invd0(1.), cRc0_0n(), initPoints(), curPoints(), curPointsInd(),
52  nbPointsCur(0), nbPointsInit(0), minNbPoint(4), enoughPoints(false), dt(1.), d0(1.),
53  cam(), polygon(NULL)
54 {
55  initPoints = std::map<int, vpImagePoint>();
56  curPoints = std::map<int, vpImagePoint>();
57  curPointsInd = std::map<int, int>();
58 }
59 
65 {}
66 
74 void
76 {
77  // extract ids of the points in the face
78  nbPointsInit = 0;
79  nbPointsCur = 0;
80  initPoints = std::map<int, vpImagePoint>();
81  curPoints = std::map<int, vpImagePoint>();
82  curPointsInd = std::map<int, int>();
83  std::vector<vpImagePoint> roi;
84  polygon->getRoiClipped(cam, roi);
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(roi, 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  if(nbPointsCur >= minNbPoint) enoughPoints = true;
101  else enoughPoints = false;
102 
103  // initialisation of the value for the computation in SE3
105 
106  d0 = plan.getD();
107  N = plan.getNormal();
108 
109  N.normalize();
110  N_cur = N;
111  invd0 = 1.0 / d0;
112 }
113 
121 unsigned int
123 {
124  int id;
125  float x, y;
126  nbPointsCur = 0;
127  curPoints = std::map<int, vpImagePoint>();
128  curPointsInd = std::map<int, int>();
129 
130  for (unsigned int i = 0; i < static_cast<unsigned int>(_tracker.getNbFeatures()); i++){
131  _tracker.getFeature((int)i, id, x, y);
132  if(isTrackedFeature(id)){
133  curPoints[id] = vpImagePoint(static_cast<double>(y),static_cast<double>(x));
134  curPointsInd[id] = (int)i;
135  nbPointsCur++;
136  }
137  }
138 
139  if(nbPointsCur >= minNbPoint) enoughPoints = true;
140  else enoughPoints = false;
141 
142  return nbPointsCur;
143 }
144 
155 void
157 {
158  unsigned int index_ = 0;
159 
160  std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
161  for( ; iter != curPoints.end(); iter++){
162  int id(iter->first);
163  double i_cur(iter->second.get_i()), j_cur(iter->second.get_j());
164 
165  double x_cur(0), y_cur(0);
166  vpPixelMeterConversion::convertPoint(cam, j_cur, i_cur, x_cur, y_cur);
167 
168  vpImagePoint iP0 = initPoints[id];
169  double x0(0), y0(0);
170  vpPixelMeterConversion::convertPoint(cam, iP0, x0, y0);
171 
172  double x0_transform, y0_transform ;// equivalent x and y in the first image (reference)
173  computeP_mu_t(x0, y0, x0_transform, y0_transform, H );
174 
175  double invZ = compute_1_over_Z(x_cur, y_cur);
176 
177  _J[2*index_][0] = - invZ;
178  _J[2*index_][1] = 0;
179  _J[2*index_][2] = x_cur * invZ;
180  _J[2*index_][3] = x_cur * y_cur;
181  _J[2*index_][4] = -(1+x_cur*x_cur);
182  _J[2*index_][5] = y_cur;
183 
184  _J[2*index_+1][0] = 0;
185  _J[2*index_+1][1] = - invZ;
186  _J[2*index_+1][2] = y_cur * invZ;
187  _J[2*index_+1][3] = (1+y_cur*y_cur);
188  _J[2*index_+1][4] = - y_cur * x_cur;
189  _J[2*index_+1][5] = - x_cur;
190 
191  _R[2*index_] = (x0_transform - x_cur);
192  _R[2*index_+1] = (y0_transform - y_cur);
193  index_++;
194  }
195 }
196 
197 double
198 vpMbtDistanceKltPoints::compute_1_over_Z(const double x, const double y)
199 {
200  double num = cRc0_0n[0] * x + cRc0_0n[1] * y + cRc0_0n[2];
201  double den = -(d0 - dt);
202  return num/den;
203 }
204 
217 inline void
218 vpMbtDistanceKltPoints::computeP_mu_t(const double x_in, const double y_in, double& x_out, double& y_out, const vpMatrix& _cHc0)
219 {
220  double p_mu_t_2 = x_in * _cHc0[2][0] + y_in * _cHc0[2][1] + _cHc0[2][2];
221 
222  if( fabs(p_mu_t_2) < std::numeric_limits<double>::epsilon()){
223  x_out = 0.0;
224  y_out = 0.0;
225  throw vpException(vpException::divideByZeroError, "the depth of the point is calculated to zero");
226  }
227 
228  x_out = (x_in * _cHc0[0][0] + y_in * _cHc0[0][1] + _cHc0[0][2]) / p_mu_t_2;
229  y_out = (x_in * _cHc0[1][0] + y_in * _cHc0[1][1] + _cHc0[1][2]) / p_mu_t_2;
230 }
231 
244 void
246 {
247  vpRotationMatrix cRc0;
248  vpTranslationVector ctransc0;
249 
250  _cTc0.extract(cRc0);
251  _cTc0.extract(ctransc0);
252  vpMatrix cHc0(_cHc0);
253 
254 // vpGEMM(cRc0, 1.0, invd0, cRc0, -1.0, _cHc0, VP_GEMM_A_T);
255  vpGEMM(ctransc0, N, -invd0, cRc0, 1.0, cHc0, VP_GEMM_B_T);
256  cHc0 /= cHc0[2][2];
257 
258  H = cHc0;
259 
260 // vpQuaternionVector NQuat(N[0], N[1], N[2], 0.0);
261 // vpQuaternionVector RotQuat(cRc0);
262 // vpQuaternionVector RotQuatConj(-RotQuat.x(), -RotQuat.y(), -RotQuat.z(), RotQuat.w());
263 // vpQuaternionVector partial = RotQuat * NQuat;
264 // vpQuaternionVector resQuat = (partial * RotQuatConj);
265 //
266 // cRc0_0n = vpColVector(3);
267 // cRc0_0n[0] = resQuat.x();
268 // cRc0_0n[1] = resQuat.y();
269 // cRc0_0n[2] = resQuat.z();
270 
271  cRc0_0n = cRc0*N;
272 
273 // vpPlane p(corners[0], corners[1], corners[2]);
274 // vpColVector Ncur = p.getNormal();
275 // Ncur.normalize();
276  N_cur = cRc0_0n;
277  dt = 0.0;
278  for (unsigned int i = 0; i < 3; i += 1){
279  dt += ctransc0[i] * (N_cur[i]);
280  }
281 }
282 
290 bool
291 vpMbtDistanceKltPoints::isTrackedFeature(const int _id)
292 {
293 // std::map<int, vpImagePoint>::const_iterator iter = initPoints.begin();
294 // while(iter != initPoints.end()){
295 // if(iter->first == _id){
296 // return true;
297 // }
298 // iter++;
299 // }
300 
301  std::map<int, vpImagePoint>::iterator iter = initPoints.find(_id);
302  if(iter != initPoints.end())
303  return true;
304 
305  return false;
306 }
307 
316 void
318 #if (VISP_HAVE_OPENCV_VERSION >= 0x020408)
319  cv::Mat &mask,
320 #else
321  IplImage* mask,
322 #endif
323  unsigned char nb, unsigned int shiftBorder)
324 {
325 #if (VISP_HAVE_OPENCV_VERSION >= 0x020408)
326  int width = mask.cols;
327  int height = mask.rows;
328 #else
329  int width = mask->width;
330  int height = mask->height;
331 #endif
332 
333  int i_min, i_max, j_min, j_max;
334  std::vector<vpImagePoint> roi;
335  polygon->getRoiClipped(cam, roi);
336  vpMbtPolygon::getMinMaxRoi(roi, i_min, i_max, j_min,j_max);
337 
338  /* check image boundaries */
339  if(i_min > height){ //underflow
340  i_min = 0;
341  }
342  if(i_max > height){
343  i_max = height;
344  }
345  if(j_min > width){ //underflow
346  j_min = 0;
347  }
348  if(j_max > width){
349  j_max = width;
350  }
351 
352  double shiftBorder_d = (double) shiftBorder;
353 #if (VISP_HAVE_OPENCV_VERSION >= 0x020408)
354  for(int i=i_min; i< i_max; i++){
355  double i_d = (double) i;
356  for(int j=j_min; j< j_max; j++){
357  double j_d = (double) j;
358  if(shiftBorder != 0){
359  if( vpMbtDistanceKltPoints::isInside(roi, i_d, j_d)
360  && vpMbtDistanceKltPoints::isInside(roi, i_d+shiftBorder_d, j_d+shiftBorder_d)
361  && vpMbtDistanceKltPoints::isInside(roi, i_d-shiftBorder_d, j_d+shiftBorder_d)
362  && vpMbtDistanceKltPoints::isInside(roi, i_d+shiftBorder_d, j_d-shiftBorder_d)
363  && vpMbtDistanceKltPoints::isInside(roi, i_d-shiftBorder_d, j_d-shiftBorder_d) ){
364  mask.at<unsigned char>(i,j) = nb;
365  }
366  }
367  else{
368  if(vpMbtDistanceKltPoints::isInside(roi, i, j)){
369  mask.at<unsigned char>(i,j) = nb;
370  }
371  }
372  }
373  }
374 #else
375  unsigned char* ptrData = (unsigned char*)mask->imageData + i_min*mask->widthStep+j_min;
376  for(int i=i_min; i< i_max; i++){
377  double i_d = (double) i;
378  for(int j=j_min; j< j_max; j++){
379  double j_d = (double) j;
380  if(shiftBorder != 0){
381  if( vpMbtDistanceKltPoints::isInside(roi, i_d, j_d)
382  && vpMbtDistanceKltPoints::isInside(roi, i_d+shiftBorder_d, j_d+shiftBorder_d)
383  && vpMbtDistanceKltPoints::isInside(roi, i_d-shiftBorder_d, j_d+shiftBorder_d)
384  && vpMbtDistanceKltPoints::isInside(roi, i_d+shiftBorder_d, j_d-shiftBorder_d)
385  && vpMbtDistanceKltPoints::isInside(roi, i_d-shiftBorder_d, j_d-shiftBorder_d) ){
386  *(ptrData++) = nb;
387  }
388  else{
389  ptrData++;
390  }
391  }
392  else{
393  if(vpMbtDistanceKltPoints::isInside(roi, i, j)){
394  *(ptrData++) = nb;
395  }
396  else{
397  ptrData++;
398  }
399  }
400  }
401  ptrData += mask->widthStep - j_max + j_min;
402  }
403 #endif
404 }
405 
413 void
414 vpMbtDistanceKltPoints::removeOutliers(const vpColVector& _w, const double &threshold_outlier)
415 {
416  std::map<int, vpImagePoint> tmp;
417  std::map<int, int> tmp2;
418  unsigned int nbSupp = 0;
419  unsigned int k = 0;
420 
421  nbPointsCur = 0;
422  std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
423  for( ; iter != curPoints.end(); iter++){
424  if(_w[k] > threshold_outlier && _w[k+1] > threshold_outlier){
425 // if(_w[k] > threshold_outlier || _w[k+1] > threshold_outlier){
426  tmp[iter->first] = vpImagePoint(iter->second.get_i(), iter->second.get_j());
427  tmp2[iter->first] = curPointsInd[iter->first];
428  nbPointsCur++;
429  }
430  else{
431  nbSupp++;
432  initPoints.erase(iter->first);
433  }
434 
435  k+=2;
436  }
437 
438  if(nbSupp != 0){
439  curPoints = std::map<int, vpImagePoint>();
440  curPointsInd = std::map<int, int>();
441 
442  curPoints = tmp;
443  curPointsInd = tmp2;
444  if(nbPointsCur >= minNbPoint) enoughPoints = true;
445  else enoughPoints = false;
446  }
447 }
448 
454 void
456 {
457  std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
458  for( ; iter != curPoints.end(); iter++){
459  int id(iter->first);
460  vpImagePoint iP;
461  iP.set_i(static_cast<double>(iter->second.get_i()));
462  iP.set_j(static_cast<double>(iter->second.get_j()));
463 
465 
466  iP.set_i( vpMath::round( iP.get_i() + 7 ) );
467  iP.set_j( vpMath::round( iP.get_j() + 7 ) );
468  char ide[10];
469  sprintf(ide, "%ld", static_cast<long int>(id));
470  vpDisplay::displayText(_I, iP, ide, vpColor::red);
471  }
472 }
473 
479 void
481 {
482  std::map<int, vpImagePoint>::const_iterator iter = curPoints.begin();
483  for( ; iter != curPoints.end(); iter++){
484  int id(iter->first);
485  vpImagePoint iP;
486  iP.set_i(static_cast<double>(iter->second.get_i()));
487  iP.set_j(static_cast<double>(iter->second.get_j()));
488 
490 
491  iP.set_i( vpMath::round( iP.get_i() + 7 ) );
492  iP.set_j( vpMath::round( iP.get_j() + 7 ) );
493  char ide[10];
494  sprintf(ide, "%ld", static_cast<long int>(id));
495  vpDisplay::displayText(_I, iP, ide, vpColor::red);
496  }
497 }
498 
499 //###################################
500 // Static functions
501 //###################################
502 
503 bool
504 vpMbtDistanceKltPoints::intersect(const vpImagePoint& p1, const vpImagePoint& p2, const double i_test, const double j_test, const double i, const double j)
505 {
506  double dx = p2.get_j() - p1.get_j();
507  double dy = p2.get_i() - p1.get_i();
508  double ex = j - j_test;
509  double ey = i - i_test;
510 
511  double den = dx * ey - dy * ex;
512  double t = 0, u = 0;
513  //if(den != 0){
514  if(std::fabs(den) > std::fabs(den)*std::numeric_limits<double>::epsilon()){
515  t = -( ey * ( p1.get_j() - j_test ) + ex * ( -p1.get_i() + i_test ) ) / den;
516  u = -( dx * ( -p1.get_i() + i_test ) + dy * ( p1.get_j() - j_test ) ) / den;
517  }
518  else{
519  throw vpException(vpException::divideByZeroError, "denominator null");
520  }
521  return ( t >= std::numeric_limits<double>::epsilon() && t < 1.0 && u >= std::numeric_limits<double>::epsilon() && u < 1.0);
522 }
523 
524 bool
525 vpMbtDistanceKltPoints::isInside(const std::vector<vpImagePoint>& roi, const double i, const double j)
526 {
527  double i_test = 100000.;
528  double j_test = 100000.;
529  unsigned int nbInter = 0;
530  bool computeAgain = true;
531 
532  if(computeAgain){
533  computeAgain = false;
534  for(unsigned int k=0; k< roi.size(); k++){
535  try{
536  if(vpMbtDistanceKltPoints::intersect(roi[k], roi[(k+1)%roi.size()], i, j, i_test, j_test)){
537  nbInter++;
538  }
539  }
540  catch(...){
541  computeAgain = true;
542  break;
543  }
544  }
545 
546  if(computeAgain){
547  i_test += 100;
548  j_test -= 100;
549  nbInter = 0;
550  }
551  }
552  return ((nbInter%2) == 1);
553 }
554 
555 #endif
Definition of the vpMatrix class.
Definition: vpMatrix.h:98
void init(const vpKltOpencv &_tracker)
double get_i() const
Definition: vpImagePoint.h:195
void removeOutliers(const vpColVector &weight, const double &threshold_outlier)
The class provides a data structure for the homogeneous matrices as well as a set of operations on th...
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
Definition: vpDisplay.cpp:887
void getRoiClipped(std::vector< vpPoint > &points)
vpPoint & getPoint(const unsigned int _index)
error that can be emited by ViSP classes.
Definition: vpException.h:76
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...
static int round(const double x)
Definition: vpMath.h:228
double get_j() const
Definition: vpImagePoint.h:206
static const vpColor red
Definition: vpColor.h:167
The vpRotationMatrix considers the particular case of a rotation matrix.
unsigned int computeNbDetectedCurrent(const vpKltOpencv &_tracker)
This class aims to compute the homography wrt.two images.
Definition: vpHomography.h:178
void set_i(const double ii)
Definition: vpImagePoint.h:159
void displayPrimitive(const vpImage< unsigned char > &_I)
virtual void displayCross(const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)=0
void getFeature(const int &index, int &id, float &x, float &y) const
void extract(vpRotationMatrix &R) const
void computeHomography(const vpHomogeneousMatrix &_cTc0, vpHomography &cHc0)
void set_j(const double jj)
Definition: vpImagePoint.h:170
Class that provides a data structure for the column vectors as well as a set of operations on these v...
Definition: vpColVector.h:72
Wrapper for the KLT (Kanade-Lucas-Tomasi) feature tracker implemented in OpenCV.
Definition: vpKltOpencv.h:79
int getNbFeatures() const
Get the number of current features.
Definition: vpKltOpencv.h:121
static void getMinMaxRoi(const std::vector< vpImagePoint > &roi, int &i_min, int &i_max, int &j_min, int &j_max)
vpMbtPolygon * polygon
Pointer to the polygon that define a face.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:93
This class defines the container for a plane geometrical structure.
Definition: vpPlane.h:67
vpColVector & normalize()
Normalise the vector.
Class that consider the case of a translation vector.
void computeInteractionMatrixAndResidu(vpColVector &_R, vpMatrix &_J)
void updateMask(cv::Mat &mask, unsigned char _nb=255, unsigned int _shiftBorder=0)