Visual Servoing Platform version 3.5.0
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
56class vpXmlConfigParserKeyPoint::Impl
57{
58public:
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
431protected:
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
521void 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}
error that can be emited by ViSP classes.
Definition: vpException.h:72
@ ioError
I/O error.
Definition: vpException.h:91
void parse(const std::string &filename)
vpMatchingMethodEnum getMatchingMethod() const