Visual Servoing Platform  version 3.5.1 under development (2023-09-22)
vpXmlConfigParserKeyPoint.cpp
1 /*
2  * ViSP, open source Visual Servoing Platform software.
3  * Copyright (C) 2005 - 2023 by Inria. All rights reserved.
4  *
5  * This software is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See https://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * XML parser to load configuration for vpKeyPoint class.
32  */
33 
41 #include <iostream>
42 
43 #include <visp3/vision/vpXmlConfigParserKeyPoint.h>
44 
45 #include <map>
46 #include <pugixml.hpp>
47 
48 #include <visp3/core/vpException.h>
49 
50 #ifndef DOXYGEN_SHOULD_SKIP_THIS
51 class vpXmlConfigParserKeyPoint::Impl
52 {
53 public:
54  Impl()
55  : m_detectorName("ORB"), m_extractorName("ORB"), m_matcherName("BruteForce-Hamming"),
56  m_matchingFactorThreshold(2.0), m_matchingMethod(ratioDistanceThreshold), m_matchingRatioThreshold(0.85),
57  m_nbRansacIterations(200), m_nbRansacMinInlierCount(100), m_ransacConsensusPercentage(20.0),
58  m_ransacReprojectionError(6.0), m_ransacThreshold(0.01), m_useRansacConsensusPercentage(false),
59  m_useRansacVVS(true)
60  {
61  init();
62  }
63 
67  void init()
68  {
69  m_nodeMap["conf"] = conf;
70  m_nodeMap["detector"] = detector;
71  m_nodeMap["extractor"] = extractor;
72  m_nodeMap["matcher"] = matcher;
73  m_nodeMap["name"] = name;
74  m_nodeMap["matching_method"] = matching_method;
75  m_nodeMap["constantFactorDistanceThreshold"] = constant_factor_distance_threshold;
76  m_nodeMap["stdDistanceThreshold"] = std_distance_threshold;
77  m_nodeMap["ratioDistanceThreshold"] = ratio_distance_threshold;
78  m_nodeMap["stdAndRatioDistanceThreshold"] = std_and_ratio_distance_threshold;
79  m_nodeMap["noFilterMatching"] = no_filter_matching;
80  m_nodeMap["matchingFactorThreshold"] = matching_factor_threshold;
81  m_nodeMap["matchingRatioThreshold"] = matching_ratio_threshold;
82  m_nodeMap["ransac"] = ransac;
83  m_nodeMap["useRansacVVS"] = use_ransac_vvs;
84  m_nodeMap["useRansacConsensusPercentage"] = use_ransac_consensus_percentage;
85  m_nodeMap["nbRansacIterations"] = nb_ransac_iterations;
86  m_nodeMap["ransacReprojectionError"] = ransac_reprojection_error;
87  m_nodeMap["nbRansacMinInlierCount"] = nb_ransac_min_inlier_count;
88  m_nodeMap["ransacThreshold"] = ransac_threshold;
89  m_nodeMap["ransacConsensusPercentage"] = ransac_consensus_percentage;
90  }
91 
92  void parse(const std::string &filename)
93  {
94  pugi::xml_document doc;
95  if (!doc.load_file(filename.c_str())) {
96  throw vpException(vpException::ioError, "Cannot open file: %s", filename.c_str());
97  }
98 
99  bool detector_node = false;
100  bool extractor_node = false;
101  bool matcher_node = false;
102 
103  pugi::xml_node root_node = doc.document_element();
104  for (pugi::xml_node dataNode = root_node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
105  if (dataNode.type() == pugi::node_element) {
106  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
107  if (iter_data != m_nodeMap.end()) {
108  switch (iter_data->second) {
109  case detector:
110  read_detector(dataNode);
111  detector_node = true;
112  break;
113 
114  case extractor:
115  read_extractor(dataNode);
116  extractor_node = true;
117  break;
118 
119  case matcher:
120  read_matcher(dataNode);
121  matcher_node = true;
122  break;
123 
124  case ransac:
125  read_ransac(dataNode);
126  break;
127 
128  default:
129  break;
130  }
131  }
132  }
133  }
134 
135  if (!detector_node) {
136  std::cout << "detector: name: " << m_detectorName << " (default)" << std::endl;
137  }
138 
139  if (!extractor_node) {
140  std::cout << "extractor: name: " << m_extractorName << " (default)" << std::endl;
141  }
142 
143  if (!matcher_node) {
144  std::cout << "matcher: name: " << m_matcherName << " (default)" << std::endl;
145  }
146  }
147 
153  void read_detector(const pugi::xml_node &node)
154  {
155  bool detector_name_node = false;
156 
157  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
158  if (dataNode.type() == pugi::node_element) {
159  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
160  if (iter_data != m_nodeMap.end()) {
161  switch (iter_data->second) {
162  case name:
163  m_detectorName = dataNode.text().as_string();
164  detector_name_node = true;
165  break;
166 
167  default:
168  break;
169  }
170  }
171  }
172  }
173 
174  if (!detector_name_node)
175  std::cout << "detector : Name : " << m_detectorName << " (default)" << std::endl;
176  else
177  std::cout << "detector : Name : " << m_detectorName << std::endl;
178  }
179 
185  void read_extractor(const pugi::xml_node &node)
186  {
187  bool extractor_name_node = false;
188 
189  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
190  if (dataNode.type() == pugi::node_element) {
191  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
192  if (iter_data != m_nodeMap.end()) {
193  switch (iter_data->second) {
194  case name:
195  m_extractorName = dataNode.text().as_string();
196  extractor_name_node = true;
197  break;
198 
199  default:
200  break;
201  }
202  }
203  }
204  }
205 
206  if (!extractor_name_node)
207  std::cout << "extractor : Name : " << m_extractorName << " (default)" << std::endl;
208  else
209  std::cout << "extractor : Name : " << m_extractorName << std::endl;
210  }
211 
217  void read_matcher(const pugi::xml_node &node)
218  {
219  bool matcher_name_node = false;
220  bool matching_method_node = false;
221  std::string matchingMethodName = "ratioDistanceThreshold";
222  bool matching_factor_threshold_node = false;
223  bool matching_ratio_threshold_node = false;
224 
225  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
226  if (dataNode.type() == pugi::node_element) {
227  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
228  if (iter_data != m_nodeMap.end()) {
229  switch (iter_data->second) {
230  case name:
231  m_matcherName = dataNode.text().as_string();
232  matcher_name_node = true;
233  break;
234 
235  case matching_method: {
236  matchingMethodName = dataNode.text().as_string();
237 
238  std::map<std::string, int>::iterator iter_data2 = m_nodeMap.find(matchingMethodName);
239  if (iter_data2 != m_nodeMap.end()) {
240  matching_method_node = true;
241  switch (iter_data2->second) {
242  case constant_factor_distance_threshold:
243  m_matchingMethod = constantFactorDistanceThreshold;
244  break;
245 
246  case std_distance_threshold:
247  m_matchingMethod = stdDistanceThreshold;
248  break;
249 
250  case ratio_distance_threshold:
251  m_matchingMethod = ratioDistanceThreshold;
252  break;
253 
254  case std_and_ratio_distance_threshold:
255  m_matchingMethod = stdAndRatioDistanceThreshold;
256  break;
257 
258  case no_filter_matching:
259  m_matchingMethod = noFilterMatching;
260  break;
261 
262  default:
263  matching_method_node = false;
264  break;
265  }
266  }
267  break;
268  }
269 
270  case matching_factor_threshold:
271  m_matchingFactorThreshold = dataNode.text().as_double();
272  matching_factor_threshold_node = true;
273  break;
274 
275  case matching_ratio_threshold:
276  m_matchingRatioThreshold = dataNode.text().as_double();
277  matching_ratio_threshold_node = true;
278  break;
279 
280  default:
281  break;
282  }
283  }
284  }
285  }
286 
287  if (!matcher_name_node)
288  std::cout << "matcher : Name : " << m_matcherName << " (default)" << std::endl;
289  else
290  std::cout << "matcher : Name : " << m_matcherName << std::endl;
291 
292  if (!matching_method_node)
293  std::cout << "matcher : Filter method : " << matchingMethodName << " (default)" << std::endl;
294  else
295  std::cout << "matcher : Filter method : " << matchingMethodName << std::endl;
296 
297  if (!matching_factor_threshold_node)
298  std::cout << "matcher : matching factor threshold : " << m_matchingFactorThreshold << " (default)" << std::endl;
299  else
300  std::cout << "matcher : matching factor threshold : " << m_matchingFactorThreshold << std::endl;
301 
302  if (!matching_ratio_threshold_node)
303  std::cout << "matcher : matching ratio threshold : " << m_matchingRatioThreshold << " (default)" << std::endl;
304  else
305  std::cout << "matcher : matching ratio threshold : " << m_matchingRatioThreshold << std::endl;
306  }
307 
313  void read_ransac(const pugi::xml_node &node)
314  {
315  bool use_ransac_vvs_node = false;
316  bool use_ransac_consensus_percentage_node = false;
317  bool nb_ransac_iterations_node = false;
318  bool ransac_reprojection_error_node = false;
319  bool nb_ransac_min_inlier_count_node = false;
320  bool ransac_threshold_node = false;
321  bool ransac_consensus_percentage_node = false;
322 
323  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
324  if (dataNode.type() == pugi::node_element) {
325  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
326  if (iter_data != m_nodeMap.end()) {
327  switch (iter_data->second) {
328  case use_ransac_vvs:
329  m_useRansacVVS = dataNode.text().as_int() != 0;
330  use_ransac_vvs_node = true;
331  break;
332 
333  case use_ransac_consensus_percentage:
334  m_useRansacConsensusPercentage = dataNode.text().as_int() != 0;
335  use_ransac_consensus_percentage_node = true;
336  break;
337 
338  case nb_ransac_iterations:
339  m_nbRansacIterations = dataNode.text().as_int();
340  nb_ransac_iterations_node = true;
341  break;
342 
343  case ransac_reprojection_error:
344  m_ransacReprojectionError = dataNode.text().as_double();
345  ransac_reprojection_error_node = true;
346  break;
347 
348  case nb_ransac_min_inlier_count:
349  m_nbRansacMinInlierCount = dataNode.text().as_int();
350  nb_ransac_min_inlier_count_node = true;
351  break;
352 
353  case ransac_threshold:
354  m_ransacThreshold = dataNode.text().as_double();
355  ransac_threshold_node = true;
356  break;
357 
358  case ransac_consensus_percentage:
359  m_ransacConsensusPercentage = dataNode.text().as_double();
360  ransac_consensus_percentage_node = true;
361  break;
362 
363  default:
364  break;
365  }
366  }
367  }
368  }
369 
370  if (!use_ransac_vvs_node)
371  std::cout << "ransac: use ransac vvs pose estimation: " << m_useRansacVVS << " (default)" << std::endl;
372  else
373  std::cout << "ransac: use ransac vvs pose estimation: " << m_useRansacVVS << std::endl;
374 
375  if (!use_ransac_consensus_percentage_node)
376  std::cout << "ransac: use consensus percentage: " << m_useRansacConsensusPercentage << " (default)" << std::endl;
377  else
378  std::cout << "ransac: use consensus percentage: " << m_useRansacConsensusPercentage << std::endl;
379 
380  if (!nb_ransac_iterations_node)
381  std::cout << "ransac: nb ransac iterations: " << m_nbRansacIterations << " (default)" << std::endl;
382  else
383  std::cout << "ransac: nb ransac iterations: " << m_nbRansacIterations << std::endl;
384 
385  if (!ransac_reprojection_error_node)
386  std::cout << "ransac: ransac reprojection error in pixel (for OpenCV "
387  "function): "
388  << m_ransacReprojectionError << " (default)" << std::endl;
389  else
390  std::cout << "ransac: ransac reprojection error in pixel (for OpenCV "
391  "function): "
392  << m_ransacReprojectionError << std::endl;
393 
394  if (!nb_ransac_min_inlier_count_node)
395  std::cout << "ransac: nb ransac min inlier count: " << m_nbRansacMinInlierCount << " (default)" << std::endl;
396  else
397  std::cout << "ransac: nb ransac min inlier count: " << m_nbRansacMinInlierCount << std::endl;
398 
399  if (!ransac_threshold_node)
400  std::cout << "ransac: ransac threshold in meter (for ViSP function): " << m_ransacThreshold << " (default)"
401  << std::endl;
402  else
403  std::cout << "ransac: ransac threshold in meter (for ViSP function): " << m_ransacThreshold << std::endl;
404 
405  if (!ransac_consensus_percentage_node)
406  std::cout << "ransac: consensus percentage: " << m_ransacConsensusPercentage << " (default)" << std::endl;
407  else
408  std::cout << "ransac: consensus percentage: " << m_ransacConsensusPercentage << std::endl;
409  }
410 
411  std::string getDetectorName() const { return m_detectorName; }
412  std::string getExtractorName() const { return m_extractorName; }
413  std::string getMatcherName() const { return m_matcherName; }
414 
415  double getMatchingFactorThreshold() const { return m_matchingFactorThreshold; }
416  vpMatchingMethodEnum getMatchingMethod() const { return m_matchingMethod; }
417  double getMatchingRatioThreshold() const { return m_matchingRatioThreshold; }
418 
419  int getNbRansacIterations() const { return m_nbRansacIterations; }
420  int getNbRansacMinInlierCount() const { return m_nbRansacMinInlierCount; }
421  double getRansacConsensusPercentage() const { return m_ransacConsensusPercentage; }
422  double getRansacReprojectionError() const { return m_ransacReprojectionError; }
423  double getRansacThreshold() const { return m_ransacThreshold; }
424  bool getUseRansacConsensusPercentage() const { return m_useRansacConsensusPercentage; }
425  bool getUseRansacVVSPoseEstimation() const { return m_useRansacVVS; }
426 
427 protected:
429  enum vpNodeIdentifier {
430  conf,
431  detector,
432  extractor,
433  matcher,
434  name,
435  matching_method,
436  constant_factor_distance_threshold,
439  std_distance_threshold,
441  ratio_distance_threshold,
443  std_and_ratio_distance_threshold,
446  no_filter_matching,
448  matching_factor_threshold,
450  matching_ratio_threshold,
452  ransac,
453  use_ransac_vvs,
454  use_ransac_consensus_percentage,
457  nb_ransac_iterations,
459  ransac_reprojection_error,
461  nb_ransac_min_inlier_count,
463  ransac_threshold,
465  ransac_consensus_percentage
467  };
468 
470  std::string m_detectorName;
472  std::string m_extractorName;
474  std::string m_matcherName;
476  double m_matchingFactorThreshold;
478  vpMatchingMethodEnum m_matchingMethod;
480  double m_matchingRatioThreshold;
482  int m_nbRansacIterations;
484  int m_nbRansacMinInlierCount;
486  double m_ransacConsensusPercentage;
489  double m_ransacReprojectionError;
492  double m_ransacThreshold;
495  // it is based on a fixed number.
496  bool m_useRansacConsensusPercentage;
499  bool m_useRansacVVS;
500  std::map<std::string, int> m_nodeMap;
501 };
502 #endif // DOXYGEN_SHOULD_SKIP_THIS
503 
505 
507 
512 void vpXmlConfigParserKeyPoint::parse(const std::string &filename) { m_impl->parse(filename); }
513 
519 std::string vpXmlConfigParserKeyPoint::getDetectorName() const { return m_impl->getDetectorName(); }
520 
526 std::string vpXmlConfigParserKeyPoint::getExtractorName() const { return m_impl->getExtractorName(); }
527 
533 std::string vpXmlConfigParserKeyPoint::getMatcherName() const { return m_impl->getMatcherName(); }
534 
541 double vpXmlConfigParserKeyPoint::getMatchingFactorThreshold() const { return m_impl->getMatchingFactorThreshold(); }
542 
549 {
550  return m_impl->getMatchingMethod();
551 }
552 
558 double vpXmlConfigParserKeyPoint::getMatchingRatioThreshold() const { return m_impl->getMatchingRatioThreshold(); }
559 
565 int vpXmlConfigParserKeyPoint::getNbRansacIterations() const { return m_impl->getNbRansacIterations(); }
566 
572 int vpXmlConfigParserKeyPoint::getNbRansacMinInlierCount() const { return m_impl->getNbRansacMinInlierCount(); }
573 
580 {
581  return m_impl->getRansacConsensusPercentage();
582 }
583 
590 double vpXmlConfigParserKeyPoint::getRansacReprojectionError() const { return m_impl->getRansacReprojectionError(); }
591 
597 double vpXmlConfigParserKeyPoint::getRansacThreshold() const { return m_impl->getRansacThreshold(); }
598 
606 {
607  return m_impl->getUseRansacConsensusPercentage();
608 }
609 
617 {
618  return m_impl->getUseRansacVVSPoseEstimation();
619 }
error that can be emitted by ViSP classes.
Definition: vpException.h:59
@ ioError
I/O error.
Definition: vpException.h:79
void parse(const std::string &filename)
vpMatchingMethodEnum getMatchingMethod() const