Visual Servoing Platform  version 3.3.0 under development (2020-02-17)
vpXmlConfigParserKeyPoint.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * XML parser to load configuration for vpKeyPoint class.
33  *
34  * Authors:
35  * Souriya Trinh
36  *
37  *****************************************************************************/
38 
46 #include <iostream>
47 
48 #include <visp3/vision/vpXmlConfigParserKeyPoint.h>
49 
50 #ifdef VISP_HAVE_PUGIXML
51 
52 #include <map>
53 #include <pugixml.hpp>
54 
55 #include <visp3/core/vpException.h>
56 
57 #ifndef DOXYGEN_SHOULD_SKIP_THIS
58 class vpXmlConfigParserKeyPoint::Impl
59 {
60 public:
61  Impl() :
62  m_detectorName("ORB"), m_extractorName("ORB"), m_matcherName("BruteForce-Hamming"), m_matchingFactorThreshold(2.0),
63  m_matchingMethod(ratioDistanceThreshold), m_matchingRatioThreshold(0.85), m_nbRansacIterations(200),
64  m_nbRansacMinInlierCount(100), m_ransacConsensusPercentage(20.0), m_ransacReprojectionError(6.0),
65  m_ransacThreshold(0.01), m_useRansacConsensusPercentage(false), m_useRansacVVS(true)
66  {
67  init();
68  }
69 
73  void init()
74  {
75  m_nodeMap["conf"] = conf;
76  m_nodeMap["detector"] = detector;
77  m_nodeMap["extractor"] = extractor;
78  m_nodeMap["matcher"] = matcher;
79  m_nodeMap["name"] = name;
80  m_nodeMap["matching_method"] = matching_method;
81  m_nodeMap["constantFactorDistanceThreshold"] = constant_factor_distance_threshold;
82  m_nodeMap["stdDistanceThreshold"] = std_distance_threshold;
83  m_nodeMap["ratioDistanceThreshold"] = ratio_distance_threshold;
84  m_nodeMap["stdAndRatioDistanceThreshold"] = std_and_ratio_distance_threshold;
85  m_nodeMap["noFilterMatching"] = no_filter_matching;
86  m_nodeMap["matchingFactorThreshold"] = matching_factor_threshold;
87  m_nodeMap["matchingRatioThreshold"] = matching_ratio_threshold;
88  m_nodeMap["ransac"] = ransac;
89  m_nodeMap["useRansacVVS"] = use_ransac_vvs;
90  m_nodeMap["useRansacConsensusPercentage"] = use_ransac_consensus_percentage;
91  m_nodeMap["nbRansacIterations"] = nb_ransac_iterations;
92  m_nodeMap["ransacReprojectionError"] = ransac_reprojection_error;
93  m_nodeMap["nbRansacMinInlierCount"] = nb_ransac_min_inlier_count;
94  m_nodeMap["ransacThreshold"] = ransac_threshold;
95  m_nodeMap["ransacConsensusPercentage"] = ransac_consensus_percentage;
96  }
97 
98  void parse(const std::string &filename)
99  {
100  pugi::xml_document doc;
101  if (!doc.load_file(filename.c_str())) {
102  throw vpException(vpException::ioError, "Cannot open file: %s", filename.c_str());
103  }
104 
105  bool detector_node = false;
106  bool extractor_node = false;
107  bool matcher_node = false;
108 
109  pugi::xml_node root_node = doc.document_element();
110  for (pugi::xml_node dataNode = root_node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
111  if (dataNode.type() == pugi::node_element) {
112  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
113  if (iter_data != m_nodeMap.end()) {
114  switch (iter_data->second) {
115  case detector:
116  read_detector(dataNode);
117  detector_node = true;
118  break;
119 
120  case extractor:
121  read_extractor(dataNode);
122  extractor_node = true;
123  break;
124 
125  case matcher:
126  read_matcher(dataNode);
127  matcher_node = true;
128  break;
129 
130  case ransac:
131  read_ransac(dataNode);
132  break;
133 
134  default:
135  break;
136  }
137  }
138  }
139  }
140 
141  if (!detector_node) {
142  std::cout << "detector: name: " << m_detectorName << " (default)" << std::endl;
143  }
144 
145  if (!extractor_node) {
146  std::cout << "extractor: name: " << m_extractorName << " (default)" << std::endl;
147  }
148 
149  if (!matcher_node) {
150  std::cout << "matcher: name: " << m_matcherName << " (default)" << std::endl;
151  }
152  }
153 
159  void read_detector(const pugi::xml_node &node)
160  {
161  bool detector_name_node = false;
162 
163  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
164  if (dataNode.type() == pugi::node_element) {
165  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
166  if (iter_data != m_nodeMap.end()) {
167  switch (iter_data->second) {
168  case name:
169  m_detectorName = dataNode.text().as_string();
170  detector_name_node = true;
171  break;
172 
173  default:
174  break;
175  }
176  }
177  }
178  }
179 
180  if (!detector_name_node)
181  std::cout << "detector : Name : " << m_detectorName << " (default)" << std::endl;
182  else
183  std::cout << "detector : Name : " << m_detectorName << std::endl;
184  }
185 
191  void read_extractor(const pugi::xml_node &node)
192  {
193  bool extractor_name_node = false;
194 
195  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
196  if (dataNode.type() == pugi::node_element) {
197  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
198  if (iter_data != m_nodeMap.end()) {
199  switch (iter_data->second) {
200  case name:
201  m_extractorName = dataNode.text().as_string();
202  extractor_name_node = true;
203  break;
204 
205  default:
206  break;
207  }
208  }
209  }
210  }
211 
212  if (!extractor_name_node)
213  std::cout << "extractor : Name : " << m_extractorName << " (default)" << std::endl;
214  else
215  std::cout << "extractor : Name : " << m_extractorName << std::endl;
216  }
217 
223  void read_matcher(const pugi::xml_node &node)
224  {
225  bool matcher_name_node = false;
226  bool matching_method_node = false;
227  std::string matchingMethodName = "ratioDistanceThreshold";
228  bool matching_factor_threshold_node = false;
229  bool matching_ratio_threshold_node = false;
230 
231  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
232  if (dataNode.type() == pugi::node_element) {
233  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
234  if (iter_data != m_nodeMap.end()) {
235  switch (iter_data->second) {
236  case name:
237  m_matcherName = dataNode.text().as_string();
238  matcher_name_node = true;
239  break;
240 
241  case matching_method: {
242  matchingMethodName = dataNode.text().as_string();
243 
244  std::map<std::string, int>::iterator iter_data2 = m_nodeMap.find(matchingMethodName);
245  if (iter_data2 != m_nodeMap.end()) {
246  matching_method_node = true;
247  switch (iter_data2->second) {
248  case constant_factor_distance_threshold:
249  m_matchingMethod = constantFactorDistanceThreshold;
250  break;
251 
252  case std_distance_threshold:
253  m_matchingMethod = stdDistanceThreshold;
254  break;
255 
256  case ratio_distance_threshold:
257  m_matchingMethod = ratioDistanceThreshold;
258  break;
259 
260  case std_and_ratio_distance_threshold:
261  m_matchingMethod = stdAndRatioDistanceThreshold;
262  break;
263 
264  case no_filter_matching:
265  m_matchingMethod = noFilterMatching;
266  break;
267 
268  default:
269  matching_method_node = false;
270  break;
271  }
272  }
273  break;
274  }
275 
276  case matching_factor_threshold:
277  m_matchingFactorThreshold = dataNode.text().as_double();
278  matching_factor_threshold_node = true;
279  break;
280 
281  case matching_ratio_threshold:
282  m_matchingRatioThreshold = dataNode.text().as_double();
283  matching_ratio_threshold_node = true;
284  break;
285 
286  default:
287  break;
288  }
289  }
290  }
291  }
292 
293  if (!matcher_name_node)
294  std::cout << "matcher : Name : " << m_matcherName << " (default)" << std::endl;
295  else
296  std::cout << "matcher : Name : " << m_matcherName << std::endl;
297 
298  if (!matching_method_node)
299  std::cout << "matcher : Filter method : " << matchingMethodName << " (default)" << std::endl;
300  else
301  std::cout << "matcher : Filter method : " << matchingMethodName << std::endl;
302 
303  if (!matching_factor_threshold_node)
304  std::cout << "matcher : matching factor threshold : " << m_matchingFactorThreshold << " (default)" << std::endl;
305  else
306  std::cout << "matcher : matching factor threshold : " << m_matchingFactorThreshold << std::endl;
307 
308  if (!matching_ratio_threshold_node)
309  std::cout << "matcher : matching ratio threshold : " << m_matchingRatioThreshold << " (default)" << std::endl;
310  else
311  std::cout << "matcher : matching ratio threshold : " << m_matchingRatioThreshold << std::endl;
312  }
313 
319  void read_ransac(const pugi::xml_node &node)
320  {
321  bool use_ransac_vvs_node = false;
322  bool use_ransac_consensus_percentage_node = false;
323  bool nb_ransac_iterations_node = false;
324  bool ransac_reprojection_error_node = false;
325  bool nb_ransac_min_inlier_count_node = false;
326  bool ransac_threshold_node = false;
327  bool ransac_consensus_percentage_node = false;
328 
329  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
330  if (dataNode.type() == pugi::node_element) {
331  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
332  if (iter_data != m_nodeMap.end()) {
333  switch (iter_data->second) {
334  case use_ransac_vvs:
335  m_useRansacVVS = dataNode.text().as_int() != 0;
336  use_ransac_vvs_node = true;
337  break;
338 
339  case use_ransac_consensus_percentage:
340  m_useRansacConsensusPercentage = dataNode.text().as_int() != 0;
341  use_ransac_consensus_percentage_node = true;
342  break;
343 
344  case nb_ransac_iterations:
345  m_nbRansacIterations = dataNode.text().as_int();
346  nb_ransac_iterations_node = true;
347  break;
348 
349  case ransac_reprojection_error:
350  m_ransacReprojectionError = dataNode.text().as_double();
351  ransac_reprojection_error_node = true;
352  break;
353 
354  case nb_ransac_min_inlier_count:
355  m_nbRansacMinInlierCount = dataNode.text().as_int();
356  nb_ransac_min_inlier_count_node = true;
357  break;
358 
359  case ransac_threshold:
360  m_ransacThreshold = dataNode.text().as_double();
361  ransac_threshold_node = true;
362  break;
363 
364  case ransac_consensus_percentage:
365  m_ransacConsensusPercentage = dataNode.text().as_double();
366  ransac_consensus_percentage_node = true;
367  break;
368 
369  default:
370  break;
371  }
372  }
373  }
374  }
375 
376  if (!use_ransac_vvs_node)
377  std::cout << "ransac: use ransac vvs pose estimation: " << m_useRansacVVS << " (default)" << std::endl;
378  else
379  std::cout << "ransac: use ransac vvs pose estimation: " << m_useRansacVVS << std::endl;
380 
381  if (!use_ransac_consensus_percentage_node)
382  std::cout << "ransac: use consensus percentage: " << m_useRansacConsensusPercentage << " (default)" << std::endl;
383  else
384  std::cout << "ransac: use consensus percentage: " << m_useRansacConsensusPercentage << std::endl;
385 
386  if (!nb_ransac_iterations_node)
387  std::cout << "ransac: nb ransac iterations: " << m_nbRansacIterations << " (default)" << std::endl;
388  else
389  std::cout << "ransac: nb ransac iterations: " << m_nbRansacIterations << std::endl;
390 
391  if (!ransac_reprojection_error_node)
392  std::cout << "ransac: ransac reprojection error in pixel (for OpenCV "
393  "function): "
394  << m_ransacReprojectionError << " (default)" << std::endl;
395  else
396  std::cout << "ransac: ransac reprojection error in pixel (for OpenCV "
397  "function): "
398  << m_ransacReprojectionError << std::endl;
399 
400  if (!nb_ransac_min_inlier_count_node)
401  std::cout << "ransac: nb ransac min inlier count: " << m_nbRansacMinInlierCount << " (default)" << std::endl;
402  else
403  std::cout << "ransac: nb ransac min inlier count: " << m_nbRansacMinInlierCount << std::endl;
404 
405  if (!ransac_threshold_node)
406  std::cout << "ransac: ransac threshold in meter (for ViSP function): " << m_ransacThreshold << " (default)"
407  << std::endl;
408  else
409  std::cout << "ransac: ransac threshold in meter (for ViSP function): " << m_ransacThreshold << std::endl;
410 
411  if (!ransac_consensus_percentage_node)
412  std::cout << "ransac: consensus percentage: " << m_ransacConsensusPercentage << " (default)" << std::endl;
413  else
414  std::cout << "ransac: consensus percentage: " << m_ransacConsensusPercentage << std::endl;
415  }
416 
417  std::string getDetectorName() const { return m_detectorName; }
418  std::string getExtractorName() const { return m_extractorName; }
419  std::string getMatcherName() const { return m_matcherName; }
420 
421  double getMatchingFactorThreshold() const { return m_matchingFactorThreshold; }
422  vpMatchingMethodEnum getMatchingMethod() const { return m_matchingMethod; }
423  double getMatchingRatioThreshold() const { return m_matchingRatioThreshold; }
424 
425  int getNbRansacIterations() const { return m_nbRansacIterations; }
426  int getNbRansacMinInlierCount() const { return m_nbRansacMinInlierCount; }
427  double getRansacConsensusPercentage() const { return m_ransacConsensusPercentage; }
428  double getRansacReprojectionError() const { return m_ransacReprojectionError; }
429  double getRansacThreshold() const { return m_ransacThreshold; }
430  bool getUseRansacConsensusPercentage() const { return m_useRansacConsensusPercentage; }
431  bool getUseRansacVVSPoseEstimation() const { return m_useRansacVVS; }
432 
433 protected:
435  enum vpNodeIdentifier {
436  conf,
437  detector,
438  extractor,
439  matcher,
440  name,
441  matching_method,
442  constant_factor_distance_threshold,
445  std_distance_threshold,
447  ratio_distance_threshold,
449  std_and_ratio_distance_threshold,
452  no_filter_matching,
454  matching_factor_threshold,
456  matching_ratio_threshold,
458  ransac,
459  use_ransac_vvs,
460  use_ransac_consensus_percentage,
463  nb_ransac_iterations,
465  ransac_reprojection_error,
467  nb_ransac_min_inlier_count,
469  ransac_threshold,
471  ransac_consensus_percentage
473  };
474 
476  std::string m_detectorName;
478  std::string m_extractorName;
480  std::string m_matcherName;
482  double m_matchingFactorThreshold;
484  vpMatchingMethodEnum m_matchingMethod;
486  double m_matchingRatioThreshold;
488  int m_nbRansacIterations;
490  int m_nbRansacMinInlierCount;
492  double m_ransacConsensusPercentage;
495  double m_ransacReprojectionError;
498  double m_ransacThreshold;
501  // it is based on a fixed number.
502  bool m_useRansacConsensusPercentage;
505  bool m_useRansacVVS;
506  std::map<std::string, int> m_nodeMap;
507 };
508 #endif // DOXYGEN_SHOULD_SKIP_THIS
509 
511 {
512 }
513 
515 {
516  delete m_impl;
517 }
518 
523 void vpXmlConfigParserKeyPoint::parse(const std::string &filename)
524 {
525  m_impl->parse(filename);
526 }
527 
534 {
535  return m_impl->getDetectorName();
536 }
537 
544 {
545  return m_impl->getExtractorName();
546 }
547 
554 {
555  return m_impl->getMatcherName();
556 }
557 
565 {
566  return m_impl->getMatchingFactorThreshold();
567 }
568 
575 {
576  return m_impl->getMatchingMethod();
577 }
578 
585 {
586  return m_impl->getMatchingRatioThreshold();
587 }
588 
595 {
596  return m_impl->getNbRansacIterations();
597 }
598 
605 {
606  return m_impl->getNbRansacMinInlierCount();
607 }
608 
615 {
616  return m_impl->getRansacConsensusPercentage();
617 }
618 
626 {
627  return m_impl->getRansacReprojectionError();
628 }
629 
636 {
637  return m_impl->getRansacThreshold();
638 }
639 
647 {
648  return m_impl->getUseRansacConsensusPercentage();
649 }
650 
658 {
659  return m_impl->getUseRansacVVSPoseEstimation();
660 }
661 
662 #elif !defined(VISP_BUILD_SHARED_LIBS)
663 // Work arround to avoid warning:
664 // libvisp_vision.a(vpXmlConfigParserKeyPoint.cpp.o) has no symbols
665 void dummy_vpXmlConfigParserKeyPoint(){};
666 #endif //VISP_HAVE_PUGIXML
vpMatchingMethodEnum getMatchingMethod() const
error that can be emited by ViSP classes.
Definition: vpException.h:71
void parse(const std::string &filename)