Main MRPT website > C++ reference for MRPT 1.9.9
CFeature.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 
11 #include "vision-precomp.h" // Precompiled headers
12 
18 #include <mrpt/vision/CFeature.h>
19 #include <mrpt/vision/types.h>
21 #include <mrpt/math/data_utils.h>
22 #include <mrpt/system/os.h>
23 
24 using namespace mrpt;
25 using namespace mrpt::vision;
26 using namespace mrpt::math;
27 using namespace mrpt::system;
28 using namespace mrpt::utils;
29 using namespace std;
30 
32 
33 // --------------------------------------------------
34 // loadFromConfigFile
35 // --------------------------------------------------
36 /** Load all the params from a config source, in the format described in
37  * saveToConfigFile()
38  */
39 void TMultiResDescMatchOptions::loadFromConfigFile(
40  const mrpt::utils::CConfigFileBase& cfg, const std::string& section)
41 {
42  useOriFilter = cfg.read_bool(section, "useOriFilter", true, false);
43  oriThreshold = cfg.read_double(section, "oriThreshold", 0.2, false);
44  lastSeenThreshold = cfg.read_int(section, "lastSeenThreshold", 10, false);
45  timesSeenThreshold = cfg.read_int(section, "timesSeenThreshold", 5, false);
46  minFeaturesToFind = cfg.read_int(section, "minFeaturesToFind", 5, false);
47  minFeaturesToBeLost =
48  cfg.read_int(section, "minFeaturesToBeLost", 5, false);
49 
50  useDepthFilter = cfg.read_bool(section, "useDepthFilter", true, false);
51 
52  matchingThreshold =
53  cfg.read_double(section, "matchingThreshold", 1e4, false);
54  matchingRatioThreshold =
55  cfg.read_double(section, "matchingRatioThreshold", 0.5, false);
56 
57  lowScl1 = cfg.read_int(section, "lowScl1", 0, false);
58  lowScl2 = cfg.read_int(section, "lowScl1", 0, false);
59  highScl1 = cfg.read_int(section, "highScl1", 6, false);
60  highScl2 = cfg.read_int(section, "highScl2", 6, false);
61 
62  searchAreaSize = cfg.read_double(section, "searchAreaSize", 20, false);
63 }
64 
65 // --------------------------------------------------
66 // saveToConfigFile
67 // --------------------------------------------------
69  mrpt::utils::CConfigFileBase& cfg, const std::string& section) const
70 {
71  if (useOriFilter)
72  {
73  cfg.write(section, "useOriFilter", "true");
74  cfg.write(section, "oriThreshold", oriThreshold);
75  }
76  else
77  cfg.write(section, "useOriFilter", "false");
78 
79  if (useDepthFilter)
80  cfg.write(section, "useDepthFilter", "true");
81  else
82  cfg.write(section, "useDepthFilter", "false");
83 
84  cfg.write(section, "matchingThreshold", matchingThreshold);
85  cfg.write(section, "matchingRatioThreshold", matchingRatioThreshold);
86  cfg.write(section, "lowScl1", lowScl1);
87  cfg.write(section, "lowScl2", lowScl2);
88  cfg.write(section, "highScl1", highScl1);
89  cfg.write(section, "highScl2", highScl2);
90 
91  cfg.write(section, "searchAreaSize", searchAreaSize);
92  cfg.write(section, "lastSeenThreshold", lastSeenThreshold);
93  cfg.write(section, "timesSeenThreshold", timesSeenThreshold);
94  cfg.write(section, "minFeaturesToFind", minFeaturesToFind);
95  cfg.write(section, "minFeaturesToBeLost", minFeaturesToBeLost);
96 } // end-saveToConfigFile
97 
98 // --------------------------------------------------
99 // dumpToTextStream
100 // --------------------------------------------------
102  mrpt::utils::CStream& out) const
103 {
104  out.printf(
105  "\n----------- [vision::TMultiResDescMatchOptions] ------------ \n");
106  out.printf("Use orientation filter?: ");
107  if (useOriFilter)
108  {
109  out.printf("Yes\n");
110  out.printf(
111  "ยท Orientation threshold: %.1f deg\n",
112  RAD2DEG(oriThreshold));
113  }
114  else
115  out.printf("No\n");
116  out.printf("Use depth filter?: ");
117  if (useDepthFilter)
118  out.printf("Yes\n");
119  else
120  {
121  out.printf("No\n");
122  out.printf("Lowest scale in list1: %d\n", lowScl1);
123  out.printf("Highest scale in list1: %d\n", highScl1);
124  out.printf("Lowest scale in list2: %d\n", lowScl2);
125  out.printf("Highest scale in list2: %d\n", highScl2);
126  }
127  out.printf("#frames last seen threshold: %d\n", lastSeenThreshold);
128  out.printf("#frames to be stable threshold: %d\n", timesSeenThreshold);
129  out.printf("min. # features in system: %d\n", minFeaturesToFind);
130  out.printf("min. # features to be lost: %d\n", minFeaturesToBeLost);
131  out.printf("Matching threshold: %.2f\n", matchingThreshold);
132  out.printf(
133  "Matching ratio threshold: %.2f\n", matchingRatioThreshold);
134  out.printf("Size of the search window: %d px\n", searchAreaSize);
135  out.printf("-------------------------------------------------------- \n");
136 } // end-dumpToTextStream
137 
138 // --------------------------------------------------
139 // loadFromConfigFile
140 // --------------------------------------------------
141 /** Load all the params from a config source, in the format described in
142  * saveToConfigFile()
143  */
145  const mrpt::utils::CConfigFileBase& cfg, const std::string& section)
146 {
147  basePSize = cfg.read_double(section, "basePSize", 23, false);
148  comLScl = cfg.read_int(section, "comLScl", 0, false);
149  comHScl = cfg.read_int(section, "comHScl", 6, false);
150  sg1 = cfg.read_double(section, "sg1", 0.5, false);
151  sg2 = cfg.read_double(section, "sg2", 7.5, false);
152  sg3 = cfg.read_double(section, "sg3", 8.0, false);
153  computeDepth = cfg.read_bool(section, "computeDepth", true, false);
154  blurImage = cfg.read_bool(section, "blurImage", true, false);
155  fx = cfg.read_double(section, "fx", 0.0, false);
156  cx = cfg.read_double(section, "cx", 0.0, false);
157  cy = cfg.read_double(section, "cy", 0.0, false);
158  baseline = cfg.read_double(section, "baseline", 0.0, false);
159  computeHashCoeffs =
160  cfg.read_bool(section, "computeHashCoeffs", false, false);
161 
162  cfg.read_vector(section, "scales", vector<double>(), scales, false);
163  if (scales.size() < 1)
164  {
165  scales.resize(7);
166  scales[0] = 0.5;
167  scales[1] = 0.8;
168  scales[2] = 1.0;
169  scales[3] = 1.2;
170  scales[4] = 1.5;
171  scales[5] = 1.8;
172  scales[6] = 2.0;
173  } // end-if
174 }
175 
176 // --------------------------------------------------
177 // saveToConfigFile
178 // --------------------------------------------------
180  mrpt::utils::CConfigFileBase& cfg, const std::string& section) const
181 {
182  cfg.write(section, "basePSize", basePSize);
183  cfg.write(section, "comLScl", comLScl);
184  cfg.write(section, "comHScl", comHScl);
185  cfg.write(section, "sg1", sg1);
186  cfg.write(section, "sg2", sg2);
187  cfg.write(section, "sg3", sg3);
188 
189  cfg.write(section, "computeDepth", computeDepth ? "true" : "false");
190  cfg.write(section, "blurImage", blurImage ? "true" : "false");
191  cfg.write(section, "fx", fx);
192  cfg.write(section, "cx", cx);
193  cfg.write(section, "cy", cy);
194  cfg.write(section, "baseline", baseline);
195  cfg.write(
196  section, "computeHashCoeffs", computeHashCoeffs ? "true" : "false");
197 
198  char buf[300];
199  for (unsigned int k = 0; k < scales.size(); ++k)
200  mrpt::system::os::sprintf(buf, 300, "%.2f ", scales[k]);
201  cfg.write(section, "scales", buf);
202 } // end-saveToConfigFile
203 
204 // --------------------------------------------------
205 // dumpToTextStream
206 // --------------------------------------------------
208 {
209  out.printf("\n----------- [vision::TMultiResDescOptions] ------------ \n");
210  out.printf("Base patch size: %d px\n", basePSize);
211  out.printf("Lowest scale to compute: %d\n", comLScl);
212  out.printf("Highest scale to compute: %d\n", comHScl);
213  out.printf("Image smoothing sigma: %.2f px\n", sg1);
214  out.printf("Orientation histogram sigma: %.2f\n", sg2);
215  out.printf("Descriptor histogram sigma: %.2f\n", sg3);
216  out.printf("Compute depth: ");
217  if (computeDepth)
218  {
219  out.printf("Yes\n");
220  out.printf("Focal length: %.2f px\n", fx);
221  out.printf("Principal point (cx): %.2f px\n", cx);
222  out.printf("Principal point (cy): %.2f px\n", cy);
223  out.printf("Baseline: %.2f m\n", baseline);
224  }
225  else
226  out.printf("No\n");
227 
228  out.printf("Compute Hash Coeffs: ");
229  if (computeHashCoeffs)
230  out.printf("Yes\n");
231  else
232  out.printf("No\n");
233 
234  out.printf("Blur image previously: ");
235  if (blurImage)
236  out.printf("Yes\n");
237  else
238  out.printf("No\n");
239 
240  out.printf("Scales: ");
241  for (unsigned int k = 0; k < scales.size(); ++k)
242  out.printf("%.2f ", scales[k]);
243  out.printf("\n");
244  out.printf("-------------------------------------------------------- \n");
245 } // end-dumpToTextStream
246 
248 {
249  out.printf("\n----------- [vision::CFeature] ------------ \n");
250  out.printf("Feature ID: %d\n", (int)ID);
251  out.printf("Coordinates: (%.2f,%.2f) px\n", x, y);
252  out.printf("PatchSize: %d\n", patchSize);
253  out.printf("Type: ");
254  switch (type)
255  {
256  case -1:
257  out.printf("Not defined\n");
258  break;
259  case 0:
260  out.printf("KLT\n");
261  break;
262  case 1:
263  out.printf("Harris\n");
264  break;
265  case 2:
266  out.printf("BCD\n");
267  break;
268  case 3:
269  out.printf("SIFT\n");
270  break;
271  case 4:
272  out.printf("SURF\n");
273  break;
274  case 5:
275  out.printf("Beacon\n");
276  break;
277  case 6:
278  out.printf("FAST\n");
279  break;
280  case 7:
281  out.printf("FASTER-9\n");
282  break;
283  case 8:
284  out.printf("FASTER-10\n");
285  break;
286  case 9:
287  out.printf("FASTER-12\n");
288  break;
289  case 10:
290  out.printf("ORB\n");
291  break;
292  case 11:
293  out.printf("AKAZE\n");
294  break;
295  case 12:
296  out.printf("LSD");
297  break;
298  }
299  out.printf("Status: ");
300  switch (track_status)
301  {
302  case 0:
303  out.printf("Idle\n");
304  break;
305  case 1:
306  out.printf("[KLT] Out of bounds [KLT]\n");
307  break;
308  case 5:
309  out.printf("[KLT] Tracked\n");
310  break;
311  case 10:
312  out.printf("[KLT] Lost\n");
313  break;
314  }
315 
316  out.printf("Response: %.2f\n", response);
317  out.printf("Main orientation: %.2f\n", orientation);
318  out.printf("Main scale: %.2f\n", scale);
319  out.printf("# frames seen: %d\n", nTimesSeen);
320  out.printf("# frames not seen: %d\n", nTimesNotSeen);
321  out.printf("# frames since last seen: %d\n", nTimesLastSeen);
322  out.printf("Initial Depth: %.2f m\n", initialDepth);
323  out.printf("Depth: %.2f m\n", depth);
324  out.printf(
325  "3D point: (%.2f,%.2f,%.2f) m\n", p3D.x, p3D.y,
326  p3D.z);
327  out.printf("Is point feature?: ");
328  isPointFeature() ? out.printf("Yes\n") : out.printf("No\n");
329 
330  out.printf("Has SIFT descriptor?: ");
331  descriptors.hasDescriptorSIFT() ? out.printf("Yes\n") : out.printf("No\n");
332  out.printf("Has SURF descriptor?: ");
333  descriptors.hasDescriptorSURF() ? out.printf("Yes\n") : out.printf("No\n");
334  out.printf("Has Spin image descriptor?: ");
335  descriptors.hasDescriptorSpinImg() ? out.printf("Yes\n")
336  : out.printf("No\n");
337  out.printf("Has Polar descriptor?: ");
338  descriptors.hasDescriptorPolarImg() ? out.printf("Yes\n")
339  : out.printf("No\n");
340  out.printf("Has Log Polar descriptor?: ");
341  descriptors.hasDescriptorLogPolarImg() ? out.printf("Yes\n")
342  : out.printf("No\n");
343  out.printf("Has ORB descriptor?: ");
344  descriptors.hasDescriptorORB() ? out.printf("Yes\n") : out.printf("No\n");
345  //# added by Raghavender Sahdev
346  out.printf("Has BLD descriptor?: ");
347  descriptors.hasDescriptorBLD() ? out.printf("Yes\n") : out.printf("No\n");
348  out.printf("Has LATCH descriptor?: ");
349  descriptors.hasDescriptorLATCH() ? out.printf("Yes\n") : out.printf("No\n");
350 
351  out.printf("Has multiscale?: ");
352  if (!descriptors.hasDescriptorMultiSIFT())
353  out.printf("No\n");
354  else
355  {
356  out.printf("Yes [%d]\n", (int)multiScales.size());
357  for (int k = 0; k < (int)multiScales.size(); ++k)
358  {
359  out.printf(" ยท Scale %d: %.2f\n", k, multiScales[k]);
360  for (int m = 0; m < (int)multiOrientations[k].size(); ++m)
361  {
362  out.printf(
363  " ยทยท Orientation %d: %.2f\n", m, multiOrientations[k][m]);
364  out.printf(" ยทยท [D] ");
365  for (int n = 0;
366  n < (int)descriptors.multiSIFTDescriptors[k][m].size();
367  ++n)
368  out.printf(
369  "%d ", descriptors.multiSIFTDescriptors[k][m][n]);
370  out.printf("\n");
371  if (multiHashCoeffs.size() > 0)
372  out.printf(
373  " ยทยท HASH coefficients %d,%d,%d\n",
374  multiHashCoeffs[k][m][0], multiHashCoeffs[k][m][1],
375  multiHashCoeffs[k][m][2]);
376  } // end-for-m
377  } // end-for-k
378  } // end else
379 } // end dumpToTextStream
380 
382 {
383  CStdOutStream myOut;
384  dumpToTextStream(myOut);
385 }
386 
387 void CFeature::writeToStream(mrpt::utils::CStream& out, int* version) const
388 {
389  if (version)
390  *version = 2;
391  else
392  {
393  // The coordinates:
394  out << x << y << ID << patch << patchSize << (uint32_t)type
395  << (uint32_t)track_status << response << orientation << scale
396  << user_flags << nTimesSeen << nTimesNotSeen << nTimesLastSeen
397  << depth << initialDepth << p3D << multiScales << multiOrientations
398  << multiHashCoeffs << descriptors.SIFT << descriptors.SURF
399  << descriptors.SpinImg << descriptors.SpinImg_range_rows
400  << descriptors.PolarImg << descriptors.LogPolarImg
401  << descriptors.polarImgsNoRotation
402  << descriptors.multiSIFTDescriptors << descriptors.ORB
403  //# ADDED by Raghavender Sahdev
404  << descriptors.BLD << descriptors.LATCH;
405  }
406 }
407 
409 {
410  switch (version)
411  {
412  case 0:
413  case 1:
414  case 2:
415  {
416  // The coordinates:
417  uint32_t aux_type, aux_KLTS;
418  in >> x >> y >> ID >> patch >> patchSize >> aux_type >> aux_KLTS >>
419  response >> orientation >> scale >> user_flags;
420  if (version > 0)
421  {
422  in >> nTimesSeen >> nTimesNotSeen >> nTimesLastSeen >> depth >>
423  initialDepth >> p3D >> multiScales >> multiOrientations >>
424  multiHashCoeffs;
425  }
426  in >> descriptors.SIFT >> descriptors.SURF >> descriptors.SpinImg >>
427  descriptors.SpinImg_range_rows >> descriptors.PolarImg >>
428  descriptors.LogPolarImg >> descriptors.polarImgsNoRotation
429  // # added by Raghavender Sahdev
430  >> descriptors.BLD >> descriptors.LATCH;
431  if (version > 0) in >> descriptors.multiSIFTDescriptors;
432  if (version > 1) in >> descriptors.ORB;
433 
434  type = (TFeatureType)aux_type;
435  track_status = (TFeatureTrackStatus)aux_KLTS;
436  }
437  break;
438  default:
440  };
441 }
442 
443 /****************************************************
444  Class CFEATURE
445 *****************************************************/
446 // CONSTRUCTOR
448  : x(0.0f),
449  y(0.0f),
450  ID(0),
451  patchSize(21),
453  track_status(status_IDLE),
454  response(0.0),
455  orientation(0.0),
456  scale(0.0),
457  user_flags(0),
458  nTimesSeen(1),
459  nTimesNotSeen(0),
460  nTimesLastSeen(0),
461  depth(0),
462  initialDepth(0),
463  p3D(),
464  multiScales(),
465  multiOrientations(),
466  multiHashCoeffs(),
467  descriptors()
468 {
469 }
470 
471 // Ctor
473  : SIFT(),
474  SURF(),
475  SpinImg(),
476  SpinImg_range_rows(0),
477  PolarImg(0, 0),
478  LogPolarImg(0, 0),
479  polarImgsNoRotation(false),
480  ORB(),
481  BLD(),
482  LATCH()
483 {
484 }
485 
486 // Return false only for Blob detectors (SIFT, SURF)
488 {
489  return type == featSIFT || type == featSURF;
490 }
491 
492 // --------------------------------------------------
493 // patchCorrelationTo
494 // --------------------------------------------------
495 float CFeature::patchCorrelationTo(const CFeature& oFeature) const
496 {
497  MRPT_START
498  ASSERT_(patch.getWidth() == oFeature.patch.getWidth())
499  ASSERT_(patch.getHeight() == oFeature.patch.getHeight())
500  ASSERT_(patch.getHeight() > 0 && patch.getWidth() > 0)
501 
502  size_t x_max, y_max;
503  double max_val;
504  patch.cross_correlation(oFeature.patch, x_max, y_max, max_val);
505 
506  return 0.5 -
507  0.5 * max_val; // Value as "distance" in the range [0,1], best = 0
508 
509  MRPT_END
510 }
511 
512 // --------------------------------------------------
513 // descriptorDistanceTo
514 // --------------------------------------------------
516  const CFeature& oFeature, TDescriptorType descriptorToUse,
517  bool normalize_distances) const
518 {
519  MRPT_START
520 
521  // If we are not ask for a specific descriptor, select the first one found:
522  if (descriptorToUse == descAny)
523  {
525  descriptorToUse = descSIFT;
526  else if (descriptors.hasDescriptorSURF())
527  descriptorToUse = descSURF;
529  descriptorToUse = descSpinImages;
531  descriptorToUse = descPolarImages;
533  descriptorToUse = descLogPolarImages;
534  else if (descriptors.hasDescriptorORB())
535  descriptorToUse = descORB;
536  // # added by Raghavender Sahdev - BLD/LATCH descriptors
537  else if (descriptors.hasDescriptorBLD())
538  descriptorToUse = descBLD;
539  else if (descriptors.hasDescriptorLATCH())
540  descriptorToUse = descLATCH;
541  else
543  "Feature has no descriptors and descriptorToUse=descAny")
544  }
545 
546  switch (descriptorToUse)
547  {
548  case descSIFT:
549  return descriptorSIFTDistanceTo(oFeature, normalize_distances);
550  case descSURF:
551  return descriptorSURFDistanceTo(oFeature, normalize_distances);
552  case descSpinImages:
553  return descriptorSpinImgDistanceTo(oFeature, normalize_distances);
554  case descPolarImages:
555  {
556  float minAng;
558  oFeature, minAng, normalize_distances);
559  }
560  case descLogPolarImages:
561  {
562  float minAng;
564  oFeature, minAng, normalize_distances);
565  }
566  case descORB:
567  return float(descriptorORBDistanceTo(oFeature));
568  // # added by Raghavender Sahdev
569  case descBLD:
570  return (descriptorBLDDistanceTo(oFeature));
571  case descLATCH:
572  return (descriptorLATCHDistanceTo(oFeature));
573  default:
575  "Unknown value for 'descriptorToUse'=%u",
576  (unsigned)descriptorToUse);
577  }
578 
579  MRPT_END
580 }
581 
582 // --------------------------------------------------
583 // descriptorSIFTDistanceTo
584 // --------------------------------------------------
586  const CFeature& oFeature, bool normalize_distances) const
587 {
588  ASSERT_(this->descriptors.SIFT.size() == oFeature.descriptors.SIFT.size());
589  ASSERT_(
590  this->descriptors.hasDescriptorSIFT() &&
591  oFeature.descriptors.hasDescriptorSIFT())
592 
593  float dist = 0.0f;
595  for (itDesc1 = this->descriptors.SIFT.begin(),
596  itDesc2 = oFeature.descriptors.SIFT.begin();
597  itDesc1 != this->descriptors.SIFT.end(); itDesc1++, itDesc2++)
598  {
599  dist += square(*itDesc1 - *itDesc2);
600  }
601  if (normalize_distances) dist /= this->descriptors.SIFT.size();
602  dist = sqrt(dist);
603  if (normalize_distances) dist /= 64.0f;
604  return dist;
605 } // end descriptorSIFTDistanceTo
606 
607 // --------------------------------------------------
608 // descriptorSURFDistanceTo
609 // --------------------------------------------------
611  const CFeature& oFeature, bool normalize_distances) const
612 {
613  ASSERT_(this->descriptors.SURF.size() == oFeature.descriptors.SURF.size());
614  ASSERT_(
615  this->descriptors.hasDescriptorSURF() &&
616  oFeature.descriptors.hasDescriptorSURF())
617 
618  float dist = 0.0f;
619  std::vector<float>::const_iterator itDesc1, itDesc2;
620  for (itDesc1 = this->descriptors.SURF.begin(),
621  itDesc2 = oFeature.descriptors.SURF.begin();
622  itDesc1 != this->descriptors.SURF.end(); itDesc1++, itDesc2++)
623  {
624  dist += square(*itDesc1 - *itDesc2);
625  }
626  if (normalize_distances) dist /= this->descriptors.SURF.size();
627  dist = sqrt(dist);
628  if (normalize_distances)
629  dist /= 0.20f; // JL: Ad-hoc value! Investigate where does this come
630  // from...
631  return dist;
632 } // end descriptorSURFDistanceTo
633 
634 // --------------------------------------------------
635 // descriptorSpinImgDistanceTo
636 // --------------------------------------------------
638  const CFeature& oFeature, bool normalize_by_vector_length) const
639 {
640  ASSERT_(
641  this->descriptors.SpinImg.size() ==
642  oFeature.descriptors.SpinImg.size());
643  ASSERT_(
646  ASSERT_(!this->descriptors.SpinImg.empty())
647 
648  float dist = 0.0f;
649  std::vector<float>::const_iterator itDesc1, itDesc2;
650  for (itDesc1 = this->descriptors.SpinImg.begin(),
651  itDesc2 = oFeature.descriptors.SpinImg.begin();
652  itDesc1 != this->descriptors.SpinImg.end(); itDesc1++, itDesc2++)
653  {
654  dist += square(*itDesc1 - *itDesc2);
655  }
656 
657  if (normalize_by_vector_length) dist /= 0.25 * descriptors.SpinImg.size();
658 
659  return sqrt(dist);
660 } // end descriptorSpinImgDistanceTo
661 
662 // --------------------------------------------------
663 // descriptorPolarImgDistanceTo
664 // --------------------------------------------------
666  const CMatrix& desc1, const CMatrix& desc2, float& minDistAngle,
667  bool normalize_distances, bool dont_shift_angle)
668 {
669  MRPT_START
670 
671  // Find the smallest distance:
672  unsigned int delta, i, j, ii, height = desc1.getRowCount(),
673  width = desc1.getColCount();
674  float dist, minDist = 0;
675 
676 //#define LM_CORR_BIAS_MEAN
677 
678 #define LM_CORR_METHOD_EUCLID
679 //#define LM_CORR_METHOD_MANHATTAN
680 //#define LM_CORR_METHOD_CORRELATION
681 
682 #if defined(LM_CORR_BIAS_MEAN) || defined(LM_CORR_METHOD_CORRELATION)
683  const float desc1_mean = desc1.sum() / static_cast<float>(width * height);
684  const float desc2_mean = desc2.sum() / static_cast<float>(width * height);
685 #endif
686 
687  CVectorFloat distances(height, 0); // Distances for each shift
688 
689  for (delta = 0; delta < height; delta++)
690  {
691 #if defined(LM_CORR_METHOD_CORRELATION)
692  float s11 = 0;
693  float s22 = 0;
694  float s12 = 0;
695 #endif
696  // Compute the mean distance between desc1[t] and desc2[t-delta]:
697  dist = 0;
698  for (i = 0; i < height; i++)
699  {
700  ii = (i + delta) % height; // Shifted index
701  for (j = 0; j < width; j++)
702  {
703 #ifdef LM_CORR_METHOD_EUCLID
704 #ifdef LM_CORR_BIAS_MEAN
705  dist += square(
706  desc1.get_unsafe(i, j) - desc1_mean -
707  desc2.get_unsafe(ii, j) + desc2_mean);
708 #else
709  dist +=
710  square(desc1.get_unsafe(i, j) - desc2.get_unsafe(ii, j));
711 #endif
712 #elif defined(LM_CORR_METHOD_MANHATTAN)
713 #ifdef LM_CORR_BIAS_MEAN
714  dist +=
715  abs(desc1.get_unsafe(i, j) - desc1_mean -
716  desc2.get_unsafe(ii, j) + desc2_mean);
717 #else
718  dist += abs(desc1.get_unsafe(i, j) - desc2.get_unsafe(ii, j));
719 #endif
720 #elif defined(LM_CORR_METHOD_CORRELATION)
721  float d1 = desc1.get_unsafe(i, j) - desc1_mean;
722  float d2 = desc2.get_unsafe(ii, j) - desc2_mean;
723  s11 += square(d1);
724  s22 += square(d2);
725  s12 += d1 * d2;
726 #else
727 #error A LM_CORR_METHOD_XXX method must be selected!
728 #endif
729  }
730  }
731 
732  // Average:
733  if (normalize_distances) dist /= static_cast<float>(width * height);
734 
735 #ifdef LM_CORR_METHOD_EUCLID
736  dist = sqrt(dist);
737 #endif
738 
739 #if defined(LM_CORR_METHOD_CORRELATION)
740  dist = 1 - (s12 / sqrt(s11 * s22));
741 #endif
742 
743  distances[delta] = dist;
744  if (!delta && dont_shift_angle)
745  {
746  distances.resize(1);
747  break;
748  }
749  } // end for delta
750 
751  size_t minDistIdx;
752  minDist = distances.minimum(&minDistIdx);
753 
754  double dist_mean, dist_std;
755  mrpt::math::meanAndStd(distances, dist_mean, dist_std);
756 
757 #if 0
758  {
759  cout << "min dist: " << minDist << endl;
760 
761  static mrpt::gui::CDisplayWindowPlots win("distances");
762  win.plot(distances,"b.4");
763  CImage img1(desc1);
764  win.image(img1,0,-0.5,0.4*width,0.5,"img1");
765 
766  CImage img2(desc2);
767  win.image(img2,0.6*width,-0.5,0.4*width,0.5,"img2");
768 
769  //win.axis_fit();
770  win.waitForKey();
771  }
772 #endif
773 
774  // Output:
775  minDistAngle = minDistIdx * M_2PI / static_cast<float>(width);
776  return minDist;
777 
778  MRPT_END
779 }
780 
781 // --------------------------------------------------
782 // descriptorPolarImgDistanceTo
783 // --------------------------------------------------
785  const CFeature& oFeature, float& minDistAngle,
786  bool normalize_distances) const
787 {
788  MRPT_START
789 
790  ASSERT_(
791  size(descriptors.PolarImg, 1) == size(oFeature.descriptors.PolarImg, 1))
792  ASSERT_(
793  size(descriptors.PolarImg, 2) == size(oFeature.descriptors.PolarImg, 2))
794  ASSERT_(
797  ASSERT_(
798  size(descriptors.PolarImg, 1) > 1 && size(descriptors.PolarImg, 2) > 1)
799 
800  // Call the common method for computing these distances:
802  descriptors.PolarImg, oFeature.descriptors.PolarImg, minDistAngle,
803  normalize_distances, descriptors.polarImgsNoRotation);
804 
805  MRPT_END
806 } // end descriptorPolarImgDistanceTo
807 
808 // --------------------------------------------------
809 // descriptorLogPolarImgDistanceTo
810 // --------------------------------------------------
812  const CFeature& oFeature, float& minDistAngle,
813  bool normalize_distances) const
814 {
815  MRPT_START
816 
817  ASSERT_(
819  size(oFeature.descriptors.LogPolarImg, 1))
820  ASSERT_(
822  size(oFeature.descriptors.LogPolarImg, 2))
823  ASSERT_(
826  ASSERT_(
827  size(descriptors.LogPolarImg, 1) > 1 &&
828  size(descriptors.LogPolarImg, 2) > 1)
829 
830  // Call the common method for computing these distances:
832  descriptors.LogPolarImg, oFeature.descriptors.LogPolarImg, minDistAngle,
833  normalize_distances, descriptors.polarImgsNoRotation);
834 
835  MRPT_END
836 } // end descriptorPolarImgDistanceTo
837 
838 // --------------------------------------------------
839 // descriptorORBDistanceTo
840 // --------------------------------------------------
842 {
843  ASSERT_(
844  this->descriptors.hasDescriptorORB() &&
845  oFeature.descriptors.hasDescriptorORB())
846  ASSERT_(this->descriptors.ORB.size() == oFeature.descriptors.ORB.size())
847 
848  const std::vector<uint8_t>& t_desc = this->descriptors.ORB;
849  const std::vector<uint8_t>& o_desc = oFeature.descriptors.ORB;
850 
851  // Descriptors XOR + Hamming weight
852  uint8_t distance = 0;
853  for (uint8_t k = 0; k < t_desc.size(); ++k)
854  {
855  uint8_t x_or = t_desc[k] ^ o_desc[k];
856  uint8_t count; // from : Wegner, Peter (1960), "A technique for
857  // counting ones in a binary computer", Communications
858  // of the ACM 3 (5): 322, doi:10.1145/367236.367286
859  for (count = 0; x_or; count++) // ...
860  x_or &= x_or - 1; // ...
861  distance += count;
862  }
863 
864  return float(distance);
865 } // end-descriptorORBDistanceTo
866 
867 // # added by Raghavender Sahdev
868 // --------------------------------------------------
869 // descriptorBLDDistanceTo
870 // --------------------------------------------------
872  const CFeature& oFeature, bool normalize_distances) const
873 {
874  ASSERT_(this->descriptors.BLD.size() == oFeature.descriptors.BLD.size());
875  ASSERT_(
876  this->descriptors.hasDescriptorBLD() &&
877  oFeature.descriptors.hasDescriptorBLD())
878 
879  float dist = 0.0f;
881  for (itDesc1 = this->descriptors.BLD.begin(),
882  itDesc2 = oFeature.descriptors.BLD.begin();
883  itDesc1 != this->descriptors.BLD.end(); itDesc1++, itDesc2++)
884  {
885  dist += square(*itDesc1 - *itDesc2);
886  }
887  if (normalize_distances) dist /= this->descriptors.BLD.size();
888  dist = sqrt(dist);
889  if (normalize_distances) dist /= 64.0f;
890  return dist;
891 } // end descriptorBLDDistanceTo
892 
893 // --------------------------------------------------
894 // descriptorLATCHDistanceTo
895 // --------------------------------------------------
897  const CFeature& oFeature, bool normalize_distances) const
898 {
899  ASSERT_(
900  this->descriptors.LATCH.size() == oFeature.descriptors.LATCH.size());
901  ASSERT_(
903  oFeature.descriptors.hasDescriptorLATCH())
904 
905  float dist = 0.0f;
907  for (itDesc1 = this->descriptors.LATCH.begin(),
908  itDesc2 = oFeature.descriptors.LATCH.begin();
909  itDesc1 != this->descriptors.LATCH.end(); itDesc1++, itDesc2++)
910  {
911  dist += square(*itDesc1 - *itDesc2);
912  }
913  if (normalize_distances) dist /= this->descriptors.LATCH.size();
914  dist = sqrt(dist);
915  if (normalize_distances) dist /= 64.0f;
916  return dist;
917 } // end descriptorLATCHDistanceTo
918 
919 // --------------------------------------------------
920 // saveToTextFile
921 // --------------------------------------------------
922 void CFeature::saveToTextFile(const std::string& filename, bool APPEND)
923 {
924  MRPT_START
925  // "%% Dump of mrpt::vision::CFeatureList. Each line format is:\n"
926  // "%% ID TYPE X Y ORIENTATION SCALE TRACK_STATUS RESPONSE HAS_SIFT
927  // [SIFT] HAS_SURF [SURF] HAS_MULTI [MULTI_i] HAS_ORB [ORB]"
928  // "%% \\---------------------- feature ------------------/ \\---------
929  // descriptors -------/\n"
930  // "%% with:\n"
931  // "%% TYPE : The used detector: 0:KLT, 1: Harris, 2: BCD, 3: SIFT, 4:
932  // SURF, 5: Beacon, 6: FAST\n"
933  // "%% HAS_* : 1 if a descriptor of that type is associated to the
934  // feature. \n"
935  // "%% SIFT : Present if HAS_SIFT=1: N DESC_0 ... DESC_N-1 \n"
936  // "%% SURF : Present if HAS_SURF=1: N DESC_0 ... DESC_N-1 \n"
937  // "%% MULTI : Present if HAS_MULTI=1: SCALE ORI N DESC_0 ... DESC_N-1"
938  // "%% ORB : Present if HAS_ORB=1: VALUE
939  // "%%-------------------------------------------------------------------------------------------\n");
941 
942  if (!f.open(filename, APPEND))
944  "[CFeature::saveToTextFile] ERROR: File could not be open for "
945  "writing");
946 
947  f.printf(
948  "%5u %2d %7.3f %7.3f %6.2f %6.2f %2d %6.3f ", (unsigned int)this->ID,
949  (int)this->get_type(), this->x, this->y, this->orientation, this->scale,
950  (int)this->track_status, this->response);
951 
952  f.printf("%2d ", int(this->descriptors.hasDescriptorSIFT() ? 1 : 0));
953  if (this->descriptors.hasDescriptorSIFT())
954  {
955  f.printf("%4d ", int(this->descriptors.SIFT.size()));
956  for (unsigned int k = 0; k < this->descriptors.SIFT.size(); k++)
957  f.printf("%4d ", this->descriptors.SIFT[k]);
958  }
959 
960  f.printf("%2d ", int(this->descriptors.hasDescriptorSURF() ? 1 : 0));
961  if (this->descriptors.hasDescriptorSURF())
962  {
963  f.printf("%4d ", int(this->descriptors.SURF.size()));
964  for (unsigned int k = 0; k < this->descriptors.SURF.size(); k++)
965  f.printf("%8.5f ", this->descriptors.SURF[k]);
966  }
967 
968  f.printf("%2d ", int(this->descriptors.hasDescriptorMultiSIFT() ? 1 : 0));
970  {
971  for (int k = 0; k < int(this->multiScales.size()); ++k)
972  {
973  for (int m = 0; m < int(this->multiOrientations[k].size()); ++m)
974  {
975  f.printf(
976  "%.2f %6.2f ", this->multiScales[k],
977  this->multiOrientations[k][m]);
978  f.printf(
979  "%4d ",
980  int(this->descriptors.multiSIFTDescriptors[k][m].size()));
981  for (unsigned int n = 0;
982  n < this->descriptors.multiSIFTDescriptors[k][m].size();
983  ++n)
984  f.printf(
985  "%4d ",
986  this->descriptors.multiSIFTDescriptors[k][m][n]);
987  }
988  } // end-for
989  } // end-if
990 
991  f.printf("%2d ", int(this->descriptors.hasDescriptorORB() ? 1 : 0));
992  if (this->descriptors.hasDescriptorORB())
993  for (size_t k = 0; k < this->descriptors.ORB.size(); ++k)
994  f.printf("%d ", this->descriptors.ORB[k]);
995 
996  // # ADDED by Raghavender Sahdev
997  f.printf("%2d ", int(this->descriptors.hasDescriptorBLD() ? 1 : 0));
998  if (this->descriptors.hasDescriptorBLD())
999  {
1000  f.printf("%4d ", int(this->descriptors.BLD.size()));
1001  for (unsigned int k = 0; k < this->descriptors.BLD.size(); k++)
1002  f.printf("%4d ", this->descriptors.BLD[k]);
1003  }
1004 
1005  f.printf("%2d ", int(this->descriptors.hasDescriptorLATCH() ? 1 : 0));
1006  if (this->descriptors.hasDescriptorLATCH())
1007  {
1008  f.printf("%4d ", int(this->descriptors.LATCH.size()));
1009  for (unsigned int k = 0; k < this->descriptors.LATCH.size(); k++)
1010  f.printf("%4d ", this->descriptors.LATCH[k]);
1011  }
1012 
1013  f.printf("\n");
1014  f.close();
1015 
1016  MRPT_END
1017 } // end saveToTextFile
1018 
1019 /****************************************************
1020  Class CFEATURELIST
1021 *****************************************************/
1022 // --------------------------------------------------
1023 // CONSTRUCTOR
1024 // --------------------------------------------------
1025 CFeatureList::CFeatureList() {} // end constructor
1026 // --------------------------------------------------
1027 // DESTRUCTOR
1028 // --------------------------------------------------
1029 CFeatureList::~CFeatureList() {} // end destructor
1030 // --------------------------------------------------
1031 // saveToTextFile
1032 // --------------------------------------------------
1033 // FORMAT: ID type x y orientation scale [descriptorSIFT] [descriptorSURF]
1034 // track_status response
1035 void CFeatureList::saveToTextFile(const std::string& filename, bool APPEND)
1036 {
1037  MRPT_START
1038 
1040 
1041  if (!f.open(filename, APPEND))
1043  "[CFeatureList::saveToTextFile] ERROR: File could not be open for "
1044  "writing");
1045 
1046  f.printf(
1047  "%% Dump of mrpt::vision::CFeatureList. Each line format is:\n"
1048  "%% ID TYPE X Y ORIENTATION SCALE TRACK_STATUS RESPONSE HAS_SIFT "
1049  "[SIFT] HAS_SURF [SURF]\n"
1050  "%% \\---------------------- feature ------------------/ \\--------- "
1051  "descriptors -------/\n"
1052  "%% with:\n"
1053  "%% TYPE : The used detector: 0:KLT, 1: Harris, 2: BCD, 3: SIFT, 4: "
1054  "SURF, 5: Beacon, 6: FAST\n"
1055  "%% HAS_* : 1 if a descriptor of that type is associated to the "
1056  "feature. \n"
1057  "%% SIFT : Present if HAS_SIFT=1: N DESC_0 ... DESC_N-1 \n"
1058  "%% SURF : Present if HAS_SURF=1: N DESC_0 ... DESC_N-1 \n"
1059  "%%--------------------------------------------------------------------"
1060  "-----------------------\n");
1061 
1062  for (CFeatureList::iterator it = this->begin(); it != this->end(); ++it)
1063  {
1064  f.printf(
1065  "%5u %2d %7.3f %7.3f %6.2f %6.2f %2d %6.3f ",
1066  (unsigned int)(*it)->ID, (int)(*it)->get_type(), (*it)->x, (*it)->y,
1067  (*it)->orientation, (*it)->scale, (int)(*it)->track_status,
1068  (*it)->response);
1069 
1070  f.printf("%2d ", int((*it)->descriptors.hasDescriptorSIFT() ? 1 : 0));
1071  if ((*it)->descriptors.hasDescriptorSIFT())
1072  {
1073  f.printf("%4d ", int((*it)->descriptors.SIFT.size()));
1074  for (unsigned int k = 0; k < (*it)->descriptors.SIFT.size(); k++)
1075  f.printf("%4d ", (*it)->descriptors.SIFT[k]);
1076  }
1077 
1078  f.printf("%2d ", int((*it)->descriptors.hasDescriptorSURF() ? 1 : 0));
1079  if ((*it)->descriptors.hasDescriptorSURF())
1080  {
1081  f.printf("%4d ", int((*it)->descriptors.SURF.size()));
1082  for (unsigned int k = 0; k < (*it)->descriptors.SURF.size(); k++)
1083  f.printf("%8.5f ", (*it)->descriptors.SURF[k]);
1084  }
1085  // # added by Raghavender Sahdev
1086  f.printf("%2d ", int((*it)->descriptors.hasDescriptorBLD() ? 1 : 0));
1087  if ((*it)->descriptors.hasDescriptorBLD())
1088  {
1089  f.printf("%4d ", int((*it)->descriptors.BLD.size()));
1090  for (unsigned int k = 0; k < (*it)->descriptors.BLD.size(); k++)
1091  f.printf("%4d ", (*it)->descriptors.BLD[k]);
1092  }
1093 
1094  f.printf("%2d ", int((*it)->descriptors.hasDescriptorLATCH() ? 1 : 0));
1095  if ((*it)->descriptors.hasDescriptorLATCH())
1096  {
1097  f.printf("%4d ", int((*it)->descriptors.LATCH.size()));
1098  for (unsigned int k = 0; k < (*it)->descriptors.LATCH.size(); k++)
1099  f.printf("%4d ", (*it)->descriptors.LATCH[k]);
1100  }
1101 
1102  f.printf("\n");
1103  } // end for
1104 
1105  f.close();
1106 
1107  MRPT_END
1108 } // end saveToTextFile
1109 
1110 // --------------------------------------------------
1111 // loadFromTextFile
1112 // --------------------------------------------------
1114 {
1115  MRPT_START
1116 
1117  mrpt::utils::CTextFileLinesParser parser(filename);
1118  std::istringstream line;
1119 
1120  while (parser.getNextLine(line))
1121  {
1122  try
1123  {
1124  CFeature::Ptr feat_ptr = std::make_shared<CFeature>();
1125  CFeature* feat = feat_ptr.get(); // for faster access
1126 
1127  int _ID;
1128  if (!(line >> _ID)) throw std::string("ID");
1129  feat->ID = TFeatureID(_ID);
1130 
1131  int _type;
1132  if (!(line >> _type)) throw std::string("type");
1133  feat->type = TFeatureType(_type);
1134 
1135  if (!(line >> feat->x >> feat->y)) throw std::string("x,y");
1136  if (!(line >> feat->orientation)) throw std::string("orientation");
1137  if (!(line >> feat->scale)) throw std::string("scale");
1138 
1139  int _track_st;
1140  if (!(line >> _track_st)) throw std::string("track_status");
1141  feat->track_status = TFeatureTrackStatus(_track_st);
1142 
1143  if (!(line >> feat->response)) throw std::string("response");
1144 
1145  int hasSIFT;
1146  if (!(line >> hasSIFT)) throw std::string("hasSIFT");
1147  if (hasSIFT)
1148  {
1149  size_t N;
1150  if (!(line >> N)) throw std::string("SIFT-len");
1151  feat->descriptors.SIFT.resize(N);
1152  for (size_t i = 0; i < N; i++)
1153  {
1154  int val;
1155  line >> val;
1156  feat->descriptors.SIFT[i] =
1157  val; // DON'T read directly SIFT[i] since it's a
1158  // uint8_t, interpreted as a cha
1159  }
1160 
1161  if (!line) throw std::string("SIFT-data");
1162  }
1163 
1164  //# ADDED by Raghavender Sahdev
1165  int hasBLD;
1166  if (!(line >> hasBLD)) throw std::string("hasBLD");
1167  if (hasBLD)
1168  {
1169  size_t N;
1170  if (!(line >> N)) throw std::string("BLD-len");
1171  feat->descriptors.BLD.resize(N);
1172  for (size_t i = 0; i < N; i++)
1173  {
1174  int val;
1175  line >> val;
1176  feat->descriptors.BLD[i] =
1177  val; // comment copied from SIFT, DON'T read directly
1178  // SIFT[i] since it's a uint8_t, interpreted as a
1179  // cha
1180  }
1181 
1182  if (!line) throw std::string("BLD-data");
1183  }
1184 
1185  int hasLATCH;
1186  if (!(line >> hasLATCH)) throw std::string("hasLATCH");
1187  if (hasBLD)
1188  {
1189  size_t N;
1190  if (!(line >> N)) throw std::string("LATCH-len");
1191  feat->descriptors.LATCH.resize(N);
1192  for (size_t i = 0; i < N; i++)
1193  {
1194  int val;
1195  line >> val;
1196  feat->descriptors.LATCH[i] =
1197  val; // comment copied from SIFT, DON'T read directly
1198  // SIFT[i] since it's a uint8_t, interpreted as a
1199  // cha
1200  }
1201 
1202  if (!line) throw std::string("LATCH-data");
1203  }
1204 
1205  int hasSURF;
1206  if (!(line >> hasSURF)) throw std::string("hasSURF");
1207  if (hasSURF)
1208  {
1209  size_t N;
1210  if (!(line >> N)) throw std::string("SURF-len");
1211  feat->descriptors.SURF.resize(N);
1212  for (size_t i = 0; i < N; i++)
1213  line >> feat->descriptors.SURF[i];
1214  if (!line) throw std::string("SURF-data");
1215  }
1216 
1217  push_back(feat_ptr);
1218  }
1219  catch (std::string& msg)
1220  {
1222  format(
1223  "%s:%d: Error parsing features text file (%s).",
1224  filename.c_str(), (int)parser.getCurrentLineNumber(),
1225  msg.c_str()))
1226  }
1227  }
1228 
1229  MRPT_END
1230 } // end loadFromTextFile
1231 
1232 // --------------------------------------------------
1233 // copyListFrom()
1234 // --------------------------------------------------
1236 {
1237  this->resize(otherList.size());
1240  for (it1 = otherList.begin(), it2 = this->begin(); it1 != otherList.end();
1241  ++it1, ++it2)
1242  {
1243  *it2 = *it1;
1244  (*it2).reset(dynamic_cast<CFeature*>((*it2)->clone()));
1245  }
1246 } // end-copyListFrom
1247 
1248 // --------------------------------------------------
1249 // getByID()
1250 // --------------------------------------------------
1252 {
1253  for (CFeatureList::const_iterator it = begin(); it != end(); ++it)
1254  if ((*it)->ID == ID) return (*it);
1255 
1256  return CFeature::Ptr();
1257 } // end getByID
1258 
1259 // --------------------------------------------------
1260 // getByID()
1261 // --------------------------------------------------
1263 {
1264  int k = 0;
1265  for (CFeatureList::const_iterator it = begin(); it != end(); ++it, ++k)
1266  if ((*it)->ID == ID)
1267  {
1268  out_idx = k;
1269  return (*it);
1270  }
1271  out_idx = -1;
1272  return CFeature::Ptr();
1273 } // end getByID
1274 
1275 // --------------------------------------------------
1276 // getByID()
1277 // --------------------------------------------------
1279  const vector<TFeatureID>& IDs, vector<CFeature::Ptr>& out,
1280  vector<int>& outIndex) const
1281 {
1282  out.clear();
1283  outIndex.clear();
1284  out.reserve(IDs.size());
1285  outIndex.reserve(IDs.size());
1286 
1287  for (int k = 0; k < int(IDs.size()); ++k)
1288  {
1289  int idx;
1290  CFeature::Ptr f = getByID(IDs[k], idx);
1291  out.push_back(f);
1292  outIndex.push_back(idx);
1293  }
1294 } // end getByID
1295 
1296 // --------------------------------------------------
1297 // nearest(x,y)
1298 // --------------------------------------------------
1300  const float x, const float y, double& dist_prev) const
1301 {
1302  if (this->empty()) return CFeature::Ptr();
1303 
1304  float closest_x, closest_y;
1305  float closest_sqDist;
1306 
1307  // Look for the closest feature using KD-tree look up:
1308  const size_t closest_idx =
1309  this->kdTreeClosestPoint2D(x, y, closest_x, closest_y, closest_sqDist);
1310  float closest_dist = std::sqrt(closest_sqDist);
1311 
1312  if (closest_dist <= dist_prev)
1313  {
1314  dist_prev = closest_dist;
1315  return m_feats[closest_idx];
1316  }
1317  else
1318  return CFeature::Ptr();
1319 } // end nearest
1320 
1321 // --------------------------------------------------
1322 // getMaxID()
1323 // --------------------------------------------------
1325 {
1326  MRPT_START
1327  ASSERT_(!empty())
1328  vision::TFeatureID maxID = (*begin())->ID;
1329  for (CFeatureList::const_iterator itList = begin(); itList != end();
1330  itList++)
1331  mrpt::utils::keep_max(maxID, (*itList)->ID);
1332  return maxID;
1333  MRPT_END
1334 
1335 } // end getMaxID()
1336 
1337 /****************************************************
1338  Class CMATCHEDFEATUREKLT
1339 *****************************************************/
1340 // --------------------------------------------------
1341 // CONSTRUCTOR
1342 // --------------------------------------------------
1343 CMatchedFeatureList::CMatchedFeatureList() : m_leftMaxID(0), m_rightMaxID(0) {}
1344 // --------------------------------------------------
1345 // DESTRUCTOR
1346 // --------------------------------------------------
1348 // --------------------------------------------------
1349 // saveToTextFile
1350 // --------------------------------------------------
1352 {
1353  // OUTPUT FORMAT: ID_1 x_1 y_1 ID_2 x_2 y_2
1354 
1355  FILE* f = os::fopen(filename.c_str(), "wt");
1356  if (!f) return;
1357 
1359  for (it = this->begin(); it != this->end(); it++)
1360  {
1361  os::fprintf(
1362  f, "%d %.3f %.3f %d %.3f %.3f\n", (unsigned int)(*it->first).ID,
1363  (*it->first).x, (*it->first).y, (unsigned int)(*it->second).ID,
1364  (*it->second).x, (*it->second).y);
1365 
1366  } // end for
1367  os::fclose(f);
1368 }
1369 
1370 // --------------------------------------------------
1371 // getBothFeatureLists
1372 // --------------------------------------------------
1374  const TFeatureID& ID, const TListIdx& idx)
1375 {
1377  for (it = begin(); it != end(); ++it)
1378  {
1379  CFeature::Ptr feat = (idx == firstList) ? it->first : it->second;
1380  if (feat->ID == ID) return feat;
1381  }
1382  return CFeature::Ptr();
1383 }
1384 
1385 // --------------------------------------------------
1386 // updateMaxID()
1387 // --------------------------------------------------
1389 {
1390  MRPT_START
1391  TFeatureID maxID1 = begin()->first->ID;
1392  TFeatureID maxID2 = begin()->second->ID;
1393  for (CMatchedFeatureList::const_iterator itList = begin(); itList != end();
1394  itList++)
1395  {
1396  if (idx == firstList || idx == bothLists)
1397  mrpt::utils::keep_max(maxID1, itList->first->ID);
1398  if (idx == secondList || idx == bothLists)
1399  mrpt::utils::keep_max(maxID2, itList->second->ID);
1400  }
1401  if (idx == firstList || idx == bothLists) m_leftMaxID = maxID1;
1402  if (idx == secondList || idx == bothLists) m_rightMaxID = maxID2;
1403  MRPT_END
1404 }
1405 
1406 // --------------------------------------------------
1407 // getMaxID()
1408 // --------------------------------------------------
1410  const TListIdx& idx, TFeatureID& firstListID, TFeatureID& secondListID)
1411 {
1412  MRPT_START
1413  ASSERT_(!empty());
1414  if (idx == firstList || idx == bothLists)
1415  if (m_leftMaxID == 0) updateMaxID(firstList);
1416  if (idx == secondList || idx == bothLists)
1417  if (m_rightMaxID == 0) updateMaxID(secondList);
1418  firstListID = m_leftMaxID;
1419  secondListID = m_rightMaxID;
1420  MRPT_END
1421 } // end getMaxID()
1422 // --------------------------------------------------
1423 // getBothFeatureLists
1424 // --------------------------------------------------
1426  CFeatureList& list1, CFeatureList& list2)
1427 {
1428  MRPT_START
1429  list1.resize(this->size());
1430  list2.resize(this->size());
1431 
1432  unsigned int k = 0;
1433  for (CMatchedFeatureList::iterator it = this->begin(); it != this->end();
1434  ++it, ++k)
1435  {
1436  list1[k] = it->first;
1437  list2[k] = it->second;
1438  } // end for
1439  MRPT_END
1440 }
1441 
1442 // --------------------------------------------------
1443 // getFirstDescriptorAsMatrix
1444 // --------------------------------------------------
1446 {
1448  {
1449  desc.setSize(1, descriptors.SIFT.size());
1450  for (size_t i = 0; i < descriptors.SIFT.size(); i++)
1451  desc(0, i) = descriptors.SIFT[i];
1452  return true;
1453  }
1454  else if (descriptors.hasDescriptorBLD())
1455  {
1456  desc.setSize(1, descriptors.BLD.size());
1457  for (size_t i = 0; i < descriptors.BLD.size(); i++)
1458  desc(0, i) = descriptors.BLD[i];
1459  return true;
1460  }
1461  else if (descriptors.hasDescriptorLATCH())
1462  {
1463  desc.setSize(1, descriptors.LATCH.size());
1464  for (size_t i = 0; i < descriptors.LATCH.size(); i++)
1465  desc(0, i) = descriptors.LATCH[i];
1466  return true;
1467  }
1468  else if (descriptors.hasDescriptorSURF())
1469  {
1470  desc.setSize(1, descriptors.SURF.size());
1471  for (size_t i = 0; i < descriptors.SURF.size(); i++)
1472  desc(0, i) = descriptors.SURF[i];
1473  return true;
1474  }
1475  else if (descriptors.hasDescriptorSpinImg())
1476  {
1477  const size_t nR = descriptors.SpinImg_range_rows;
1478  const size_t nC =
1480  desc.resize(nR, nC);
1482  for (size_t r = 0; r < nR; r++)
1483  for (size_t c = 0; c < nC; c++) desc.coeffRef(r, c) = *itD++;
1484  return true;
1485  }
1487  {
1488  desc = descriptors.PolarImg;
1489  return true;
1490  }
1492  {
1493  desc = descriptors.LogPolarImg;
1494  return true;
1495  }
1496  else
1497  return false;
1498 }
void updateMaxID(const TListIdx &idx)
Updates the value of the maximum ID of the features in the matched list, i.e.
Definition: CFeature.cpp:1388
float descriptorDistanceTo(const CFeature &oFeature, TDescriptorType descriptorToUse=descAny, bool normalize_distances=true) const
Computes the Euclidean Distance between this feature&#39;s and other feature&#39;s descriptors, using the given descriptor or the first present one.
Definition: CFeature.cpp:515
std::shared_ptr< CFeature > Ptr
Definition: CFeature.h:58
GLuint GLuint GLsizei count
Definition: glext.h:3528
Non-defined feature (also used for Occupancy features)
TFeatureID ID
ID of the feature.
Definition: CFeature.h:62
EIGEN_STRONG_INLINE bool empty() const
bool read_bool(const std::string &section, const std::string &name, bool defaultValue, bool failIfNotFound=false) const
void loadFromConfigFile(const mrpt::utils::CConfigFileBase &source, const std::string &section) override
Load all the params from a config source, in the format described in saveToConfigFile() ...
Definition: CFeature.cpp:144
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
uint8_t descriptorORBDistanceTo(const CFeature &oFeature) const
Computes the Hamming distance "this" and the "other" descriptor ORB descriptor.
Definition: CFeature.cpp:841
float descriptorSpinImgDistanceTo(const CFeature &oFeature, bool normalize_distances=true) const
Computes the Euclidean Distance between "this" and the "other" descriptors.
Definition: CFeature.cpp:637
bool hasDescriptorBLD() const
Whether this feature has this kind of descriptor.
Definition: CFeature.h:170
Used in some methods to mean "any of the present descriptors".
void saveToConfigFile(mrpt::utils::CConfigFileBase &cfg, const std::string &section) const override
This method saves the options to a ".ini"-like file or memory-stored string list. ...
Definition: CFeature.cpp:179
std::vector< uint8_t > BLD
BLD feature descriptor.
Definition: CFeature.h:135
void loadFromTextFile(const std::string &fileName)
Save feature list to a text file.
Definition: CFeature.cpp:1113
This namespace provides a OS-independent interface to many useful functions: filenames manipulation...
Definition: math_frwds.h:30
Create a GUI window and display plots with MATLAB-like interfaces and commands.
The virtual base class which provides a unified interface for all persistent objects in MRPT...
Definition: CSerializable.h:44
int void fclose(FILE *f)
An OS-independent version of fclose.
Definition: os.cpp:272
A class for storing images as grayscale or RGB bitmaps.
Definition: CImage.h:118
#define IMPLEMENTS_SERIALIZABLE(class_name, base, NameSpace)
This must be inserted in all CSerializable classes implementation files.
int waitForKey(bool ignoreControlKeys=true, mrptKeyModifier *out_pushModifier=nullptr)
Waits for any key to be pushed on the image or the console, and returns the key code.
bool hasDescriptorLogPolarImg() const
Whether this feature has this kind of descriptor.
Definition: CFeature.h:154
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:6502
TFeatureTrackStatus track_status
featKLT, featHarris, featSURF, featBeacon
Definition: CFeature.h:69
size_t size() const
Definition: CFeature.h:387
void dumpToConsole() const
Definition: CFeature.cpp:381
#define THROW_EXCEPTION(msg)
float descriptorSIFTDistanceTo(const CFeature &oFeature, bool normalize_distances=true) const
Computes the Euclidean Distance between "this" and the "other" descriptors.
Definition: CFeature.cpp:585
#define THROW_EXCEPTION_FMT(_FORMAT_STRING,...)
GLenum GLsizei n
Definition: glext.h:5074
Scalar * iterator
Definition: eigen_plugins.h:26
float descriptorSURFDistanceTo(const CFeature &oFeature, bool normalize_distances=true) const
Computes the Euclidean Distance between "this" and the "other" descriptors.
Definition: CFeature.cpp:610
This CStdOutStream derived class allow printing to standard out, normally the console text output...
Definition: CStdOutStream.h:26
void dumpToTextStream(mrpt::utils::CStream &out) const override
This method should clearly display all the contents of the structure in textual form, sending it to a CStream.
Definition: CFeature.cpp:207
void getByMultiIDs(const std::vector< TFeatureID > &IDs, std::vector< CFeature::Ptr > &out, std::vector< int > &outIndex) const
Get a vector of references to a subset of features from their IDs.
Definition: CFeature.cpp:1278
EIGEN_STRONG_INLINE iterator begin()
Definition: eigen_plugins.h:29
Column vector, like Eigen::MatrixX*, but automatically initialized to zeros since construction...
Definition: eigen_frwds.h:42
EIGEN_STRONG_INLINE void push_back(Scalar val)
Insert an element at the end of the container (for 1D vectors/arrays)
std::vector< float > SURF
SURF feature descriptor.
Definition: CFeature.h:113
std::deque< double > multiScales
A set of scales where the.
Definition: CFeature.h:93
for(ctr=DCTSIZE;ctr > 0;ctr--)
Definition: jidctflt.cpp:56
TInternalFeatList::const_iterator const_iterator
Definition: CFeature.h:367
GLint GLint GLsizei GLsizei GLsizei depth
Definition: glext.h:3600
STL namespace.
void cross_correlation(const CImage &patch_img, size_t &u_max, size_t &v_max, double &max_val, int u_search_ini=-1, int v_search_ini=-1, int u_search_size=-1, int v_search_size=-1, CImage *out_corr_image=nullptr) const
Computes the correlation between this image and another one, encapsulating the openCV function cvMatc...
Definition: CImage.cpp:1462
const Scalar * const_iterator
Definition: eigen_plugins.h:27
void saveToConfigFile(mrpt::utils::CConfigFileBase &cfg, const std::string &section) const override
This method saves the options to a ".ini"-like file or memory-stored string list. ...
Definition: CFeature.cpp:68
TFeatureType get_type() const
Get the type of the feature.
Definition: CFeature.h:277
mrpt::math::CMatrix LogPolarImg
A log-polar image centered at the interest point.
Definition: CFeature.h:122
bool hasDescriptorMultiSIFT() const
Whether this feature has this kind of descriptor.
Definition: CFeature.h:158
void dumpToTextStream(mrpt::utils::CStream &out) const override
This method should clearly display all the contents of the structure in textual form, sending it to a CStream.
Definition: CFeature.cpp:101
GLenum GLsizei width
Definition: glext.h:3531
void image(const utils::CImage &img, const float &x_left, const float &y_bottom, const float &x_width, const float &y_height, const std::string &plotName=std::string("image"))
Adds a bitmap image layer.
#define M_2PI
Definition: mrpt_macros.h:437
This class allows loading and storing values and vectors of different types from a configuration text...
T square(const T x)
Inline function for the square of a number.
Definition: bits.h:55
unsigned char uint8_t
Definition: rptypes.h:41
Inactive (right after detection, and before being tried to track)
int read_int(const std::string &section, const std::string &name, int defaultValue, bool failIfNotFound=false) const
This base class is used to provide a unified interface to files,memory buffers,..Please see the deriv...
Definition: CStream.h:41
bool polarImgsNoRotation
If set to true (manually, default=false)
Definition: CFeature.h:123
void getBothFeatureLists(CFeatureList &list1, CFeatureList &list2)
Returns the matching features as two separate CFeatureLists.
Definition: CFeature.cpp:1425
void saveToTextFile(const std::string &filename, bool APPEND=false)
Save the feature to a text file in this format: "%% Dump of mrpt::vision::CFeatureList. Each line format is:\n" "%% ID TYPE X Y ORIENTATION SCALE TRACK_STATUS RESPONSE HAS_SIFT [SIFT] HAS_SURF [SURF] HAS_MULTI [MULTI_i] HAS_ORB [ORB]" "%% |---------------------- feature ------------------| |---------------------- descriptors ------------------------|" "%% with:\n" "%% TYPE : The used detector: 0:KLT, 1: Harris, 2: BCD, 3: SIFT, 4: SURF, 5: Beacon, 6: FAST, 7: ORB\n" "%% HAS_* : 1 if a descriptor of that type is associated to the feature.
Definition: CFeature.cpp:922
This base provides a set of functions for maths stuff.
Definition: CArrayNumeric.h:19
size_t getWidth() const override
Returns the width of the image in pixels.
Definition: CImage.cpp:869
void resize(size_t N)
Definition: CFeature.h:393
#define MRPT_END
void writeToStream(mrpt::utils::CStream &out, int *getVersion) const override
Introduces a pure virtual method responsible for writing to a CStream.
Definition: CFeature.cpp:387
This CStream derived class allow using a file as a write-only, binary stream.
void getMaxID(const TListIdx &idx, TFeatureID &firstListID, TFeatureID &secondListID)
Returns the maximum ID of the features in the list.
Definition: CFeature.cpp:1409
static float internal_distanceBetweenPolarImages(const mrpt::math::CMatrix &desc1, const mrpt::math::CMatrix &desc2, float &minDistAngle, bool normalize_distances, bool dont_shift_angle)
Internal function used by "descriptorLogPolarImgDistanceTo" and "descriptorPolarImgDistanceTo".
Definition: CFeature.cpp:665
const GLubyte * c
Definition: glext.h:6313
#define MRPT_THROW_UNKNOWN_SERIALIZATION_VERSION(__V)
For use in CSerializable implementations.
Scale Invariant Feature Transform [LOWE&#39;04].
void read_vector(const std::string &section, const std::string &name, const VECTOR_TYPE &defaultValue, VECTOR_TYPE &outValues, bool failIfNotFound=false) const
Reads a configuration parameter of type vector, stored in the file as a string: "[v1 v2 v3 ...
GLuint GLuint end
Definition: glext.h:3528
std::vector< uint8_t > SIFT
SIFT feature descriptor.
Definition: CFeature.h:112
size_t getHeight() const override
Returns the height of the image in pixels.
Definition: CImage.cpp:897
int val
Definition: mrpt_jpeglib.h:955
std::string format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
Definition: format.cpp:19
std::deque< std::vector< double > > multiOrientations
multi-resolution descriptor has been computed
Definition: CFeature.h:96
void readFromStream(mrpt::utils::CStream &in, int version) override
Introduces a pure virtual method responsible for loading from a CStream This can not be used directly...
Definition: CFeature.cpp:408
CFeature()
Constructor.
Definition: CFeature.cpp:447
Classes for computer vision, detectors, features, etc.
uint16_t SpinImg_range_rows
The number of rows (corresponding to.
Definition: CFeature.h:115
A generic 2D feature from an image, extracted with CFeatureExtraction Each feature may have one or mo...
Definition: CFeature.h:53
float descriptorLATCHDistanceTo(const CFeature &oFeature, bool normalize_distances=true) const
Computes the Euclidean Distance between "this" and the "other" descriptors.
Definition: CFeature.cpp:896
A class for parsing text files, returning each non-empty and non-comment line, along its line number...
void plot(const std::vector< T1 > &x, const std::vector< T2 > &y, const std::string &lineFormat=std::string("b-"), const std::string &plotName=std::string("plotXY"))
Adds a new layer with a 2D plot based on two vectors of X and Y points, using a MATLAB-like syntax...
uint64_t TFeatureID
Definition of a feature ID.
Bit-based feature descriptor.
bool hasDescriptorORB() const
Whether this feature has this kind of descriptor.
Definition: CFeature.h:165
void saveToTextFile(const std::string &fileName)
Save list of matched features to a text file.
Definition: CFeature.cpp:1351
GLsizei const GLchar ** string
Definition: glext.h:4101
A list of visual features, to be used as output by detectors, as input/output by trackers, etc.
Definition: CFeature.h:305
TDescriptorType
The bitwise OR combination of values of TDescriptorType are used in CFeatureExtraction::computeDescri...
void dumpToTextStream(mrpt::utils::CStream &out) const
Dump feature information into a text stream.
Definition: CFeature.cpp:247
int fprintf(FILE *fil, const char *format,...) noexcept MRPT_printf_format_check(2
An OS-independent version of fprintf.
Definition: os.cpp:405
CFeature::Ptr getByID(const TFeatureID &ID, const TListIdx &idx)
Returns a smart pointer to the feature with the provided ID or a empty one if not found...
Definition: CFeature.cpp:1373
TFeatureType
Types of features - This means that the point has been detected with this algorithm, which is independent of additional descriptors a feature may also have.
bool hasDescriptorLATCH() const
Whether this feature has this kind of descriptor.
Definition: CFeature.h:174
CFeature::Ptr nearest(const float x, const float y, double &max_dist) const
Get a reference to the nearest feature to the a given 2D point (version returning distance to closest...
Definition: CFeature.cpp:1299
struct mrpt::vision::CFeature::TDescriptors descriptors
void saveToTextFile(const std::string &fileName, bool APPEND=false)
Save feature list to a text file.
Definition: CFeature.cpp:1035
float response
process (old name: KLT_status)
Definition: CFeature.h:71
#define MRPT_START
bool getFirstDescriptorAsMatrix(mrpt::math::CMatrixFloat &desc) const
Return the first found descriptor, as a matrix.
Definition: CFeature.cpp:1445
virtual ~CFeatureList()
Virtual destructor.
Definition: CFeature.cpp:1029
#define RAD2DEG
CFeatureList()
Constructor.
Definition: CFeature.cpp:1025
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void write(const std::string &section, const std::string &name, enum_t value, const int name_padding_width=-1, const int value_padding_width=-1, const std::string &comment=std::string())
GLdouble GLdouble GLdouble r
Definition: glext.h:3705
void meanAndStd(const VECTORLIKE &v, double &out_mean, double &out_std, bool unbiased=true)
Computes the standard deviation of a vector.
std::vector< float > SpinImg
The 2D histogram as a single row.
Definition: CFeature.h:114
Speeded Up Robust Feature [BAY&#39;06].
double read_double(const std::string &section, const std::string &name, double defaultValue, bool failIfNotFound=false) const
float descriptorPolarImgDistanceTo(const CFeature &oFeature, float &minDistAngle, bool normalize_distances=true) const
Returns the minimum Euclidean Distance between "this" and the "other" polar image descriptor...
Definition: CFeature.cpp:784
std::vector< uint8_t > LATCH
LATCH feature descriptor.
Definition: CFeature.h:136
GLuint in
Definition: glext.h:7274
float patchCorrelationTo(const CFeature &oFeature) const
Computes the normalized cross-correlation between the patches of this and another feature (normalized...
Definition: CFeature.cpp:495
#define ASSERT_(f)
virtual ~CMatchedFeatureList()
Virtual destructor.
Definition: CFeature.cpp:1347
TFeatureID getMaxID() const
Get the maximum ID into the list.
Definition: CFeature.cpp:1324
Struct containing the options when matching multi-resolution SIFT-like descriptors.
TInternalFeatList::iterator iterator
Definition: CFeature.h:366
GLenum GLint GLint y
Definition: glext.h:3538
Intensity-domain spin image descriptors.
FILE * fopen(const char *fileName, const char *mode) noexcept
An OS-independent version of fopen.
Definition: os.cpp:254
typedef void(APIENTRYP PFNGLBLENDCOLORPROC)(GLclampf red
mrpt::utils::CImage patch
A patch of the image surrounding the feature.
Definition: CFeature.h:64
bool hasDescriptorPolarImg() const
Whether this feature has this kind of descriptor.
Definition: CFeature.h:150
GLsizeiptr size
Definition: glext.h:3923
float orientation
KLT_val)
Definition: CFeature.h:73
GLenum GLint x
Definition: glext.h:3538
float descriptorLogPolarImgDistanceTo(const CFeature &oFeature, float &minDistAngle, bool normalize_distances=true) const
Returns the minimum Euclidean Distance between "this" and the "other" log-polar image descriptor...
Definition: CFeature.cpp:811
This class is a "CSerializable" wrapper for "CMatrixFloat".
Definition: CMatrix.h:25
GLenum GLsizei GLsizei height
Definition: glext.h:3554
unsigned __int32 uint32_t
Definition: rptypes.h:47
float descriptorBLDDistanceTo(const CFeature &oFeature, bool normalize_distances=true) const
Computes the Euclidean Distance between "this" and the "other" descriptors.
Definition: CFeature.cpp:871
GLuint GLuint GLsizei GLenum type
Definition: glext.h:3528
std::deque< std::vector< std::vector< int32_t > > > multiSIFTDescriptors
the call to "descriptorDistanceTo" will not consider all the rotations between polar image descriptor...
Definition: CFeature.h:129
void keep_max(T &var, const K test_val)
If the second argument is above the first one, set the first argument to this higher value...
CFeature::Ptr getByID(const TFeatureID &ID) const
Get a reference to a Feature from its ID.
Definition: CFeature.cpp:1251
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
Definition: geometry.cpp:1885
virtual int printf(const char *fmt,...) MRPT_printf_format_check(2
Writes a string to the stream in a textual form.
Definition: CStream.cpp:597
int sprintf(char *buf, size_t bufSize, const char *format,...) noexcept MRPT_printf_format_check(3
An OS-independent version of sprintf (Notice the bufSize param, which may be ignored in some compiler...
Definition: os.cpp:188
mrpt::math::CMatrix PolarImg
range bins in the 2D histogram) of the original matrix from which SpinImg was extracted as a vector...
Definition: CFeature.h:120
void copyListFrom(const CFeatureList &otherList)
Copies the content of another CFeatureList inside this one.
Definition: CFeature.cpp:1235
bool isPointFeature() const
a HASH table of descriptors
Definition: CFeature.cpp:487
bool hasDescriptorSURF() const
Whether this feature has this kind of descriptor.
Definition: CFeature.h:142
std::vector< uint8_t > ORB
orientation and scale of the multiResolution feature (there is a vector of descriptors for each scale...
Definition: CFeature.h:133



Page generated by Doxygen 1.8.14 for MRPT 1.9.9 Git: ae4571287 Thu Nov 23 00:06:53 2017 +0100 at dom oct 27 23:51:55 CET 2019