Main MRPT website > C++ reference for MRPT 1.9.9
CFaceDetection.cpp
Go to the documentation of this file.
1 /* +------------------------------------------------------------------------+
2  | Mobile Robot Programming Toolkit (MRPT) |
3  | http://www.mrpt.org/ |
4  | |
5  | Copyright (c) 2005-2017, Individual contributors, see AUTHORS file |
6  | See: http://www.mrpt.org/Authors - All rights reserved. |
7  | Released under BSD License. See details in http://www.mrpt.org/License |
8  +------------------------------------------------------------------------+ */
9 
10 #include "detectors-precomp.h" // Precompiled headers
11 #include <mrpt/gui.h>
13 
15 #include <mrpt/math.h>
18 #include <mrpt/opengl/CSphere.h>
19 #include <mrpt/opengl/CArrow.h>
21 #include <mrpt/opengl/CAxis.h>
22 
24 #include <mrpt/slam/CICP.h>
25 
26 // Universal include for all versions of OpenCV
27 #include <mrpt/otherlibs/do_opencv_includes.h>
28 
29 using namespace std;
30 using namespace mrpt;
31 using namespace mrpt::detectors;
32 using namespace mrpt::math;
33 using namespace mrpt::gui;
34 using namespace mrpt::math;
35 using namespace mrpt::utils;
36 using namespace mrpt::opengl;
37 using namespace mrpt::system;
38 using namespace mrpt::maps;
39 using namespace mrpt::obs;
40 
41 //------------------------------------------------------------------------
42 // CFaceDetection
43 //------------------------------------------------------------------------
44 CFaceDetection::CFaceDetection() : m_end_threads(false)
45 {
48 
49  m_measure.faceNum = 0;
50 
51  m_timeLog.enable();
52 }
53 
54 //------------------------------------------------------------------------
55 // ~CFaceDetection
56 //------------------------------------------------------------------------
58 {
59  // Stop filters threads
60 
61  m_end_threads = true;
62 
63  m_enter_checkIfFacePlaneCov.set_value();
64  m_enter_checkIfFaceRegions.set_value();
66 
70 }
71 
72 //------------------------------------------------------------------------
73 // init
74 //------------------------------------------------------------------------
76 {
78  cfg.read_int("FaceDetection", "confidenceThreshold", 240);
79  m_options.multithread = cfg.read_bool("FaceDetection", "multithread", true);
81  cfg.read_bool("FaceDetection", "useCovFilter", true);
83  cfg.read_bool("FaceDetection", "useRegionsFilter", true);
85  cfg.read_bool("FaceDetection", "useSizeDistanceRelationFilter", true);
87  cfg.read_bool("FaceDetection", "useDiagonalDistanceFilter", true);
88 
90  cfg.read_double("FaceDetection", "planeThreshold", 50);
92  cfg.read_double("FaceDetection", "planeTest_eigenVal_top", 0.011);
94  cfg.read_double("FaceDetection", "planeTest_eigenVal_bottom", 0.0002);
96  "FaceDetection", "regionsTest_sumDistThreshold_top", 0.5);
98  "FaceDetection", "regionsTest_sumDistThreshold_bottom", 0.04);
99 
100  m_measure.takeTime = cfg.read_bool("FaceDetection", "takeTime", false);
102  cfg.read_bool("FaceDetection", "takeMeasures", false);
104  cfg.read_bool("FaceDetection", "saveMeasurementsToFile", false);
105 
106  // Run filters threads
108  {
111  std::thread(dummy_checkIfFaceRegions, this);
114  std::thread(dummy_checkIfFacePlaneCov, this);
118  std::thread(dummy_checkIfDiagonalSurface, this);
119 
123  }
124 
125  cascadeClassifier.init(cfg);
126 }
127 
128 //------------------------------------------------------------------------
129 // detectObjects
130 //------------------------------------------------------------------------
133 {
134  MRPT_START
135 
136  // Detect possible faces
137  vector_detectable_object localDetected;
138 
139  // To obtain experimental results
140  {
141  if (m_measure.takeTime) m_timeLog.enter("Detection time");
142  }
143 
144  cascadeClassifier.detectObjects(obs, localDetected);
145 
146  // To obtain experimental results
147  {
148  if (m_measure.takeTime) m_timeLog.leave("Detection time");
149 
150  // if ( m_measure.takeMeasures )
151  m_measure.numPossibleFacesDetected += localDetected.size();
152  }
153 
154  // Check if we are using a 3D Camera and 3D points are saved
155  if ((IS_CLASS(obs, CObservation3DRangeScan)) && (localDetected.size() > 0))
156  {
157  // To obtain experimental results
158  {
159  if (m_measure.takeTime) m_timeLog.enter("Check if real face time");
160  }
161 
163  const_cast<CObservation*>(obs));
164 
165  if (o->hasPoints3D)
166  {
167  // Vector to save detected objects to delete if they aren't a face
168  vector<size_t> deleteDetected;
169 
170  // Check if all possible detected faces satisfy a serial of
171  // constrains
172  for (unsigned int i = 0; i < localDetected.size(); i++)
173  {
174  CDetectable2D::Ptr rec =
175  std::dynamic_pointer_cast<CDetectable2D>(localDetected[i]);
176 
177  // Calculate initial and final rows and columns
178  unsigned int r1 = rec->m_y;
179  unsigned int r2 = rec->m_y + rec->m_height;
180  unsigned int c1 = rec->m_x;
181  unsigned int c2 = rec->m_x + rec->m_width;
182 
183  o->getZoneAsObs(m_lastFaceDetected, r1, r2, c1, c2);
184 
186  {
187  // To obtain experimental results
188  {
189  if (m_measure.takeTime)
190  m_timeLog.enter("Multithread filters application");
191  }
192 
193  // Semaphores signal
195  m_enter_checkIfFacePlaneCov.set_value();
197  m_enter_checkIfFaceRegions.set_value();
200  m_enter_checkIfDiagonalSurface.set_value();
201 
202  // Semaphores wait
204  m_leave_checkIfFacePlaneCov.get_future().wait();
206  m_leave_checkIfFaceRegions.get_future().wait();
209  m_leave_checkIfDiagonalSurface.get_future().wait();
210 
211  // Check resutls
215  deleteDetected.push_back(i);
216 
217  // To obtain experimental results
218  {
219  if (m_measure.takeTime)
220  m_timeLog.leave("Multithread filters application");
221  }
222 
223  m_measure.faceNum++;
224  }
225  else
226  {
227  // To obtain experimental results
228  {
229  if (m_measure.takeTime)
230  m_timeLog.enter("Secuential filters application");
231  }
232 
233  /////////////////////////////////////////////////////
234  // CMatrixTemplate<bool> region;
235  // experimental_segmentFace( m_lastFaceDetected, region);
236  /////////////////////////////////////////////////////
237 
238  // m_lastFaceDetected.intensityImage.saveToFile(format("%i.jpg",m_measure.faceNum));
239 
240  bool remove = false;
241 
242  // First check if we can adjust a plane to detected region
243  // as face, if yes it isn't a face!
244  if (m_options.useCovFilter &&
246  {
247  deleteDetected.push_back(i);
248  remove = true;
249  }
250  else if (
253  {
254  deleteDetected.push_back(i);
255  remove = true;
256  }
257  else if (
261  {
262  deleteDetected.push_back(i);
263  remove = true;
264  }
265 
266  if (remove)
267  {
268  /*ofstream f;
269  f.open("deleted.txt", ofstream::app);
270  f << "Deleted: " << m_measure.faceNum << endl;
271  f.close();*/
273  }
274 
275  m_measure.faceNum++;
276 
277  // To obtain experimental results
278  {
279  if (m_measure.takeTime)
280  m_timeLog.leave("Secuential filters application");
281  }
282  }
283  }
284 
285  // Delete non faces
286  for (unsigned int i = deleteDetected.size(); i > 0; i--)
287  localDetected.erase(
288  localDetected.begin() + deleteDetected[i - 1]);
289  }
290 
291  // Convert 2d detected objects to 3d
292  for (unsigned int i = 0; i < localDetected.size(); i++)
293  {
295  new CDetectable3D(
296  std::dynamic_pointer_cast<CDetectable2D>(
297  localDetected[i])));
298  detected.push_back(object3d);
299  }
300 
301  // To obtain experimental results
302  {
303  if (m_measure.takeTime) m_timeLog.leave("Check if real face time");
304  }
305  }
306  else // Not using a 3D camera
307  {
308  detected = localDetected;
309  }
310 
311  // To obtain experimental results
312  {
313  // if ( m_measure.takeMeasures )
314  m_measure.numRealFacesDetected += detected.size();
315  }
316 
317  MRPT_END
318 }
319 
320 //------------------------------------------------------------------------
321 // checkIfFacePlane
322 //------------------------------------------------------------------------
324 {
325  vector<TPoint3D> points;
326 
327  size_t N = face->points3D_x.size();
328 
329  points.resize(N);
330 
331  for (size_t i = 0; i < N; i++)
332  points[i] = TPoint3D(
333  face->points3D_x.at(i), face->points3D_y.at(i),
334  face->points3D_z.at(i));
335 
336  // Try to ajust a plane
337  TPlane plane;
338 
339  // To obtain experimental results
340  {
342  m_measure.errorEstimations.push_back(
343  (double)getRegressionPlane(points, plane));
344  }
345 
347  return true;
348 
349  return false;
350 }
351 
353 {
354  obj->thread_checkIfFacePlaneCov();
355 }
356 
358 {
359  for (;;)
360  {
361  m_enter_checkIfFacePlaneCov.get_future().wait();
362 
363  if (m_end_threads) break;
364 
365  // Perform filter
367 
368  m_leave_checkIfFacePlaneCov.set_value();
369  }
370 }
371 
372 //------------------------------------------------------------------------
373 // checkIfFacePlaneCov
374 //------------------------------------------------------------------------
376 {
378 
379  // To obtain experimental results
380  {
381  if (m_measure.takeTime)
382  m_timeLog.enter("Check if face plane: covariance");
383  }
384 
385  // Get face region size
386  const unsigned int faceWidth = face->intensityImage.getWidth();
387  const unsigned int faceHeight = face->intensityImage.getHeight();
388 
389  // We work with a confidence image?
390  const bool confidence = face->hasConfidenceImage;
391 
392  // To fill with valid points
393  vector<CArrayDouble<3>> pointsVector;
394 
395  CMatrixTemplate<bool> region; // To save the segmented region
396  experimental_segmentFace(*face, region);
397 
398  for (unsigned int j = 0; j < faceHeight; j++)
399  {
400  for (unsigned int k = 0; k < faceWidth; k++)
401  {
402  CArrayDouble<3> aux;
403 
404  if (region.get_unsafe(j, k) &&
405  (((!confidence) ||
406  ((confidence) &&
407  (*(face->confidenceImage.get_unsafe(k, j, 0)) >
409  (*(face->intensityImage.get_unsafe(k, j)) >
410  50))))) // Don't take in account dark pixels
411  {
412  int position = faceWidth * j + k;
413  aux[0] = face->points3D_x[position];
414  aux[1] = face->points3D_y[position];
415  aux[2] = face->points3D_z[position];
416  pointsVector.push_back(aux);
417  }
418  }
419  }
420 
421  // Check if points vector is empty to avoid a future crash
422  if (pointsVector.empty()) return false;
423 
424  // experimental_viewFacePointsScanned( *face );
425 
426  // To obtain the covariance vector and eigenvalues
428  CMatrixDouble eVects, m_eVals;
429  CVectorDouble eVals;
430 
431  cov = covVector<vector<CArrayDouble<3>>, CMatrixDouble>(pointsVector);
432 
433  cov.eigenValues(eVals);
434 
435  cov.eigenVectors(eVects, m_eVals);
436 
437  // To obtain experimental results
438  {
439  if (m_measure.takeMeasures) m_measure.lessEigenVals.push_back(eVals[0]);
440 
441  if (m_measure.takeTime)
442  m_timeLog.leave("Check if face plane: covariance");
443 
444  // Uncomment if you want to analyze the calculated eigenvalues
445  // ofstream f;
446  /*f.open("eigenvalues.txt", ofstream::app);
447  f << m_measure.faceNum << " " << eVals[0] << endl;
448  f.close();*/
449 
450  // f.open("eigenvalues2.txt", ofstream::app);
451  cout << eVals[0] << " " << eVals[1] << " " << eVals[2] << " > ";
452  cout << eVals[0] / eVals[2] << endl;
453  // f << eVals[0]/eVals[2] << endl;
454  // f.close();
455  }
456 
457  if (m_measure.faceNum >= 314)
458  experimental_viewFacePointsAndEigenVects(pointsVector, eVects, eVals);
459 
460  // Check if the less eigenvalue is out of the permited area
461  // if ( ( eVals[0] > m_options.planeEigenValThreshold_down )
462  // && ( eVals[0] < m_options.planeEigenValThreshold_up ) )
463  if (eVals[0] / eVals[2] > 0.06)
464  {
465  // Uncomment if you want to save the face regions discarted by this
466  // filter
467  /*ofstream f;
468  f.open("deletedCOV.txt", ofstream::app);
469  f << m_measure.faceNum << endl;
470  f.close();*/
471 
472  return true; // Filter not passed
473  }
474 
475  return false; // Filter passed
476 
478 }
479 
481 {
482  obj->thread_checkIfFaceRegions();
483 }
484 
486 {
487  for (;;)
488  {
489  m_enter_checkIfFaceRegions.get_future().wait();
490 
491  if (m_end_threads) break;
492 
493  // Perform filter
495 
496  m_leave_checkIfFaceRegions.set_value();
497  }
498 }
499 
500 //------------------------------------------------------------------------
501 // checkIfFaceRegions
502 //------------------------------------------------------------------------
503 
505 {
506  MRPT_START
507 
508  // To obtain experimental results
509  {
510  if (m_measure.takeTime) m_timeLog.enter("Check if face plane: regions");
511  }
512 
513  // To obtain region size
514  const unsigned int faceWidth = face->intensityImage.getWidth();
515  const unsigned int faceHeight = face->intensityImage.getHeight();
516 
517  // Initial vertical size of a region
518  unsigned int sectionVSize = faceHeight / 3.0;
519 
520  // Steps of this filter
521  // 1. To segment the region detected as face using a regions growing
522  // algorithm
523  // 2. To obtain the first and last column to work (a profile face detected
524  // can have a lateral area without to use)
525  // 3. To calculate the histogram of the upper zone of the region for
526  // determine if we use it (if this zone present
527  // a lot of dark pixels the measurements can be wrong)
528  // 4. To obtain the coordinates of pixels that form each subregion
529  // 5. To calculate medians or means of each subregion
530  // 6. To check subregions constrains
531 
532  vector<TPoint3D> points;
533 
534  TPoint3D meanPos[3][3] = {
535  {TPoint3D(0, 0, 0), TPoint3D(0, 0, 0), TPoint3D(0, 0, 0)},
536  {TPoint3D(0, 0, 0), TPoint3D(0, 0, 0), TPoint3D(0, 0, 0)},
537  {TPoint3D(0, 0, 0), TPoint3D(0, 0, 0), TPoint3D(0, 0, 0)}};
538  int numPoints[3][3] = {{0, 0, 0}, {0, 0, 0}, {0, 0, 0}};
539 
540  vector<TPoint3D> regions2[9];
541 
542  //
543  // 1. To segment the region detected as face using a regions growing
544  // algorithm
545  //
546 
547  CMatrixTemplate<bool> region; // To save the segmented region
548  experimental_segmentFace(*face, region);
549 
550  //
551  // 2. To obtain the first and last column to work (a profile face detected
552  // can have a lateral area without to use)
553  //
554 
555  size_t start = faceWidth, end = 0;
556 
557  for (size_t r = 0; r < region.getRowCount(); r++)
558  for (size_t c = 1; c < region.getColCount(); c++)
559  {
560  if ((!(region.get_unsafe(r, c - 1))) && (region.get_unsafe(r, c)))
561  {
562  if (c < start) start = c;
563  }
564  else if (
565  (region.get_unsafe(r, c - 1)) && (!(region.get_unsafe(r, c))))
566  if (c > end) end = c;
567 
568  if ((c > end) && (region.get_unsafe(r, c))) end = c;
569  }
570 
571  if (end == 0) end = faceWidth - 1; // Check if the end has't changed
572  if (end < 3 * (faceWidth / 4))
573  end = 3 * (faceWidth / 4); // To avoid spoiler
574  if (start == faceWidth) start = 0; // Check if the start has't changed
575  if (start > faceWidth / 4) start = faceWidth / 4; // To avoid spoiler
576 
577  // cout << "Start: " << start << " End: " << end << endl;
578 
579  // To use the start and end calculated to obtain the final regions limits
580  unsigned int utilWidth = faceWidth - start - (faceWidth - end);
581  unsigned int c1 = ceil(utilWidth / 3.0 + start);
582  unsigned int c2 = ceil(2 * (utilWidth / 3.0) + start);
583 
584  //
585  // 3. To calculate the histogram of the upper zone of the region for
586  // determine if we use it
587  //
588 
590  hist.setSize(1, 256, true);
592  face->intensityImage, start, 0, end, ceil(faceHeight * 0.1), hist);
593 
594  size_t countHist = 0;
595  for (size_t i = 0; i < 60; i++)
596  {
597  countHist += hist.get_unsafe(0, i);
598  }
599 
600  size_t upLimit = 0;
601  size_t downLimit = faceHeight - 1;
602 
603  if (countHist > 10)
604  {
605  upLimit = floor(faceHeight * 0.1);
606  downLimit = floor(faceHeight * 0.9);
607  }
608 
609  // Uncomment it if you want to analyze the number of pixels that have more
610  // dark that the 60 gray tone
611  // m_meanHist.push_back( countHist );
612 
613  //
614  // 4. To obtain the coordinates of pixels that form each region
615  //
616 
617  unsigned int cont = 0;
618 
619  for (unsigned int r = 0; r < faceHeight; r++)
620  {
621  for (unsigned int c = 0; c < faceWidth; c++, cont++)
622  {
623  if ((r >= upLimit) && (r <= downLimit) &&
624  (region.get_unsafe(r, c)) &&
625  (*(face->confidenceImage.get_unsafe(c, r, 0)) >
627  (*(face->intensityImage.get_unsafe(c, r)) > 50))
628  {
629  unsigned int row, col;
630  if (r < sectionVSize + upLimit * 0.3)
631  row = 0;
632  else if (r < sectionVSize * 2 - upLimit * 0.15)
633  row = 1;
634  else
635  row = 2;
636 
637  if (c < c1)
638  col = 0;
639  else if (c < c2)
640  col = 1;
641  else
642  col = 2;
643 
644  TPoint3D point(
645  face->points3D_x[cont], face->points3D_y[cont],
646  face->points3D_z[cont]);
647  meanPos[row][col] = meanPos[row][col] + point;
648 
649  ++numPoints[row][col];
650 
651  if (row == 0 && col == 0)
652  regions2[0].push_back(
653  TPoint3D(
654  face->points3D_x[cont], face->points3D_y[cont],
655  face->points3D_z[cont]));
656  else if (row == 0 && col == 1)
657  regions2[1].push_back(
658  TPoint3D(
659  face->points3D_x[cont], face->points3D_y[cont],
660  face->points3D_z[cont]));
661  else if (row == 0 && col == 2)
662  regions2[2].push_back(
663  TPoint3D(
664  face->points3D_x[cont], face->points3D_y[cont],
665  face->points3D_z[cont]));
666  else if (row == 1 && col == 0)
667  regions2[3].push_back(
668  TPoint3D(
669  face->points3D_x[cont], face->points3D_y[cont],
670  face->points3D_z[cont]));
671  else if (row == 1 && col == 1)
672  regions2[4].push_back(
673  TPoint3D(
674  face->points3D_x[cont], face->points3D_y[cont],
675  face->points3D_z[cont]));
676  else if (row == 1 && col == 2)
677  regions2[5].push_back(
678  TPoint3D(
679  face->points3D_x[cont], face->points3D_y[cont],
680  face->points3D_z[cont]));
681  else if (row == 2 && col == 0)
682  regions2[6].push_back(
683  TPoint3D(
684  face->points3D_x[cont], face->points3D_y[cont],
685  face->points3D_z[cont]));
686  else if (row == 2 && col == 1)
687  regions2[7].push_back(
688  TPoint3D(
689  face->points3D_x[cont], face->points3D_y[cont],
690  face->points3D_z[cont]));
691  else
692  regions2[8].push_back(
693  TPoint3D(
694  face->points3D_x[cont], face->points3D_y[cont],
695  face->points3D_z[cont]));
696  }
697  }
698  }
699 
700  //
701  // 5. To calculate medians or means of each subregion
702  //
703 
704  vector<double> oldPointsX1;
705 
706  size_t middle1 = 0;
707  size_t middle2 = 0;
708 
709  if (regions2[0].size() > 0)
710  {
711  for (size_t i = 0; i < regions2[0].size(); i++)
712  oldPointsX1.push_back(regions2[0][i].x);
713 
714  middle1 = floor((double)oldPointsX1.size() / 2);
715  nth_element(
716  oldPointsX1.begin(), oldPointsX1.begin() + middle1,
717  oldPointsX1.end()); // Obtain center element
718  }
719 
720  vector<double> oldPointsX2;
721 
722  if (regions2[2].size() > 0)
723  {
724  for (size_t i = 0; i < regions2[2].size(); i++)
725  oldPointsX2.push_back(regions2[2][i].x);
726 
727  middle2 = floor((double)oldPointsX2.size() / 2);
728  nth_element(
729  oldPointsX2.begin(), oldPointsX2.begin() + middle2,
730  oldPointsX2.end()); // Obtain center element
731  }
732 
733  for (size_t i = 0; i < 3; i++)
734  for (size_t j = 0; j < 3; j++)
735  if (!numPoints[i][j])
736  meanPos[i][j] = TPoint3D(0, 0, 0);
737  else
738  meanPos[i][j] = meanPos[i][j] / numPoints[i][j];
739 
740  if (regions2[0].size() > 0) meanPos[0][0].x = oldPointsX1.at(middle1);
741 
742  if (regions2[2].size() > 0) meanPos[0][2].x = oldPointsX2.at(middle2);
743 
744  //
745  // 6. To check subregions constrains
746  //
747  vector<double> dist(5);
748  size_t res = checkRelativePosition(
749  meanPos[1][0], meanPos[1][2], meanPos[1][1], dist[0]);
751  meanPos[2][0], meanPos[2][2], meanPos[2][1], dist[1]);
753  meanPos[0][0], meanPos[0][2], meanPos[0][1], dist[2]);
755  meanPos[0][0], meanPos[2][2], meanPos[1][1], dist[3]);
757  meanPos[2][0], meanPos[0][2], meanPos[1][1], dist[4]);
758 
759  ofstream f;
760  f.open("dist.txt", ofstream::app);
761  f << sum(dist) << endl;
762  f.close();
763 
764  bool real = false;
765  if (!res)
766  real = true;
767  else if ((res = 1) && (sum(dist) > 0.04))
768  real = true;
769 
770  f.open("tam.txt", ofstream::app);
771  f << meanPos[0][1].distanceTo(meanPos[2][1]) << endl;
772  f.close();
773 
774  // experimental_viewRegions( regions2, meanPos );
775 
776  // cout << endl << meanPos[0][0] << "\t" << meanPos[0][1] << "\t" <<
777  // meanPos[0][2];
778  // cout << endl << meanPos[1][0] << "\t" << meanPos[1][1] << "\t" <<
779  // meanPos[1][2];
780  // cout << endl << meanPos[2][0] << "\t" << meanPos[2][1] << "\t" <<
781  // meanPos[2][2] << endl;
782 
783  // To obtain experimental results
784  {
785  if (m_measure.takeTime) m_timeLog.leave("Check if face plane: regions");
786  }
787 
788  if (real)
789  return true; // Filter passed
790  else
791  {
792  // Uncomment if you want to known what regions was discarted by this
793  // filter
794  /*ofstream f;
795  f.open("deletedSTRUCTURES.txt", ofstream::app);
796  f << m_measure.faceNum << endl;
797  f.close();*/
798 
799  return false; // Filter not passed
800  }
801 
802  MRPT_END
803 }
804 
805 //------------------------------------------------------------------------
806 // checkRelativePosition
807 //------------------------------------------------------------------------
808 
810  const TPoint3D& p1, const TPoint3D& p2, const TPoint3D& p, double& dist)
811 {
812  double x1 = -p1.y;
813  double y1 = p1.x;
814 
815  double x2 = -p2.y;
816  double y2 = p2.x;
817 
818  double x = -p.y;
819  double y = p.x;
820 
821  double yIdeal = y1 + (((x - x1) * (y2 - y1)) / (x2 - x1));
822 
823  //////////////////////////////////
824 
825  /*double xaux = x2;
826  double yaux = y1;
827 
828  cout << "Grados= " << RAD2DEG(acos(
829  (xaux-x1)/(sqrt(pow(x1-x2,2)+pow(y1-y2,2))) )) << endl;*/
830 
831  ///////////////////////////////////////
832 
833  dist = yIdeal - y;
834 
835  if (y < yIdeal)
836  return 0;
837  else
838  return 1;
839 }
840 
842 {
843  obj->thread_checkIfDiagonalSurface();
844 }
845 
847 {
848  for (;;)
849  {
850  m_enter_checkIfDiagonalSurface.get_future().wait();
851 
852  if (m_end_threads) break;
853 
854  // Perform filter
857 
858  m_leave_checkIfDiagonalSurface.set_value();
859  }
860 }
861 
862 //------------------------------------------------------------------------
863 // checkIfDiagonalSurface
864 //------------------------------------------------------------------------
865 
867 {
868  MRPT_START
869 
870  // To obtain experimental results
871  {
873  m_timeLog.enter("Check if face plane: diagonal distances");
874 
876  m_timeLog.enter("Check if face plane: size-distance relation");
877  }
878 
879  const unsigned int faceWidth = face->intensityImage.getWidth();
880  const unsigned int faceHeight = face->intensityImage.getHeight();
881 
882  // const float max_desv = 0.2;
883 
884  unsigned int x1 = ceil(faceWidth * 0.25);
885  unsigned int x2 = floor(faceWidth * 0.75);
886  unsigned int y1 = ceil(faceHeight * 0.15);
887  unsigned int y2 = floor(faceHeight * 0.85);
888 
889  vector<TPoint3D> points;
890  unsigned int cont = (y1 == 0 ? 0 : faceHeight * (y1 - 1));
891  CMatrixBool valids;
892 
893  valids.setSize(faceHeight, faceWidth);
894 
895  int total = 0;
896  double sumDepth = 0;
897 
898  for (unsigned int i = y1; i <= y2; i++)
899  {
900  cont += x1;
901 
902  for (unsigned int j = x1; j <= x2; j++, cont++)
903  {
904  if (*(face->confidenceImage.get_unsafe(j, i, 0)) >
906  {
907  sumDepth += face->points3D_x[cont];
908  total++;
909  points.push_back(
910  TPoint3D(
911  face->points3D_x[cont], face->points3D_y[cont],
912  face->points3D_z[cont]));
913  }
914  }
915  cont += faceWidth - x2 - 1;
916  }
917 
918  double meanDepth = sumDepth / total;
919 
920  /*if ( m_measure.faceNum == 434 )
921  experimental_viewFacePointsScanned( *face );*/
922 
923  // experimental_viewFacePointsScanned( points );
924 
925  bool res = true;
926 
928  {
929  double maxFaceDistance = 0.5 + 1000 / (pow(faceWidth, 1.9));
930 
931  // To obtain experimental results
932  {
933  if (m_measure.takeTime)
934  m_timeLog.leave("Check if face plane: size-distance relation");
935 
937  m_timeLog.leave("Check if face plane: diagonal distances");
938  }
939 
940  /*if ( maxFaceDistance > meanDepth )
941  return true;
942 
943  if ( !m_options.useDiagonalDistanceFilter )
944  return false;*/
945 
946  if (maxFaceDistance < meanDepth)
947  {
948  // Uncomment if you want to analyze the regions discarted by this
949  // filter
950  /*ofstream f;
951  f.open("deletedSIZEDISTANCE.txt", ofstream::app);
952  f << m_measure.faceNum << endl;
953  f.close();*/
954 
955  // if ( !m_options.useDiagonalDistanceFilter )
956  return false;
957  // else
958  // res = false;
959  }
960 
961  if (!m_options.useDiagonalDistanceFilter) return true;
962  }
963 
964  ofstream f;
965  /*f.open("relaciones1.txt", ofstream::app);
966  f << faceWidth << endl;
967  f.close();*/
968 
969  f.open("relaciones2.txt", ofstream::app);
970  f << meanDepth << endl;
971  f.close();
972 
973  // cout << m_measure.faceNum ;
974 
975  // experimental_viewFacePointsScanned( points );
976 
977  points.clear();
978 
979  cont = (y1 == 1 ? 0 : faceHeight * (y1 - 1));
980 
981  for (unsigned int i = y1; i <= y2; i++)
982  {
983  cont += x1;
984 
985  for (unsigned int j = x1; j <= x2; j++, cont++)
986  {
987  if ((*(face->confidenceImage.get_unsafe(j, i, 0)) >
989  //&& ( face->points3D_x[cont] > meanDepth - max_desv )
990  //&& ( face->points3D_x[cont] < meanDepth + max_desv ) )
991  {
992  valids.set_unsafe(i, j, true);
993  points.push_back(
994  TPoint3D(
995  face->points3D_x[cont], face->points3D_y[cont],
996  face->points3D_z[cont]));
997  }
998  else
999  valids.set_unsafe(i, j, false);
1000  }
1001  cont += faceWidth - x2 - 1;
1002  }
1003 
1004  /*if ( m_measure.faceNum > 838 )
1005  experimental_viewFacePointsScanned( points );*/
1006 
1007  // if ( ( m_measure.faceNum == 225 ) || ( m_measure.faceNum == 226 ) )
1008  // experimental_viewFacePointsScanned( points );
1009 
1010  double sumDistances = 0;
1011  double distance;
1012  int offsetIndex;
1013 
1014  cont = 0;
1015 
1016  for (unsigned int i = y1; i <= y2; i++)
1017  {
1018  cont += x1;
1019 
1020  for (unsigned int j = x1; j <= x2; j++, cont++)
1021  {
1022  if (valids.get_unsafe(i, j))
1023  {
1024  // experimental_calcDiagDist( face, i, j, faceWidth, faceHeight,
1025  // valids, distance );
1026 
1027  distance = 0;
1028  if ((i + 1 <= y2) && (j + 1 <= x2))
1029  {
1030  if (valids.get_unsafe(i + 1, j + 1))
1031  {
1032  TPoint3D p1(
1033  face->points3D_x[cont], face->points3D_y[cont],
1034  face->points3D_z[cont]);
1035  offsetIndex = cont + faceWidth + 1;
1036  distance = p1.distanceTo(
1037  TPoint3D(
1038  face->points3D_x[offsetIndex],
1039  face->points3D_y[offsetIndex],
1040  face->points3D_z[offsetIndex]));
1041  }
1042  else
1043  {
1044  bool validOffset = true;
1045  int offset = 2;
1046 
1047  while (validOffset)
1048  {
1049  if ((i + offset <= y2) && (j + offset <= x2))
1050  {
1051  if (valids.get_unsafe(i + offset, j + offset))
1052  {
1053  TPoint3D p1(
1054  face->points3D_x[cont],
1055  face->points3D_y[cont],
1056  face->points3D_z[cont]);
1057  offsetIndex = cont + faceWidth + offset;
1058  distance = p1.distanceTo(
1059  TPoint3D(
1060  face->points3D_x[offsetIndex],
1061  face->points3D_y[offsetIndex],
1062  face->points3D_z[offsetIndex]));
1063  break;
1064  }
1065  offset++;
1066  }
1067  else
1068  validOffset = false;
1069  }
1070  }
1071  }
1072 
1073  sumDistances += distance;
1074  }
1075  }
1076  cont += faceWidth - x2 - 1;
1077  }
1078 
1079  // For experimental results
1080  {
1081  if (m_measure.takeMeasures)
1082  m_measure.sumDistances.push_back(sumDistances);
1083 
1084  ofstream f;
1085  f.open("distances.txt", ofstream::app);
1086  // f << m_measure.faceNum << " " << sumDistances << endl;
1087  f << sumDistances << endl;
1088  f.close();
1089 
1090  f.open("distances2.txt", ofstream::app);
1091  f << m_measure.faceNum << " " << sumDistances << endl;
1092  f.close();
1093  }
1094 
1095  // double yMax = 3 + 3.8 / ( pow( meanDepth, 2 ) );
1096  // double yMax = 3 + 7 /( pow( meanDepth, 2) ) ;
1097  double yMax = 3 + 6 / (pow(meanDepth, 2));
1098  double yMin = 1 + 3.8 / (pow(meanDepth + 1.2, 2));
1099 
1100  // To obtain experimental results
1101  {
1102  if (m_measure.takeTime)
1103  m_timeLog.leave("Check if face plane: diagonal distances");
1104  }
1105 
1106  if (((sumDistances <= yMax) && (sumDistances >= yMin)) && (res))
1107  {
1108  /* Uncomment if you want to analyze the real size of each studied region
1109  / *ofstream f;
1110  f.open("sizes.txt", ofstream::app);
1111  double h = meanDepth/cos(DEG2RAD(faceHeight*0.2361111111111111));
1112  double realHigh = sin(DEG2RAD(faceHeight*0.2361111111111111))*h;
1113  f << realHigh << endl;
1114  f.close();*/
1115 
1116  return true;
1117  }
1118 
1119  // Uncomment if you want to analyze regions discarted by this filter
1120  /*if (( sumDistances > yMax ) || ( sumDistances < yMin ))
1121  {
1122  ofstream f;
1123  f.open("deletedDIAGONAL.txt", ofstream::app);
1124  f << m_measure.faceNum << endl;
1125  f.close();
1126  }*/
1127 
1128  return false;
1129 
1130  MRPT_END
1131 }
1132 
1133 //------------------------------------------------------------------------
1134 // checkIfDiagonalSurface2
1135 //------------------------------------------------------------------------
1136 
1138 {
1139  MRPT_START
1140 
1141  // To obtain experimental results
1142  {
1144  m_timeLog.enter("Check if face plane: diagonal distances");
1145 
1147  m_timeLog.enter("Check if face plane: size-distance relation");
1148  }
1149 
1150  const unsigned int faceWidth = face->intensityImage.getWidth();
1151  const unsigned int faceHeight = face->intensityImage.getHeight();
1152 
1153  CMatrixTemplate<bool> region; // To save the segmented region
1154  experimental_segmentFace(*face, region);
1155 
1156  size_t cont = 0;
1157  size_t total = 0;
1158  float sumDepth = 0;
1159 
1160  vector<TPoint3D> points;
1161 
1162  for (unsigned int row = 0; row < faceHeight; row++)
1163  {
1164  for (unsigned int col = 0; col < faceWidth; col++, cont++)
1165  {
1166  if ((region.get_unsafe(row, col)) &&
1167  (*(face->confidenceImage.get_unsafe(col, row, 0)) >
1169  {
1170  sumDepth += face->points3D_x[cont];
1171  total++;
1172  points.push_back(
1173  TPoint3D(
1174  face->points3D_x[cont], face->points3D_y[cont],
1175  face->points3D_z[cont]));
1176  }
1177  }
1178  }
1179 
1180  double meanDepth = sumDepth / total;
1181 
1182  bool res = true;
1183 
1185  {
1186  double maxFaceDistance = 0.5 + 1000 / (pow(faceWidth, 1.9));
1187 
1188  // To obtain experimental results
1189  {
1190  if (m_measure.takeTime)
1191  m_timeLog.leave("Check if face plane: size-distance relation");
1192 
1194  m_timeLog.leave("Check if face plane: diagonal distances");
1195  }
1196 
1197  /*if ( maxFaceDistance > meanDepth )
1198  return true;
1199 
1200  if ( !m_options.useDiagonalDistanceFilter )
1201  return false;*/
1202 
1203  if (maxFaceDistance < meanDepth)
1204  {
1205  // Uncomment if you want to analyze the regions discarted by this
1206  // filter
1207  /*ofstream f;
1208  f.open("deletedSIZEDISTANCE.txt", ofstream::app);
1209  f << m_measure.faceNum << endl;
1210  f.close();*/
1211 
1212  // if ( !m_options.useDiagonalDistanceFilter )
1213  return false;
1214  // else
1215  // res = false;
1216  }
1217 
1218  if (!m_options.useDiagonalDistanceFilter) return true;
1219  }
1220 
1221  ofstream f;
1222  /*f.open("relaciones1.txt", ofstream::app);
1223  f << faceWidth << endl;
1224  f.close();*/
1225 
1226  f.open("relaciones2.txt", ofstream::app);
1227  f << meanDepth << endl;
1228  f.close();
1229 
1230  // cout << m_measure.faceNum ;
1231 
1232  // experimental_viewFacePointsScanned( points );
1233 
1234  points.clear();
1235 
1236  /*if ( m_measure.faceNum > 838 )
1237  experimental_viewFacePointsScanned( points );*/
1238 
1239  // if ( ( m_measure.faceNum == 225 ) || ( m_measure.faceNum == 226 ) )
1240  // experimental_viewFacePointsScanned( points );
1241 
1242  double sumDistances = 0;
1243  double distance;
1244  size_t offsetIndex = 0;
1245 
1246  cont = 0;
1247 
1248  for (unsigned int i = 0; i < faceHeight; i++)
1249  {
1250  for (unsigned int j = 0; j < faceWidth; j++, cont++)
1251  {
1252  if (region.get_unsafe(i, j))
1253  {
1254  distance = 0;
1255  if ((i + 1 < faceHeight) && (j + 1 < faceWidth))
1256  {
1257  if (region.get_unsafe(i + 1, j + 1))
1258  {
1259  TPoint3D p1(
1260  face->points3D_x[cont], face->points3D_y[cont],
1261  face->points3D_z[cont]);
1262  offsetIndex = cont + faceWidth + 1;
1263  distance = p1.distanceTo(
1264  TPoint3D(
1265  face->points3D_x[offsetIndex],
1266  face->points3D_y[offsetIndex],
1267  face->points3D_z[offsetIndex]));
1268  }
1269  else
1270  {
1271  bool validOffset = true;
1272  int offset = 2;
1273 
1274  while (validOffset)
1275  {
1276  if ((i + offset < faceHeight) &&
1277  (j + offset < faceWidth))
1278  {
1279  if (region.get_unsafe(i + offset, j + offset))
1280  {
1281  TPoint3D p1(
1282  face->points3D_x[cont],
1283  face->points3D_y[cont],
1284  face->points3D_z[cont]);
1285  offsetIndex = cont + faceWidth + offset;
1286  distance = p1.distanceTo(
1287  TPoint3D(
1288  face->points3D_x[offsetIndex],
1289  face->points3D_y[offsetIndex],
1290  face->points3D_z[offsetIndex]));
1291  break;
1292  }
1293  offset++;
1294  }
1295  else
1296  validOffset = false;
1297  }
1298  }
1299  }
1300 
1301  sumDistances += distance;
1302  }
1303  }
1304  }
1305 
1306  // For experimental results
1307  {
1308  if (m_measure.takeMeasures)
1309  m_measure.sumDistances.push_back(sumDistances);
1310 
1311  ofstream f;
1312  f.open("distances.txt", ofstream::app);
1313  // f << m_measure.faceNum << " " << sumDistances << endl;
1314  f << sumDistances << endl;
1315  f.close();
1316 
1317  /*f.open("distances2.txt", ofstream::app);
1318  f << m_measure.faceNum << " " << sumDistances << endl;
1319  f.close();*/
1320  }
1321 
1322  // double yMax = 3 + 3.8 / ( pow( meanDepth, 2 ) );
1323  // double yMax = 3 + 7 /( pow( meanDepth, 2) ) ;
1324  double yMax = 3 + 11.8 / (pow(meanDepth, 0.9));
1325  double yMin = 1 + 3.8 / (pow(meanDepth + 7, 6));
1326 
1327  // To obtain experimental results
1328  {
1329  if (m_measure.takeTime)
1330  m_timeLog.leave("Check if face plane: diagonal distances");
1331  }
1332 
1333  if (((sumDistances <= yMax) && (sumDistances >= yMin)) && (res))
1334  {
1335  /* Uncomment if you want to analyze the real size of each studied region
1336  / *ofstream f;
1337  f.open("sizes.txt", ofstream::app);
1338  double h = meanDepth/cos(DEG2RAD(faceHeight*0.2361111111111111));
1339  double realHigh = sin(DEG2RAD(faceHeight*0.2361111111111111))*h;
1340  f << realHigh << endl;
1341  f.close();*/
1342 
1343  return true;
1344  }
1345 
1346  // Uncomment if you want to analyze regions discarted by this filter
1347  /*if (( sumDistances > yMax ) || ( sumDistances < yMin ))
1348  {
1349  ofstream f;
1350  f.open("deletedDIAGONAL.txt", ofstream::app);
1351  f << m_measure.faceNum << endl;
1352  f.close();
1353  }*/
1354 
1355  return false;
1356 
1357  MRPT_END
1358 }
1359 
1360 //------------------------------------------------------------------------
1361 // experimental_viewFacePointsScanned
1362 //------------------------------------------------------------------------
1363 
1366 {
1367  vector<float> xs, ys, zs;
1368 
1369  unsigned int N = face.points3D_x.size();
1370 
1371  xs.resize(N);
1372  ys.resize(N);
1373  zs.resize(N);
1374 
1375  for (unsigned int i = 0; i < N; i++)
1376  {
1377  xs[i] = face.points3D_x[i];
1378  ys[i] = face.points3D_y[i];
1379  zs[i] = face.points3D_z[i];
1380  }
1381 
1383 }
1384 
1385 //------------------------------------------------------------------------
1386 // experimental_ViewFacePointsScanned
1387 //------------------------------------------------------------------------
1388 
1390  const vector<TPoint3D>& points)
1391 {
1392  vector<float> xs, ys, zs;
1393 
1394  unsigned int N = points.size();
1395 
1396  xs.resize(N);
1397  ys.resize(N);
1398  zs.resize(N);
1399 
1400  for (unsigned int i = 0; i < N; i++)
1401  {
1402  xs[i] = points[i].x;
1403  ys[i] = points[i].y;
1404  zs[i] = points[i].z;
1405  }
1406 
1408 }
1409 
1410 //------------------------------------------------------------------------
1411 // experimental_viewFacePointsScanned
1412 //------------------------------------------------------------------------
1413 
1415  const vector<float>& xs, const vector<float>& ys, const vector<float>& zs)
1416 {
1418 
1419  win3D.setWindowTitle("3D Face detected (Scanned points)");
1420 
1421  win3D.resize(400, 300);
1422 
1423  win3D.setCameraAzimuthDeg(140);
1424  win3D.setCameraElevationDeg(20);
1425  win3D.setCameraZoom(6.0);
1426  win3D.setCameraPointingToPoint(2.5, 0, 0);
1427 
1429  mrpt::make_aligned_shared<mrpt::opengl::CPointCloudColoured>();
1430  gl_points->setPointSize(4.5);
1431 
1433 
1434  scene->insert(gl_points);
1435  scene->insert(mrpt::make_aligned_shared<mrpt::opengl::CGridPlaneXY>());
1436 
1437  CColouredPointsMap pntsMap;
1438 
1439  pntsMap.setAllPoints(xs, ys, zs);
1440 
1441  gl_points->loadFromPointsMap(&pntsMap);
1442 
1443  // gl_points->setColor(0,0.7,0.7,1);
1444 
1445  /*static int i = 0;
1446 
1447  if ( i == 2 )
1448  {
1449  mapa.setAllPoints( xs, ys, zs );
1450  i++;
1451  }
1452  else if ( i > 2 )
1453  {
1454  float run_time;
1455  CICP icp;
1456  CICP::TReturnInfo icp_info;
1457 
1458  icp.options.thresholdDist = 0.40;
1459  icp.options.thresholdAng = 0.40;
1460 
1461  CPose3DPDF::Ptr pdf= icp.Align3D(
1462  &mapa, // Map to align
1463  &pntsMap, // Reference map
1464  CPose3D(), // Initial gross estimate
1465  &run_time,
1466  &icp_info);
1467 
1468  cout << "ICP run took " << run_time << " secs." << endl;
1469  cout << "Goodness: " << 100*icp_info.goodness << "%" << endl;
1470  }
1471 
1472  i++;*/
1473 
1474  win3D.unlockAccess3DScene();
1475  win3D.repaint();
1476 
1477  system::pause();
1478 }
1479 
1480 //------------------------------------------------------------------------
1481 // experimental_viewFacePointsAndEigenVects
1482 //------------------------------------------------------------------------
1483 
1485  const vector<CArrayDouble<3>>& pointsVector, const CMatrixDouble& eigenVect,
1486  const CVectorDouble& eigenVal)
1487 {
1488  vector<float> xs, ys, zs;
1489 
1490  const size_t size = pointsVector.size();
1491 
1492  xs.resize(size);
1493  ys.resize(size);
1494  zs.resize(size);
1495 
1496  for (size_t i = 0; i < size; i++)
1497  {
1498  xs[i] = pointsVector[i][0];
1499  ys[i] = pointsVector[i][1];
1500  zs[i] = pointsVector[i][2];
1501  }
1502 
1503  TPoint3D center(sum(xs) / size, sum(ys) / size, sum(zs) / size);
1504 
1506 
1507  win3D.setWindowTitle("3D Face detected (Scanned points)");
1508 
1509  win3D.resize(400, 300);
1510 
1511  win3D.setCameraAzimuthDeg(140);
1512  win3D.setCameraElevationDeg(20);
1513  win3D.setCameraZoom(6.0);
1514  win3D.setCameraPointingToPoint(2.5, 0, 0);
1515 
1517  mrpt::make_aligned_shared<mrpt::opengl::CPointCloudColoured>();
1518  gl_points->setPointSize(4.5);
1519 
1521 
1522  CSphere::Ptr sphere = mrpt::make_aligned_shared<CSphere>(0.005f);
1523  sphere->setLocation(center);
1524  sphere->setColor(TColorf(0, 1, 0));
1525  scene->insert(sphere);
1526 
1527  // TPoint3D E1( eigenVect.get_unsafe(0,0), eigenVect.get_unsafe(1,0),
1528  // eigenVect.get_unsafe(2,0) );
1529  // TPoint3D E2( eigenVect.get_unsafe(0,1), eigenVect.get_unsafe(1,1),
1530  // eigenVect.get_unsafe(2,1) );
1531  // TPoint3D E3( eigenVect.get_unsafe(0,2), eigenVect.get_unsafe(1,2),
1532  // eigenVect.get_unsafe(2,2) );
1533 
1534  TPoint3D E1(
1535  eigenVect.get_unsafe(0, 0), eigenVect.get_unsafe(0, 1),
1536  eigenVect.get_unsafe(0, 2));
1537  TPoint3D E2(
1538  eigenVect.get_unsafe(1, 0), eigenVect.get_unsafe(1, 1),
1539  eigenVect.get_unsafe(1, 2));
1540  TPoint3D E3(
1541  eigenVect.get_unsafe(2, 0), eigenVect.get_unsafe(2, 1),
1542  eigenVect.get_unsafe(2, 2));
1543 
1544  // vector<TSegment3D> sgms;
1545 
1546  TPoint3D p1(center + E1 * eigenVal[0] * 100);
1547  TPoint3D p2(center + E2 * eigenVal[1] * 100);
1548  TPoint3D p3(center + E3 * eigenVal[2] * 100);
1549 
1550  CArrow::Ptr arrow1 = mrpt::make_aligned_shared<CArrow>(
1551  center.x, center.y, center.z, p1.x, p1.y, p1.z);
1552  CArrow::Ptr arrow2 = mrpt::make_aligned_shared<CArrow>(
1553  center.x, center.y, center.z, p2.x, p2.y, p2.z);
1554  CArrow::Ptr arrow3 = mrpt::make_aligned_shared<CArrow>(
1555  center.x, center.y, center.z, p3.x, p3.y, p3.z);
1556 
1557  arrow1->setColor(TColorf(0, 1, 0));
1558  arrow2->setColor(TColorf(1, 0, 0));
1559  arrow3->setColor(TColorf(0, 0, 1));
1560 
1561  scene->insert(arrow1);
1562  scene->insert(arrow2);
1563  scene->insert(arrow3);
1564 
1565  // sgms.push_back( TSegment3D(center,center + E1*eigenVal[0]*100) );
1566  // sgms.push_back( TSegment3D(center,center + E2*eigenVal[1]*100) );
1567  // sgms.push_back( TSegment3D(center,center + E3*eigenVal[2]*100) );
1568  // mrpt::opengl::CSetOfLines::Ptr lines =
1569  // mrpt::make_aligned_shared<mrpt::opengl::CSetOfLines>( sgms );
1570  // lines->setColor(0,0,1,1);
1571  // lines->setLineWidth( 10 );
1572 
1573  // scene->insert( lines );
1574 
1575  scene->insert(gl_points);
1576  scene->insert(mrpt::make_aligned_shared<mrpt::opengl::CGridPlaneXY>());
1577 
1578  CColouredPointsMap pntsMap;
1579 
1580  pntsMap.setAllPoints(xs, ys, zs);
1581 
1582  gl_points->loadFromPointsMap(&pntsMap);
1583 
1584  win3D.unlockAccess3DScene();
1585  win3D.repaint();
1586 
1587  system::pause();
1588 }
1589 
1590 //------------------------------------------------------------------------
1591 // experimental_viewRegions
1592 //------------------------------------------------------------------------
1593 
1595  const vector<TPoint3D> regions[9], const TPoint3D meanPos[3][3])
1596 {
1598 
1599  win3D.setWindowTitle("3D Face detected (Scanned points)");
1600 
1601  win3D.resize(400, 300);
1602 
1603  win3D.setCameraAzimuthDeg(140);
1604  win3D.setCameraElevationDeg(20);
1605  win3D.setCameraZoom(6.0);
1606  win3D.setCameraPointingToPoint(2.5, 0, 0);
1607 
1609  mrpt::make_aligned_shared<mrpt::opengl::CPointCloudColoured>();
1610  gl_points->setPointSize(6);
1611 
1613 
1614  if (meanPos != nullptr)
1615  {
1616  for (size_t i = 0; i < 3; i++)
1617  for (size_t j = 0; j < 3; j++)
1618  {
1619  CSphere::Ptr sphere =
1620  mrpt::make_aligned_shared<CSphere>(0.005f);
1621  sphere->setLocation(meanPos[i][j]);
1622  sphere->setColor(TColorf(0, 1, 0));
1623  scene->insert(sphere);
1624  }
1625  }
1626 
1627  vector<TSegment3D> sgms;
1628  sgms.push_back(TSegment3D(meanPos[0][0], meanPos[0][1]));
1629  sgms.push_back(TSegment3D(meanPos[0][1], meanPos[0][2]));
1630  sgms.push_back(TSegment3D(meanPos[1][0], meanPos[1][1]));
1631  sgms.push_back(TSegment3D(meanPos[1][1], meanPos[1][2]));
1632  sgms.push_back(TSegment3D(meanPos[2][0], meanPos[2][1]));
1633  sgms.push_back(TSegment3D(meanPos[2][1], meanPos[2][2]));
1634  sgms.push_back(TSegment3D(meanPos[0][0], meanPos[1][1]));
1635  sgms.push_back(TSegment3D(meanPos[1][1], meanPos[2][2]));
1636  sgms.push_back(TSegment3D(meanPos[2][0], meanPos[1][1]));
1637  sgms.push_back(TSegment3D(meanPos[1][1], meanPos[0][2]));
1639  mrpt::make_aligned_shared<mrpt::opengl::CSetOfLines>(sgms);
1640  lines->setColor(0, 0, 1, 1);
1641  lines->setLineWidth(10);
1642 
1643  scene->insert(lines);
1644 
1645  scene->insert(gl_points);
1646  scene->insert(mrpt::make_aligned_shared<mrpt::opengl::CGridPlaneXY>());
1647  scene->insert(
1648  mrpt::make_aligned_shared<mrpt::opengl::CAxis>(
1649  -5, -5, -5, 5, 5, 5, 2.5, 3, true));
1650 
1651  CColouredPointsMap pntsMap;
1652 
1653  vector<float> xs, ys, zs;
1654 
1655  for (size_t i = 0; i < 9; i++)
1656  for (unsigned int j = 0; j < regions[i].size(); j++)
1657  {
1658  xs.push_back(regions[i][j].x);
1659  ys.push_back(regions[i][j].y);
1660  zs.push_back(regions[i][j].z);
1661  }
1662 
1663  pntsMap.setAllPoints(xs, ys, zs);
1664 
1665  int cont = 0;
1666  float colors[9][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1},
1667  {1, 1, 0}, {1, 0, 1}, {0, 1, 1},
1668  {0.5f, 0.25f, 0}, {0.5f, 0, 0.25f}, {0, 0.35f, 0.5f}};
1669  for (size_t i = 0; i < 9; i++)
1670  {
1671  float R = colors[i][0];
1672  float G = colors[i][1];
1673  float B = colors[i][2];
1674 
1675  for (unsigned int j = 0; j < regions[i].size(); j++, cont++)
1676  pntsMap.setPointColor(cont, R, G, B);
1677  }
1678 
1679  gl_points->loadFromPointsMap(&pntsMap);
1680  // gl_points->setColorA(0.5);
1681 
1682  win3D.unlockAccess3DScene();
1683  win3D.repaint();
1684 
1685  system::pause();
1686 }
1687 
1688 //------------------------------------------------------------------------
1689 // experimental_segmentFace
1690 //------------------------------------------------------------------------
1691 
1694 {
1695  const unsigned int faceWidth = face.intensityImage.getWidth();
1696  const unsigned int faceHeight = face.intensityImage.getHeight();
1697 
1698  region.setSize(faceWidth, faceHeight, true);
1699 
1700  unsigned int x1 = ceil(faceWidth * 0.4);
1701  unsigned int x2 = floor(faceWidth * 0.6);
1702  unsigned int y1 = ceil(faceHeight * 0.4);
1703  unsigned int y2 = floor(faceHeight * 0.6);
1704 
1705  region.setSize(faceHeight, faceWidth);
1706  CMatrixTemplate<size_t> toExpand;
1707  toExpand.setSize(faceHeight, faceWidth, true);
1708 
1709  unsigned int cont = (y1 <= 1 ? 0 : faceHeight * (y1 - 1));
1710 
1711  // int total = 0; // JL: Unused var
1712  // int numPoints = 0; // JL: Unused var
1713 
1715  // Normalize the image
1717  range2D *= 1.0f / 5;
1718  img.setFromMatrix(range2D);
1719 
1720  // INITIALIZATION
1721  for (unsigned int i = y1; i <= y2; i++)
1722  {
1723  cont += x1;
1724 
1725  for (unsigned int j = x1; j <= x2; j++, cont++)
1726  {
1727  if (*(face.confidenceImage.get_unsafe(j, i, 0)) >
1729  {
1730  // unsigned char *c = img.get_unsafe(i,j);
1731  // size_t value = (size_t)*c;
1732  // total += value;
1733  //++numPoints;
1734  toExpand.set_unsafe(i, j, 1);
1735  }
1736  }
1737  cont += faceWidth - x2;
1738  }
1739 
1740  // int mean = total / numPoints;
1741 
1742  // cout << "Mean: " << mean << endl;
1743  // system::pause();
1744 
1745  // UMBRALIZATION
1746  /*
1747  for ( unsigned int row = 0; row < faceWidth; row++ )
1748  {
1749  for ( unsigned int col = 0; col < faceHeight; col++ )
1750  {
1751  unsigned char *c = img.get_unsafe(row,col);
1752  size_t value = (size_t)*c;
1753 
1754  if ( ( value < mean+7 ) && ( value > mean-7 ) )
1755  {
1756  region.set_unsafe( row, col, true );
1757  }else{
1758  img.setPixel( row, col, 0 );
1759  }
1760  }
1761  }
1762  */
1763 
1764  // REGIONS GROWING
1765 
1766  bool newExpanded = true;
1767 
1768  while (newExpanded)
1769  {
1770  newExpanded = false;
1771 
1772  for (size_t row = 0; row < faceHeight; row++)
1773  {
1774  for (size_t col = 0; col < faceWidth; col++)
1775  {
1776  // cout << toExpand.get_unsafe( row, col ) << "" ;
1777 
1778  if (toExpand.get_unsafe(row, col) == 1)
1779  {
1780  region.set_unsafe(row, col, true);
1781 
1782  unsigned char* c = img.get_unsafe(col, row);
1783  int value = (int)*c;
1784 
1785  if ((row > 0) && (toExpand.get_unsafe(row - 1, col) != 2))
1786  {
1787  unsigned char* c = img.get_unsafe(col, row - 1);
1788  int value2 = (int)*c;
1789  if (abs(value - value2) < 2)
1790  {
1791  toExpand.set_unsafe(row - 1, col, 1);
1792  newExpanded = true;
1793  }
1794  }
1795 
1796  if ((row < faceWidth - 1) &&
1797  (toExpand.get_unsafe(row + 1, col) != 2))
1798  {
1799  unsigned char* c = img.get_unsafe(col, row + 1);
1800  int value2 = (int)*c;
1801  if (abs(value - value2) < 2)
1802  {
1803  toExpand.set_unsafe(row + 1, col, 1);
1804  newExpanded = true;
1805  }
1806  }
1807 
1808  if ((col > 0) && (toExpand.get_unsafe(row, col - 1) != 2))
1809  {
1810  unsigned char* c = img.get_unsafe(col - 1, row);
1811  int value2 = (int)*c;
1812  if (abs(value - value2) < 2)
1813  {
1814  toExpand.set_unsafe(row, col - 1, 1);
1815  newExpanded = true;
1816  }
1817  }
1818 
1819  if ((col < faceHeight - 1) &&
1820  (toExpand.get_unsafe(row, col + 1) != 2))
1821  {
1822  unsigned char* c = img.get_unsafe(col + 1, row);
1823  int value2 = (int)*c;
1824  if (abs(value - value2) < 2)
1825  {
1826  toExpand.set_unsafe(row, col + 1, 1);
1827  newExpanded = true;
1828  }
1829  }
1830 
1831  toExpand.set_unsafe(row, col, 2);
1832  }
1833  }
1834  }
1835  }
1836 
1837  for (unsigned int row = 0; row < faceHeight; row++)
1838  {
1839  for (unsigned int col = 0; col < faceWidth; col++)
1840  {
1841  if (!(region.get_unsafe(row, col)))
1842  {
1843  img.setPixel(col, row, 0);
1844  }
1845  }
1846  }
1847 
1848  // Uncomment if you want to see the resultant region segmented
1849  if (m_measure.faceNum >= 314)
1850  {
1851  CDisplayWindow win("Live video");
1852 
1853  win.showImage(img);
1854  system::pause();
1855  }
1856 }
1857 
1858 //------------------------------------------------------------------------
1859 // experimental_calcHist
1860 //------------------------------------------------------------------------
1861 
1863  const CImage& face, const size_t& c1, const size_t& r1, const size_t& c2,
1864  const size_t& r2, CMatrixTemplate<unsigned int>& hist)
1865 {
1866  TImageSize size;
1867  face.getSize(size);
1868  for (size_t row = r1; row <= r2; row++)
1869  for (size_t col = c1; col <= c2; col++)
1870  {
1871  unsigned char* c = face.get_unsafe(col, row);
1872  size_t value = (size_t)*c;
1873  int count = hist.get_unsafe(0, value) + 1;
1874  hist.set_unsafe(0, value, count);
1875  }
1876 }
1877 
1878 //------------------------------------------------------------------------
1879 // experimental_showMeasurements
1880 //------------------------------------------------------------------------
1881 
1883 {
1884  // This method execution time is not critical because it's executed only at
1885  // the end
1886  // or a few times in user application
1887 
1888  ofstream f;
1889  f.open("statistics.txt", ofstream::app);
1890 
1891  if (m_measure.lessEigenVals.size() > 0)
1892  {
1893  double meanEigenVal, stdEigenVal;
1894  double minEigenVal = *min_element(
1896  double maxEigenVal = *max_element(
1898 
1899  meanAndStd(m_measure.lessEigenVals, meanEigenVal, stdEigenVal);
1900 
1901  cout << endl
1902  << "Statistical data about eigen values calculated of regions "
1903  "detected as faces"
1904  << endl;
1905  cout << "Min eigenVal: " << minEigenVal << endl;
1906  cout << "Max eigenVal: " << maxEigenVal << endl;
1907  cout << "Mean eigenVal: " << meanEigenVal << endl;
1908  cout << "Standard Desv: " << stdEigenVal << endl;
1909 
1911  {
1912  f << endl
1913  << "Statistical data about eigen values calculated of regions "
1914  "detected as faces"
1915  << endl;
1916  f << "Min eigenVal: " << minEigenVal << endl;
1917  f << "Max eigenVal: " << maxEigenVal << endl;
1918  f << "Mean eigenVal: " << meanEigenVal << endl;
1919  f << "Standard Desv: " << stdEigenVal << endl;
1920  }
1921  }
1922 
1923  if (m_measure.sumDistances.size() > 0)
1924  {
1925  double meanSumDist, stdSumDist;
1926  double minSumDist = *min_element(
1927  m_measure.sumDistances.begin(), m_measure.sumDistances.end());
1928  double maxSumDist = *max_element(
1929  m_measure.sumDistances.begin(), m_measure.sumDistances.end());
1930 
1931  meanAndStd(m_measure.sumDistances, meanSumDist, stdSumDist);
1932 
1933  cout << endl << "Statistical data about sum of distances" << endl;
1934  cout << "Min sumDistances: " << minSumDist << endl;
1935  cout << "Max sumDistances: " << maxSumDist << endl;
1936  cout << "Mean sumDistances: " << meanSumDist << endl;
1937  cout << "Standard Desv: " << stdSumDist << endl;
1938 
1940  {
1941  f << endl << "Statistical data about sum of distances" << endl;
1942  f << "Min sumDistances: " << minSumDist << endl;
1943  f << "Max sumDistances: " << maxSumDist << endl;
1944  f << "Mean sumDistances: " << meanSumDist << endl;
1945  f << "Standard Desv: " << stdSumDist << endl;
1946  }
1947  }
1948 
1949  if (m_measure.errorEstimations.size() > 0)
1950  {
1951  double meanEstimationErr, stdEstimationErr;
1952  double minEstimationErr = *min_element(
1953  m_measure.errorEstimations.begin(),
1954  m_measure.errorEstimations.end());
1955  double maxEstimationErr = *max_element(
1956  m_measure.errorEstimations.begin(),
1957  m_measure.errorEstimations.end());
1958 
1959  meanAndStd(
1960  m_measure.errorEstimations, meanEstimationErr, stdEstimationErr);
1961 
1962  cout << endl
1963  << "Statistical data about estimation error adjusting a plane of "
1964  "regions detected as faces"
1965  << endl;
1966  cout << "Min estimation: " << minEstimationErr << endl;
1967  cout << "Max estimation: " << maxEstimationErr << endl;
1968  cout << "Mean estimation: " << meanEstimationErr << endl;
1969  cout << "Standard Desv: " << stdEstimationErr << endl;
1970 
1972  {
1973  f << endl
1974  << "Statistical data about estimation error adjusting a plane of "
1975  "regions detected as faces"
1976  << endl;
1977  f << "Min estimation: " << minEstimationErr << endl;
1978  f << "Max estimation: " << maxEstimationErr << endl;
1979  f << "Mean estimation: " << meanEstimationErr << endl;
1980  f << "Standard Desv: " << stdEstimationErr << endl;
1981  }
1982  }
1983 
1984  cout << endl << "Data about number of faces" << endl;
1985  cout << "Possible faces detected: " << m_measure.numPossibleFacesDetected
1986  << endl;
1987  cout << "Real faces detected: " << m_measure.numRealFacesDetected << endl;
1988 
1989  if (m_meanHist.size() > 0)
1990  {
1991  double minHist = *min_element(m_meanHist.begin(), m_meanHist.end());
1992  double maxHist = *max_element(m_meanHist.begin(), m_meanHist.end());
1993  double meanHist;
1994  double stdHist;
1995  meanAndStd(m_meanHist, meanHist, stdHist);
1996 
1997  cout << endl << "Mean hist: " << meanHist << endl;
1998  cout << "Min hist: " << minHist << endl;
1999  cout << "Max hist: " << maxHist << endl;
2000  cout << "Stdv: " << stdHist << endl;
2001  }
2002 
2004  {
2005  f << endl << "Data about number of faces" << endl;
2006  f << "Possible faces detected: " << m_measure.numPossibleFacesDetected
2007  << endl;
2008  f << "Real faces detected: " << m_measure.numRealFacesDetected << endl;
2009  }
2010 
2012  f << endl << m_timeLog.getStatsAsText();
2013 
2014  f.close();
2015 
2017 }
2018 
2019 //------------------------------------------------------------------------
2020 // debug_returnResults
2021 //------------------------------------------------------------------------
2022 
2024  const vector_uint& falsePositives, const vector_uint& ignore,
2025  unsigned int& falsePositivesDeleted, unsigned int& realFacesDeleted)
2026 {
2027  const unsigned int numDeleted = m_measure.deletedRegions.size();
2028  const unsigned int numFalsePositives = falsePositives.size();
2029  const unsigned int numIgnored = ignore.size();
2030  unsigned int ignoredDetected = 0;
2031 
2032  falsePositivesDeleted = 0;
2033 
2034  for (unsigned int i = 0; i < numDeleted; i++)
2035  {
2036  unsigned int region = m_measure.deletedRegions[i];
2037 
2038  bool falsePositive = false;
2039 
2040  unsigned int j = 0;
2041  while (!falsePositive && (j < numFalsePositives))
2042  {
2043  if (region == falsePositives[j]) falsePositive = true;
2044  j++;
2045  }
2046 
2047  if (falsePositive)
2048  falsePositivesDeleted++;
2049  else
2050  {
2051  bool igno = false;
2052 
2053  j = 0;
2054  while (!igno && (j < numIgnored))
2055  {
2056  if (region == ignore[j]) igno = true;
2057  j++;
2058  }
2059 
2060  if (igno) ignoredDetected++;
2061  }
2062  }
2063 
2064  realFacesDeleted = numDeleted - falsePositivesDeleted - ignoredDetected;
2065 
2066  m_measure.faceNum = 0;
2067  m_measure.deletedRegions.clear();
2068 }
const float R
#define IS_CLASS(ptrObj, class_name)
Evaluates to true if the given pointer to an object (derived from mrpt::utils::CSerializable) is of t...
Definition: CObject.h:103
virtual void init(const mrpt::utils::CConfigFileBase &cfg)
Initialize cascade classifier detection.
std::shared_ptr< CDetectable2D > Ptr
std::shared_ptr< CDetectable3D > Ptr
Specific class for face detection.
void experimental_calcHist(const mrpt::utils::CImage &face, const size_t &c1, const size_t &r1, const size_t &c2, const size_t &r2, mrpt::math::CMatrixTemplate< unsigned int > &hist)
bool m_checkIfFaceRegions_res
Save result of checkIfFaceRegions filter.
void experimental_viewFacePointsScanned(const std::vector< float > &xs, const std::vector< float > &ys, const std::vector< float > &zs)
std::promise< void > m_enter_checkIfDiagonalSurface
Indicates to thread_checkIfDiagonalSurface that exist a new face to analyze.
bool checkIfDiagonalSurface2(mrpt::obs::CObservation3DRangeScan *face)
virtual void detectObjects_Impl(const mrpt::obs::CObservation *obs, vector_detectable_object &detected)
std::thread m_thread_checkIfDiagonalSurface
Thread that execute checkIfDiagonalSurface filter.
bool checkIfFacePlaneCov(mrpt::obs::CObservation3DRangeScan *face)
static void dummy_checkIfFacePlaneCov(CFaceDetection *obj)
std::promise< void > m_enter_checkIfFacePlaneCov
Indicates to thread_checkIfFacePlaneCov that exist a new face to analyze.
bool checkIfFaceRegions(mrpt::obs::CObservation3DRangeScan *face)
size_t checkRelativePosition(const mrpt::math::TPoint3D &p1, const mrpt::math::TPoint3D &p2, const mrpt::math::TPoint3D &p, double &dist)
std::vector< double > m_meanHist
std::promise< void > m_enter_checkIfFaceRegions
Indicates to thread_checkIfFaceRegions that exist a new face to analyze.
std::promise< void > m_leave_checkIfFaceRegions
Indicates to main thread that thread_checkIfFaceRegions has been completed analisis of the last face ...
bool checkIfDiagonalSurface(mrpt::obs::CObservation3DRangeScan *face)
mrpt::obs::CObservation3DRangeScan m_lastFaceDetected
Last face detected.
mrpt::utils::CTimeLogger m_timeLog
CCascadeClassifierDetection cascadeClassifier
std::thread m_thread_checkIfFacePlaneCov
Thread that execute checkIfFacePlaneCov filter.
std::promise< void > m_leave_checkIfFacePlaneCov
Indicates to main thread that thread_checkIfFacePlaneCov has been completed analisis of the last face...
bool m_end_threads
Indicates to all threads that must finish their execution.
struct mrpt::detectors::CFaceDetection::TMeasurement m_measure
static void dummy_checkIfFaceRegions(CFaceDetection *obj)
std::thread m_thread_checkIfFaceRegions
Thread that execute checkIfFaceRegions filter.
static void dummy_checkIfDiagonalSurface(CFaceDetection *obj)
bool m_checkIfFacePlaneCov_res
Save result of checkIfFacePlaneCov filter.
virtual void init(const mrpt::utils::CConfigFileBase &cfg)
Initialize the object with parameters loaded from the given config source.
void debug_returnResults(const vector_uint &falsePositives, const vector_uint &ignore, unsigned int &falsePositivesDeleted, unsigned int &realFacesDeleted)
void experimental_viewFacePointsAndEigenVects(const std::vector< mrpt::math::CArrayDouble< 3 >> &pointsVector, const mrpt::math::CMatrixDouble &eigenVect, const mrpt::math::CVectorDouble &eigenVal)
void experimental_viewRegions(const std::vector< mrpt::math::TPoint3D > regions[9], const mrpt::math::TPoint3D meanPos[3][3])
std::promise< void > m_leave_checkIfDiagonalSurface
Indicates to main thread that thread_checkIfDiagonalSurface has been completed analisis of the last f...
struct mrpt::detectors::CFaceDetection::TTestsOptions m_testsOptions
bool m_checkIfDiagonalSurface_res
Save result of checkIfDiagonalSurface filter.
void experimental_segmentFace(const mrpt::obs::CObservation3DRangeScan &face, mrpt::math::CMatrixTemplate< bool > &region)
bool checkIfFacePlane(mrpt::obs::CObservation3DRangeScan *face)
struct mrpt::detectors::CFaceDetection::TOptions m_options
void detectObjects(const mrpt::obs::CObservation::Ptr obs, vector_detectable_object &detected)
A graphical user interface (GUI) for efficiently rendering 3D scenes in real-time.
void setCameraPointingToPoint(float x, float y, float z)
Changes the camera parameters programmatically.
void unlockAccess3DScene()
Unlocks the access to the internal 3D scene.
void setCameraZoom(float zoom)
Changes the camera parameters programmatically.
void setWindowTitle(const std::string &str) override
Changes the window title.
mrpt::opengl::COpenGLScene::Ptr & get3DSceneAndLock()
Gets a reference to the smart shared pointer that holds the internal scene (carefuly read introductio...
void setCameraAzimuthDeg(float deg)
Changes the camera parameters programmatically.
void resize(unsigned int width, unsigned int height) override
Resizes the window, stretching the image to fit into the display area.
void repaint()
Repaints the window.
void setCameraElevationDeg(float deg)
Changes the camera parameters programmatically.
This class creates a window as a graphical user interface (GUI) for displaying images to the user.
void showImage(const mrpt::utils::CImage &img)
Show a given color or grayscale image on the window.
A map of 2D/3D points with individual colours (RGB).
void setPointColor(size_t index, float R, float G, float B)
Changes just the color of a given point from the map.
void setAllPoints(const std::vector< float > &X, const std::vector< float > &Y, const std::vector< float > &Z)
Set all the points at once from vectors with X,Y and Z coordinates.
Definition: CPointsMap.h:630
Declares a matrix of booleans (non serializable).
void set_unsafe(size_t row, size_t col, const T &v)
Fast but unsafe method to write a value in the matrix.
void setSize(size_t row, size_t col, bool zeroNewElements=false)
Changes the size of matrix, maintaining the previous contents.
const T & get_unsafe(size_t row, size_t col) const
Fast but unsafe method to read a value from the matrix.
size_t getColCount() const
Number of columns in the matrix.
size_t getRowCount() const
Number of rows in the matrix.
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction.
Definition: types_math.h:70
Declares a class derived from "CObservation" that encapsules a 3D range scan measurement,...
bool hasPoints3D
true means the field points3D contains valid data.
void getZoneAsObs(CObservation3DRangeScan &obs, const unsigned int &r1, const unsigned int &r2, const unsigned int &c1, const unsigned int &c2)
Extract a ROI of the 3D observation as a new one.
mrpt::math::CMatrix rangeImage
If hasRangeImage=true, a matrix of floats with the range data as captured by the camera (in meters)
Declares a class that represents any robot's observation.
Definition: CObservation.h:42
std::shared_ptr< CArrow > Ptr
Definition: CArrow.h:33
std::shared_ptr< COpenGLScene > Ptr
Definition: COpenGLScene.h:62
std::shared_ptr< CPointCloudColoured > Ptr
std::shared_ptr< CSetOfLines > Ptr
Definition: CSetOfLines.h:37
std::shared_ptr< CSphere > Ptr
Definition: CSphere.h:33
This class allows loading and storing values and vectors of different types from a configuration text...
bool read_bool(const std::string &section, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
double read_double(const std::string &section, const std::string &name, double defaultValue, bool failIfNotFound=false) const
int read_int(const std::string &section, const std::string &name, int defaultValue, bool failIfNotFound=false) const
A class for storing images as grayscale or RGB bitmaps.
Definition: CImage.h:119
std::string getStatsAsText(const size_t column_width=80) const
Dump all stats to a multi-line text string.
void enter(const char *func_name)
Start of a named section.
Definition: CTimeLogger.h:117
void enable(bool enabled=true)
Definition: CTimeLogger.h:107
double leave(const char *func_name)
End of a named section.
Definition: CTimeLogger.h:123
void meanAndStd(VEC &outMeanVector, VEC &outStdVector, const bool unbiased_variance=true) const
Computes a row with the mean values of each column in the matrix and the associated vector with the s...
GLsizei GLsizei GLuint * obj
Definition: glext.h:4070
GLenum GLenum GLvoid * row
Definition: glext.h:3576
GLuint start
Definition: glext.h:3528
GLuint res
Definition: glext.h:7268
const GLubyte * c
Definition: glext.h:6313
GLuint GLuint end
Definition: glext.h:3528
GLuint GLuint GLsizei count
Definition: glext.h:3528
GLenum GLint GLint y
Definition: glext.h:3538
GLenum GLuint GLint GLenum face
Definition: glext.h:8194
GLintptr offset
Definition: glext.h:3925
GLint GLvoid * img
Definition: glext.h:3763
GLenum GLint x
Definition: glext.h:3538
GLfloat GLfloat p
Definition: glext.h:6305
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
GLsizeiptr size
Definition: glext.h:3923
GLdouble GLdouble z
Definition: glext.h:3872
GLsizei const GLfloat * value
Definition: glext.h:4117
GLsizei const GLfloat * points
Definition: glext.h:5339
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
Definition: geometry.cpp:1885
double getRegressionPlane(const std::vector< TPoint3D > &points, TPlane &plane)
Using eigenvalues, gets the best fitting plane for a set of 3D points.
Definition: geometry.cpp:2157
std::vector< uint32_t > vector_uint
Definition: types_simple.h:29
void pause(const std::string &msg=std::string("Press any key to continue...")) noexcept
Shows the message "Press any key to continue" (or other custom message) to the current standard outpu...
Definition: os.cpp:427
#define MRPT_START
Definition: mrpt_macros.h:425
#define MRPT_TRY_START
Definition: mrpt_macros.h:408
#define MRPT_END
Definition: mrpt_macros.h:429
#define MRPT_TRY_END
Definition: mrpt_macros.h:409
std::vector< CDetectableObject::Ptr > vector_detectable_object
Classes for creating GUI windows for 2D and 3D visualization.
Definition: about_box.h:17
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:20
Eigen::Matrix< typename MATRIX::Scalar, MATRIX::ColsAtCompileTime, MATRIX::ColsAtCompileTime > cov(const MATRIX &v)
Computes the covariance matrix from a list of samples in an NxM matrix, where each row is a sample,...
Definition: ops_matrices.h:148
CONTAINER::Scalar sum(const CONTAINER &v)
Computes the sum of all the elements.
This namespace contains representation of robot actions and observations.
The namespace for 3D scene representation and rendering.
Definition: CGlCanvasBase.h:16
This namespace provides a OS-independent interface to many useful functions: filenames manipulation,...
Definition: math_frwds.h:31
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values,...
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
3D Plane, represented by its equation
Lightweight 3D point.
double distanceTo(const TPoint3D &p) const
Point-to-point distance.
double x
X,Y,Z coordinates.
3D segment, consisting of two points.
A RGB color - floats in the range [0,1].
Definition: TColor.h:79
A pair (x,y) of pixel coordinates (integer resolution).
Definition: TPixelCoord.h:39



Page generated by Doxygen 1.9.1 for MRPT 1.9.9 Git: 63ea9d1f1 Thu Nov 23 00:06:53 2017 +0100 at mar 26 may 2026 12:19:29 CEST