Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
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"), m_matchingFactorThreshold(2.0),
61  m_matchingMethod(ratioDistanceThreshold), m_matchingRatioThreshold(0.85), m_nbRansacIterations(200),
62  m_nbRansacMinInlierCount(100), m_ransacConsensusPercentage(20.0), m_ransacReprojectionError(6.0),
63  m_ransacThreshold(0.01), m_useRansacConsensusPercentage(false), m_useRansacVVS(true)
64  {
65  init();
66  }
67 
71  void init()
72  {
73  m_nodeMap["conf"] = conf;
74  m_nodeMap["detector"] = detector;
75  m_nodeMap["extractor"] = extractor;
76  m_nodeMap["matcher"] = matcher;
77  m_nodeMap["name"] = name;
78  m_nodeMap["matching_method"] = matching_method;
79  m_nodeMap["constantFactorDistanceThreshold"] = constant_factor_distance_threshold;
80  m_nodeMap["stdDistanceThreshold"] = std_distance_threshold;
81  m_nodeMap["ratioDistanceThreshold"] = ratio_distance_threshold;
82  m_nodeMap["stdAndRatioDistanceThreshold"] = std_and_ratio_distance_threshold;
83  m_nodeMap["noFilterMatching"] = no_filter_matching;
84  m_nodeMap["matchingFactorThreshold"] = matching_factor_threshold;
85  m_nodeMap["matchingRatioThreshold"] = matching_ratio_threshold;
86  m_nodeMap["ransac"] = ransac;
87  m_nodeMap["useRansacVVS"] = use_ransac_vvs;
88  m_nodeMap["useRansacConsensusPercentage"] = use_ransac_consensus_percentage;
89  m_nodeMap["nbRansacIterations"] = nb_ransac_iterations;
90  m_nodeMap["ransacReprojectionError"] = ransac_reprojection_error;
91  m_nodeMap["nbRansacMinInlierCount"] = nb_ransac_min_inlier_count;
92  m_nodeMap["ransacThreshold"] = ransac_threshold;
93  m_nodeMap["ransacConsensusPercentage"] = ransac_consensus_percentage;
94  }
95 
96  void parse(const std::string &filename)
97  {
98  pugi::xml_document doc;
99  if (!doc.load_file(filename.c_str())) {
100  throw vpException(vpException::ioError, "Cannot open file: %s", filename.c_str());
101  }
102 
103  bool detector_node = false;
104  bool extractor_node = false;
105  bool matcher_node = false;
106 
107  pugi::xml_node root_node = doc.document_element();
108  for (pugi::xml_node dataNode = root_node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
109  if (dataNode.type() == pugi::node_element) {
110  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
111  if (iter_data != m_nodeMap.end()) {
112  switch (iter_data->second) {
113  case detector:
114  read_detector(dataNode);
115  detector_node = true;
116  break;
117 
118  case extractor:
119  read_extractor(dataNode);
120  extractor_node = true;
121  break;
122 
123  case matcher:
124  read_matcher(dataNode);
125  matcher_node = true;
126  break;
127 
128  case ransac:
129  read_ransac(dataNode);
130  break;
131 
132  default:
133  break;
134  }
135  }
136  }
137  }
138 
139  if (!detector_node) {
140  std::cout << "detector: name: " << m_detectorName << " (default)" << std::endl;
141  }
142 
143  if (!extractor_node) {
144  std::cout << "extractor: name: " << m_extractorName << " (default)" << std::endl;
145  }
146 
147  if (!matcher_node) {
148  std::cout << "matcher: name: " << m_matcherName << " (default)" << std::endl;
149  }
150  }
151 
157  void read_detector(const pugi::xml_node &node)
158  {
159  bool detector_name_node = false;
160 
161  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
162  if (dataNode.type() == pugi::node_element) {
163  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
164  if (iter_data != m_nodeMap.end()) {
165  switch (iter_data->second) {
166  case name:
167  m_detectorName = dataNode.text().as_string();
168  detector_name_node = true;
169  break;
170 
171  default:
172  break;
173  }
174  }
175  }
176  }
177 
178  if (!detector_name_node)
179  std::cout << "detector : Name : " << m_detectorName << " (default)" << std::endl;
180  else
181  std::cout << "detector : Name : " << m_detectorName << std::endl;
182  }
183 
189  void read_extractor(const pugi::xml_node &node)
190  {
191  bool extractor_name_node = false;
192 
193  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
194  if (dataNode.type() == pugi::node_element) {
195  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
196  if (iter_data != m_nodeMap.end()) {
197  switch (iter_data->second) {
198  case name:
199  m_extractorName = dataNode.text().as_string();
200  extractor_name_node = true;
201  break;
202 
203  default:
204  break;
205  }
206  }
207  }
208  }
209 
210  if (!extractor_name_node)
211  std::cout << "extractor : Name : " << m_extractorName << " (default)" << std::endl;
212  else
213  std::cout << "extractor : Name : " << m_extractorName << std::endl;
214  }
215 
221  void read_matcher(const pugi::xml_node &node)
222  {
223  bool matcher_name_node = false;
224  bool matching_method_node = false;
225  std::string matchingMethodName = "ratioDistanceThreshold";
226  bool matching_factor_threshold_node = false;
227  bool matching_ratio_threshold_node = false;
228 
229  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
230  if (dataNode.type() == pugi::node_element) {
231  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
232  if (iter_data != m_nodeMap.end()) {
233  switch (iter_data->second) {
234  case name:
235  m_matcherName = dataNode.text().as_string();
236  matcher_name_node = true;
237  break;
238 
239  case matching_method: {
240  matchingMethodName = dataNode.text().as_string();
241 
242  std::map<std::string, int>::iterator iter_data2 = m_nodeMap.find(matchingMethodName);
243  if (iter_data2 != m_nodeMap.end()) {
244  matching_method_node = true;
245  switch (iter_data2->second) {
246  case constant_factor_distance_threshold:
247  m_matchingMethod = constantFactorDistanceThreshold;
248  break;
249 
250  case std_distance_threshold:
251  m_matchingMethod = stdDistanceThreshold;
252  break;
253 
254  case ratio_distance_threshold:
255  m_matchingMethod = ratioDistanceThreshold;
256  break;
257 
258  case std_and_ratio_distance_threshold:
259  m_matchingMethod = stdAndRatioDistanceThreshold;
260  break;
261 
262  case no_filter_matching:
263  m_matchingMethod = noFilterMatching;
264  break;
265 
266  default:
267  matching_method_node = false;
268  break;
269  }
270  }
271  break;
272  }
273 
274  case matching_factor_threshold:
275  m_matchingFactorThreshold = dataNode.text().as_double();
276  matching_factor_threshold_node = true;
277  break;
278 
279  case matching_ratio_threshold:
280  m_matchingRatioThreshold = dataNode.text().as_double();
281  matching_ratio_threshold_node = true;
282  break;
283 
284  default:
285  break;
286  }
287  }
288  }
289  }
290 
291  if (!matcher_name_node)
292  std::cout << "matcher : Name : " << m_matcherName << " (default)" << std::endl;
293  else
294  std::cout << "matcher : Name : " << m_matcherName << std::endl;
295 
296  if (!matching_method_node)
297  std::cout << "matcher : Filter method : " << matchingMethodName << " (default)" << std::endl;
298  else
299  std::cout << "matcher : Filter method : " << matchingMethodName << std::endl;
300 
301  if (!matching_factor_threshold_node)
302  std::cout << "matcher : matching factor threshold : " << m_matchingFactorThreshold << " (default)" << std::endl;
303  else
304  std::cout << "matcher : matching factor threshold : " << m_matchingFactorThreshold << std::endl;
305 
306  if (!matching_ratio_threshold_node)
307  std::cout << "matcher : matching ratio threshold : " << m_matchingRatioThreshold << " (default)" << std::endl;
308  else
309  std::cout << "matcher : matching ratio threshold : " << m_matchingRatioThreshold << std::endl;
310  }
311 
317  void read_ransac(const pugi::xml_node &node)
318  {
319  bool use_ransac_vvs_node = false;
320  bool use_ransac_consensus_percentage_node = false;
321  bool nb_ransac_iterations_node = false;
322  bool ransac_reprojection_error_node = false;
323  bool nb_ransac_min_inlier_count_node = false;
324  bool ransac_threshold_node = false;
325  bool ransac_consensus_percentage_node = false;
326 
327  for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
328  if (dataNode.type() == pugi::node_element) {
329  std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
330  if (iter_data != m_nodeMap.end()) {
331  switch (iter_data->second) {
332  case use_ransac_vvs:
333  m_useRansacVVS = dataNode.text().as_int() != 0;
334  use_ransac_vvs_node = true;
335  break;
336 
337  case use_ransac_consensus_percentage:
338  m_useRansacConsensusPercentage = dataNode.text().as_int() != 0;
339  use_ransac_consensus_percentage_node = true;
340  break;
341 
342  case nb_ransac_iterations:
343  m_nbRansacIterations = dataNode.text().as_int();
344  nb_ransac_iterations_node = true;
345  break;
346 
347  case ransac_reprojection_error:
348  m_ransacReprojectionError = dataNode.text().as_double();
349  ransac_reprojection_error_node = true;
350  break;
351 
352  case nb_ransac_min_inlier_count:
353  m_nbRansacMinInlierCount = dataNode.text().as_int();
354  nb_ransac_min_inlier_count_node = true;
355  break;
356 
357  case ransac_threshold:
358  m_ransacThreshold = dataNode.text().as_double();
359  ransac_threshold_node = true;
360  break;
361 
362  case ransac_consensus_percentage:
363  m_ransacConsensusPercentage = dataNode.text().as_double();
364  ransac_consensus_percentage_node = true;
365  break;
366 
367  default:
368  break;
369  }
370  }
371  }
372  }
373 
374  if (!use_ransac_vvs_node)
375  std::cout << "ransac: use ransac vvs pose estimation: " << m_useRansacVVS << " (default)" << std::endl;
376  else
377  std::cout << "ransac: use ransac vvs pose estimation: " << m_useRansacVVS << std::endl;
378 
379  if (!use_ransac_consensus_percentage_node)
380  std::cout << "ransac: use consensus percentage: " << m_useRansacConsensusPercentage << " (default)" << std::endl;
381  else
382  std::cout << "ransac: use consensus percentage: " << m_useRansacConsensusPercentage << std::endl;
383 
384  if (!nb_ransac_iterations_node)
385  std::cout << "ransac: nb ransac iterations: " << m_nbRansacIterations << " (default)" << std::endl;
386  else
387  std::cout << "ransac: nb ransac iterations: " << m_nbRansacIterations << std::endl;
388 
389  if (!ransac_reprojection_error_node)
390  std::cout << "ransac: ransac reprojection error in pixel (for OpenCV "
391  "function): "
392  << m_ransacReprojectionError << " (default)" << std::endl;
393  else
394  std::cout << "ransac: ransac reprojection error in pixel (for OpenCV "
395  "function): "
396  << m_ransacReprojectionError << std::endl;
397 
398  if (!nb_ransac_min_inlier_count_node)
399  std::cout << "ransac: nb ransac min inlier count: " << m_nbRansacMinInlierCount << " (default)" << std::endl;
400  else
401  std::cout << "ransac: nb ransac min inlier count: " << m_nbRansacMinInlierCount << std::endl;
402 
403  if (!ransac_threshold_node)
404  std::cout << "ransac: ransac threshold in meter (for ViSP function): " << m_ransacThreshold << " (default)"
405  << std::endl;
406  else
407  std::cout << "ransac: ransac threshold in meter (for ViSP function): " << m_ransacThreshold << std::endl;
408 
409  if (!ransac_consensus_percentage_node)
410  std::cout << "ransac: consensus percentage: " << m_ransacConsensusPercentage << " (default)" << std::endl;
411  else
412  std::cout << "ransac: consensus percentage: " << m_ransacConsensusPercentage << std::endl;
413  }
414 
415  std::string getDetectorName() const { return m_detectorName; }
416  std::string getExtractorName() const { return m_extractorName; }
417  std::string getMatcherName() const { return m_matcherName; }
418 
419  double getMatchingFactorThreshold() const { return m_matchingFactorThreshold; }
420  vpMatchingMethodEnum getMatchingMethod() const { return m_matchingMethod; }
421  double getMatchingRatioThreshold() const { return m_matchingRatioThreshold; }
422 
423  int getNbRansacIterations() const { return m_nbRansacIterations; }
424  int getNbRansacMinInlierCount() const { return m_nbRansacMinInlierCount; }
425  double getRansacConsensusPercentage() const { return m_ransacConsensusPercentage; }
426  double getRansacReprojectionError() const { return m_ransacReprojectionError; }
427  double getRansacThreshold() const { return m_ransacThreshold; }
428  bool getUseRansacConsensusPercentage() const { return m_useRansacConsensusPercentage; }
429  bool getUseRansacVVSPoseEstimation() const { return m_useRansacVVS; }
430 
431 protected:
433  enum vpNodeIdentifier {
434  conf,
435  detector,
436  extractor,
437  matcher,
438  name,
439  matching_method,
440  constant_factor_distance_threshold,
443  std_distance_threshold,
445  ratio_distance_threshold,
447  std_and_ratio_distance_threshold,
450  no_filter_matching,
452  matching_factor_threshold,
454  matching_ratio_threshold,
456  ransac,
457  use_ransac_vvs,
458  use_ransac_consensus_percentage,
461  nb_ransac_iterations,
463  ransac_reprojection_error,
465  nb_ransac_min_inlier_count,
467  ransac_threshold,
469  ransac_consensus_percentage
471  };
472 
474  std::string m_detectorName;
476  std::string m_extractorName;
478  std::string m_matcherName;
480  double m_matchingFactorThreshold;
482  vpMatchingMethodEnum m_matchingMethod;
484  double m_matchingRatioThreshold;
486  int m_nbRansacIterations;
488  int m_nbRansacMinInlierCount;
490  double m_ransacConsensusPercentage;
493  double m_ransacReprojectionError;
496  double m_ransacThreshold;
499  // it is based on a fixed number.
500  bool m_useRansacConsensusPercentage;
503  bool m_useRansacVVS;
504  std::map<std::string, int> m_nodeMap;
505 };
506 #endif // DOXYGEN_SHOULD_SKIP_THIS
507 
509 {
510 }
511 
513 {
514  delete m_impl;
515 }
516 
521 void vpXmlConfigParserKeyPoint::parse(const std::string &filename)
522 {
523  m_impl->parse(filename);
524 }
525 
532 {
533  return m_impl->getDetectorName();
534 }
535 
542 {
543  return m_impl->getExtractorName();
544 }
545 
552 {
553  return m_impl->getMatcherName();
554 }
555 
563 {
564  return m_impl->getMatchingFactorThreshold();
565 }
566 
573 {
574  return m_impl->getMatchingMethod();
575 }
576 
583 {
584  return m_impl->getMatchingRatioThreshold();
585 }
586 
593 {
594  return m_impl->getNbRansacIterations();
595 }
596 
603 {
604  return m_impl->getNbRansacMinInlierCount();
605 }
606 
613 {
614  return m_impl->getRansacConsensusPercentage();
615 }
616 
624 {
625  return m_impl->getRansacReprojectionError();
626 }
627 
634 {
635  return m_impl->getRansacThreshold();
636 }
637 
645 {
646  return m_impl->getUseRansacConsensusPercentage();
647 }
648 
656 {
657  return m_impl->getUseRansacVVSPoseEstimation();
658 }
vpMatchingMethodEnum getMatchingMethod() const
error that can be emited by ViSP classes.
Definition: vpException.h:71
void parse(const std::string &filename)