Visual Servoing Platform  version 3.5.1 under development (2022-08-18)
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 #include <map>
51 #include <pugixml.hpp>
52 
53 #include <visp3/core/vpException.h>
54 
55 #ifndef DOXYGEN_SHOULD_SKIP_THIS
56 class vpXmlConfigParserKeyPoint::Impl
57 {
58 public:
59  Impl()
60  : m_detectorName("ORB"), m_extractorName("ORB"), m_matcherName("BruteForce-Hamming"),
61  m_matchingFactorThreshold(2.0), m_matchingMethod(ratioDistanceThreshold), m_matchingRatioThreshold(0.85),
62  m_nbRansacIterations(200), m_nbRansacMinInlierCount(100), m_ransacConsensusPercentage(20.0),
63  m_ransacReprojectionError(6.0), m_ransacThreshold(0.01), m_useRansacConsensusPercentage(false),
64  m_useRansacVVS(true)
65  {
66  init();
67  }
68 
72  void init()
73  {
74  m_nodeMap["conf"] = conf;
75  m_nodeMap["detector"] = detector;
76  m_nodeMap["extractor"] = extractor;
77  m_nodeMap["matcher"] = matcher;
78  m_nodeMap["name"] = name;
79  m_nodeMap["matching_method"] = matching_method;
80  m_nodeMap["constantFactorDistanceThreshold"] = constant_factor_distance_threshold;
81  m_nodeMap["stdDistanceThreshold"] = std_distance_threshold;
82  m_nodeMap["ratioDistanceThreshold"] = ratio_distance_threshold;
83  m_nodeMap["stdAndRatioDistanceThreshold"] = std_and_ratio_distance_threshold;
84  m_nodeMap["noFilterMatching"] = no_filter_matching;
85  m_nodeMap["matchingFactorThreshold"] = matching_factor_threshold;
86  m_nodeMap["matchingRatioThreshold"] = matching_ratio_threshold;
87  m_nodeMap["ransac"] = ransac;
88  m_nodeMap["useRansacVVS"] = use_ransac_vvs;
89  m_nodeMap["useRansacConsensusPercentage"] = use_ransac_consensus_percentage;
90  m_nodeMap["nbRansacIterations"] = nb_ransac_iterations;
91  m_nodeMap["ransacReprojectionError"] = ransac_reprojection_error;
92  m_nodeMap["nbRansacMinInlierCount"] = nb_ransac_min_inlier_count;
93  m_nodeMap["ransacThreshold"] = ransac_threshold;
94  m_nodeMap["ransacConsensusPercentage"] = ransac_consensus_percentage;
95  }
96 
97  void parse(const std::string &filename)
98  {
99  pugi::xml_document doc;
100  if (!doc.load_file(filename.c_str())) {
101  throw vpException(vpException::ioError, "Cannot open file: %s", filename.c_str());
102  }
103 
104  bool detector_node = false;
105  bool extractor_node = false;
106  bool matcher_node = false;
107 
108  pugi::xml_node root_node = doc.document_element();
109  for (pugi::xml_node dataNode = root_node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
110  if (dataNode.type() == pugi::node_element) {
111  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
112  if (iter_data != m_nodeMap.end()) {
113  switch (iter_data->second) {
114  case detector:
115  read_detector(dataNode);
116  detector_node = true;
117  break;
118 
119  case extractor:
120  read_extractor(dataNode);
121  extractor_node = true;
122  break;
123 
124  case matcher:
125  read_matcher(dataNode);
126  matcher_node = true;
127  break;
128 
129  case ransac:
130  read_ransac(dataNode);
131  break;
132 
133  default:
134  break;
135  }
136  }
137  }
138  }
139 
140  if (!detector_node) {
141  std::cout << "detector: name: " << m_detectorName << " (default)" << std::endl;
142  }
143 
144  if (!extractor_node) {
145  std::cout << "extractor: name: " << m_extractorName << " (default)" << std::endl;
146  }
147 
148  if (!matcher_node) {
149  std::cout << "matcher: name: " << m_matcherName << " (default)" << std::endl;
150  }
151  }
152 
158  void read_detector(const pugi::xml_node &node)
159  {
160  bool detector_name_node = false;
161 
162  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
163  if (dataNode.type() == pugi::node_element) {
164  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
165  if (iter_data != m_nodeMap.end()) {
166  switch (iter_data->second) {
167  case name:
168  m_detectorName = dataNode.text().as_string();
169  detector_name_node = true;
170  break;
171 
172  default:
173  break;
174  }
175  }
176  }
177  }
178 
179  if (!detector_name_node)
180  std::cout << "detector : Name : " << m_detectorName << " (default)" << std::endl;
181  else
182  std::cout << "detector : Name : " << m_detectorName << std::endl;
183  }
184 
190  void read_extractor(const pugi::xml_node &node)
191  {
192  bool extractor_name_node = false;
193 
194  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
195  if (dataNode.type() == pugi::node_element) {
196  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
197  if (iter_data != m_nodeMap.end()) {
198  switch (iter_data->second) {
199  case name:
200  m_extractorName = dataNode.text().as_string();
201  extractor_name_node = true;
202  break;
203 
204  default:
205  break;
206  }
207  }
208  }
209  }
210 
211  if (!extractor_name_node)
212  std::cout << "extractor : Name : " << m_extractorName << " (default)" << std::endl;
213  else
214  std::cout << "extractor : Name : " << m_extractorName << std::endl;
215  }
216 
222  void read_matcher(const pugi::xml_node &node)
223  {
224  bool matcher_name_node = false;
225  bool matching_method_node = false;
226  std::string matchingMethodName = "ratioDistanceThreshold";
227  bool matching_factor_threshold_node = false;
228  bool matching_ratio_threshold_node = false;
229 
230  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
231  if (dataNode.type() == pugi::node_element) {
232  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
233  if (iter_data != m_nodeMap.end()) {
234  switch (iter_data->second) {
235  case name:
236  m_matcherName = dataNode.text().as_string();
237  matcher_name_node = true;
238  break;
239 
240  case matching_method: {
241  matchingMethodName = dataNode.text().as_string();
242 
243  std::map<std::string, int>::iterator iter_data2 = m_nodeMap.find(matchingMethodName);
244  if (iter_data2 != m_nodeMap.end()) {
245  matching_method_node = true;
246  switch (iter_data2->second) {
247  case constant_factor_distance_threshold:
248  m_matchingMethod = constantFactorDistanceThreshold;
249  break;
250 
251  case std_distance_threshold:
252  m_matchingMethod = stdDistanceThreshold;
253  break;
254 
255  case ratio_distance_threshold:
256  m_matchingMethod = ratioDistanceThreshold;
257  break;
258 
259  case std_and_ratio_distance_threshold:
260  m_matchingMethod = stdAndRatioDistanceThreshold;
261  break;
262 
263  case no_filter_matching:
264  m_matchingMethod = noFilterMatching;
265  break;
266 
267  default:
268  matching_method_node = false;
269  break;
270  }
271  }
272  break;
273  }
274 
275  case matching_factor_threshold:
276  m_matchingFactorThreshold = dataNode.text().as_double();
277  matching_factor_threshold_node = true;
278  break;
279 
280  case matching_ratio_threshold:
281  m_matchingRatioThreshold = dataNode.text().as_double();
282  matching_ratio_threshold_node = true;
283  break;
284 
285  default:
286  break;
287  }
288  }
289  }
290  }
291 
292  if (!matcher_name_node)
293  std::cout << "matcher : Name : " << m_matcherName << " (default)" << std::endl;
294  else
295  std::cout << "matcher : Name : " << m_matcherName << std::endl;
296 
297  if (!matching_method_node)
298  std::cout << "matcher : Filter method : " << matchingMethodName << " (default)" << std::endl;
299  else
300  std::cout << "matcher : Filter method : " << matchingMethodName << std::endl;
301 
302  if (!matching_factor_threshold_node)
303  std::cout << "matcher : matching factor threshold : " << m_matchingFactorThreshold << " (default)" << std::endl;
304  else
305  std::cout << "matcher : matching factor threshold : " << m_matchingFactorThreshold << std::endl;
306 
307  if (!matching_ratio_threshold_node)
308  std::cout << "matcher : matching ratio threshold : " << m_matchingRatioThreshold << " (default)" << std::endl;
309  else
310  std::cout << "matcher : matching ratio threshold : " << m_matchingRatioThreshold << std::endl;
311  }
312 
318  void read_ransac(const pugi::xml_node &node)
319  {
320  bool use_ransac_vvs_node = false;
321  bool use_ransac_consensus_percentage_node = false;
322  bool nb_ransac_iterations_node = false;
323  bool ransac_reprojection_error_node = false;
324  bool nb_ransac_min_inlier_count_node = false;
325  bool ransac_threshold_node = false;
326  bool ransac_consensus_percentage_node = false;
327 
328  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
329  if (dataNode.type() == pugi::node_element) {
330  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
331  if (iter_data != m_nodeMap.end()) {
332  switch (iter_data->second) {
333  case use_ransac_vvs:
334  m_useRansacVVS = dataNode.text().as_int() != 0;
335  use_ransac_vvs_node = true;
336  break;
337 
338  case use_ransac_consensus_percentage:
339  m_useRansacConsensusPercentage = dataNode.text().as_int() != 0;
340  use_ransac_consensus_percentage_node = true;
341  break;
342 
343  case nb_ransac_iterations:
344  m_nbRansacIterations = dataNode.text().as_int();
345  nb_ransac_iterations_node = true;
346  break;
347 
348  case ransac_reprojection_error:
349  m_ransacReprojectionError = dataNode.text().as_double();
350  ransac_reprojection_error_node = true;
351  break;
352 
353  case nb_ransac_min_inlier_count:
354  m_nbRansacMinInlierCount = dataNode.text().as_int();
355  nb_ransac_min_inlier_count_node = true;
356  break;
357 
358  case ransac_threshold:
359  m_ransacThreshold = dataNode.text().as_double();
360  ransac_threshold_node = true;
361  break;
362 
363  case ransac_consensus_percentage:
364  m_ransacConsensusPercentage = dataNode.text().as_double();
365  ransac_consensus_percentage_node = true;
366  break;
367 
368  default:
369  break;
370  }
371  }
372  }
373  }
374 
375  if (!use_ransac_vvs_node)
376  std::cout << "ransac: use ransac vvs pose estimation: " << m_useRansacVVS << " (default)" << std::endl;
377  else
378  std::cout << "ransac: use ransac vvs pose estimation: " << m_useRansacVVS << std::endl;
379 
380  if (!use_ransac_consensus_percentage_node)
381  std::cout << "ransac: use consensus percentage: " << m_useRansacConsensusPercentage << " (default)" << std::endl;
382  else
383  std::cout << "ransac: use consensus percentage: " << m_useRansacConsensusPercentage << std::endl;
384 
385  if (!nb_ransac_iterations_node)
386  std::cout << "ransac: nb ransac iterations: " << m_nbRansacIterations << " (default)" << std::endl;
387  else
388  std::cout << "ransac: nb ransac iterations: " << m_nbRansacIterations << std::endl;
389 
390  if (!ransac_reprojection_error_node)
391  std::cout << "ransac: ransac reprojection error in pixel (for OpenCV "
392  "function): "
393  << m_ransacReprojectionError << " (default)" << std::endl;
394  else
395  std::cout << "ransac: ransac reprojection error in pixel (for OpenCV "
396  "function): "
397  << m_ransacReprojectionError << std::endl;
398 
399  if (!nb_ransac_min_inlier_count_node)
400  std::cout << "ransac: nb ransac min inlier count: " << m_nbRansacMinInlierCount << " (default)" << std::endl;
401  else
402  std::cout << "ransac: nb ransac min inlier count: " << m_nbRansacMinInlierCount << std::endl;
403 
404  if (!ransac_threshold_node)
405  std::cout << "ransac: ransac threshold in meter (for ViSP function): " << m_ransacThreshold << " (default)"
406  << std::endl;
407  else
408  std::cout << "ransac: ransac threshold in meter (for ViSP function): " << m_ransacThreshold << std::endl;
409 
410  if (!ransac_consensus_percentage_node)
411  std::cout << "ransac: consensus percentage: " << m_ransacConsensusPercentage << " (default)" << std::endl;
412  else
413  std::cout << "ransac: consensus percentage: " << m_ransacConsensusPercentage << std::endl;
414  }
415 
416  std::string getDetectorName() const { return m_detectorName; }
417  std::string getExtractorName() const { return m_extractorName; }
418  std::string getMatcherName() const { return m_matcherName; }
419 
420  double getMatchingFactorThreshold() const { return m_matchingFactorThreshold; }
421  vpMatchingMethodEnum getMatchingMethod() const { return m_matchingMethod; }
422  double getMatchingRatioThreshold() const { return m_matchingRatioThreshold; }
423 
424  int getNbRansacIterations() const { return m_nbRansacIterations; }
425  int getNbRansacMinInlierCount() const { return m_nbRansacMinInlierCount; }
426  double getRansacConsensusPercentage() const { return m_ransacConsensusPercentage; }
427  double getRansacReprojectionError() const { return m_ransacReprojectionError; }
428  double getRansacThreshold() const { return m_ransacThreshold; }
429  bool getUseRansacConsensusPercentage() const { return m_useRansacConsensusPercentage; }
430  bool getUseRansacVVSPoseEstimation() const { return m_useRansacVVS; }
431 
432 protected:
434  enum vpNodeIdentifier {
435  conf,
436  detector,
437  extractor,
438  matcher,
439  name,
440  matching_method,
441  constant_factor_distance_threshold,
444  std_distance_threshold,
446  ratio_distance_threshold,
448  std_and_ratio_distance_threshold,
451  no_filter_matching,
453  matching_factor_threshold,
455  matching_ratio_threshold,
457  ransac,
458  use_ransac_vvs,
459  use_ransac_consensus_percentage,
462  nb_ransac_iterations,
464  ransac_reprojection_error,
466  nb_ransac_min_inlier_count,
468  ransac_threshold,
470  ransac_consensus_percentage
472  };
473 
475  std::string m_detectorName;
477  std::string m_extractorName;
479  std::string m_matcherName;
481  double m_matchingFactorThreshold;
483  vpMatchingMethodEnum m_matchingMethod;
485  double m_matchingRatioThreshold;
487  int m_nbRansacIterations;
489  int m_nbRansacMinInlierCount;
491  double m_ransacConsensusPercentage;
494  double m_ransacReprojectionError;
497  double m_ransacThreshold;
500  // it is based on a fixed number.
501  bool m_useRansacConsensusPercentage;
504  bool m_useRansacVVS;
505  std::map<std::string, int> m_nodeMap;
506 };
507 #endif // DOXYGEN_SHOULD_SKIP_THIS
508 
510 
512 
517 void vpXmlConfigParserKeyPoint::parse(const std::string &filename) { m_impl->parse(filename); }
518 
524 std::string vpXmlConfigParserKeyPoint::getDetectorName() const { return m_impl->getDetectorName(); }
525 
531 std::string vpXmlConfigParserKeyPoint::getExtractorName() const { return m_impl->getExtractorName(); }
532 
538 std::string vpXmlConfigParserKeyPoint::getMatcherName() const { return m_impl->getMatcherName(); }
539 
546 double vpXmlConfigParserKeyPoint::getMatchingFactorThreshold() const { return m_impl->getMatchingFactorThreshold(); }
547 
554 {
555  return m_impl->getMatchingMethod();
556 }
557 
563 double vpXmlConfigParserKeyPoint::getMatchingRatioThreshold() const { return m_impl->getMatchingRatioThreshold(); }
564 
570 int vpXmlConfigParserKeyPoint::getNbRansacIterations() const { return m_impl->getNbRansacIterations(); }
571 
577 int vpXmlConfigParserKeyPoint::getNbRansacMinInlierCount() const { return m_impl->getNbRansacMinInlierCount(); }
578 
585 {
586  return m_impl->getRansacConsensusPercentage();
587 }
588 
595 double vpXmlConfigParserKeyPoint::getRansacReprojectionError() const { return m_impl->getRansacReprojectionError(); }
596 
602 double vpXmlConfigParserKeyPoint::getRansacThreshold() const { return m_impl->getRansacThreshold(); }
603 
611 {
612  return m_impl->getUseRansacConsensusPercentage();
613 }
614 
622 {
623  return m_impl->getUseRansacVVSPoseEstimation();
624 }
vpMatchingMethodEnum getMatchingMethod() const
error that can be emited by ViSP classes.
Definition: vpException.h:71
void parse(const std::string &filename)