Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpXmlConfigParserKeyPoint.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 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
40
41#include <iostream>
42
43#include <visp3/vision/vpXmlConfigParserKeyPoint.h>
44
45#include <map>
46#if defined(VISP_HAVE_PUGIXML)
47#include <pugixml.hpp>
48
49#include <visp3/core/vpException.h>
50
52#ifndef DOXYGEN_SHOULD_SKIP_THIS
53class vpXmlConfigParserKeyPoint::Impl
54{
55public:
56 Impl()
57 : m_detectorName("ORB"), m_extractorName("ORB"), m_matcherName("BruteForce-Hamming"),
58 m_matchingFactorThreshold(2.0), m_matchingMethod(ratioDistanceThreshold), m_matchingRatioThreshold(0.85),
59 m_nbRansacIterations(200), m_nbRansacMinInlierCount(100), m_ransacConsensusPercentage(20.0),
60 m_ransacReprojectionError(6.0), m_ransacThreshold(0.01), m_useRansacConsensusPercentage(false),
61 m_useRansacVVS(true)
62 {
63 init();
64 }
65
69 void init()
70 {
71 m_nodeMap["conf"] = conf;
72 m_nodeMap["detector"] = detector;
73 m_nodeMap["extractor"] = extractor;
74 m_nodeMap["matcher"] = matcher;
75 m_nodeMap["name"] = name;
76 m_nodeMap["matching_method"] = matching_method;
77 m_nodeMap["constantFactorDistanceThreshold"] = constant_factor_distance_threshold;
78 m_nodeMap["stdDistanceThreshold"] = std_distance_threshold;
79 m_nodeMap["ratioDistanceThreshold"] = ratio_distance_threshold;
80 m_nodeMap["stdAndRatioDistanceThreshold"] = std_and_ratio_distance_threshold;
81 m_nodeMap["noFilterMatching"] = no_filter_matching;
82 m_nodeMap["matchingFactorThreshold"] = matching_factor_threshold;
83 m_nodeMap["matchingRatioThreshold"] = matching_ratio_threshold;
84 m_nodeMap["ransac"] = ransac;
85 m_nodeMap["useRansacVVS"] = use_ransac_vvs;
86 m_nodeMap["useRansacConsensusPercentage"] = use_ransac_consensus_percentage;
87 m_nodeMap["nbRansacIterations"] = nb_ransac_iterations;
88 m_nodeMap["ransacReprojectionError"] = ransac_reprojection_error;
89 m_nodeMap["nbRansacMinInlierCount"] = nb_ransac_min_inlier_count;
90 m_nodeMap["ransacThreshold"] = ransac_threshold;
91 m_nodeMap["ransacConsensusPercentage"] = ransac_consensus_percentage;
92 }
93
94 void parse(const std::string &filename)
95 {
96 pugi::xml_document doc;
97 if (!doc.load_file(filename.c_str())) {
98 throw vpException(vpException::ioError, "Cannot open file: %s", filename.c_str());
99 }
100
101 bool detector_node = false;
102 bool extractor_node = false;
103 bool matcher_node = false;
104
105 pugi::xml_node root_node = doc.document_element();
106 for (pugi::xml_node dataNode = root_node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
107 if (dataNode.type() == pugi::node_element) {
108 std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
109 if (iter_data != m_nodeMap.end()) {
110 switch (iter_data->second) {
111 case detector:
112 read_detector(dataNode);
113 detector_node = true;
114 break;
115
116 case extractor:
117 read_extractor(dataNode);
118 extractor_node = true;
119 break;
120
121 case matcher:
122 read_matcher(dataNode);
123 matcher_node = true;
124 break;
125
126 case ransac:
127 read_ransac(dataNode);
128 break;
129
130 default:
131 break;
132 }
133 }
134 }
135 }
136
137 if (!detector_node) {
138 std::cout << "detector: name: " << m_detectorName << " (default)" << std::endl;
139 }
140
141 if (!extractor_node) {
142 std::cout << "extractor: name: " << m_extractorName << " (default)" << std::endl;
143 }
144
145 if (!matcher_node) {
146 std::cout << "matcher: name: " << m_matcherName << " (default)" << std::endl;
147 }
148 }
149
155 void read_detector(const pugi::xml_node &node)
156 {
157 bool detector_name_node = false;
158
159 for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
160 if (dataNode.type() == pugi::node_element) {
161 std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
162 if (iter_data != m_nodeMap.end()) {
163 switch (iter_data->second) {
164 case name:
165 m_detectorName = dataNode.text().as_string();
166 detector_name_node = true;
167 break;
168
169 default:
170 break;
171 }
172 }
173 }
174 }
175
176 if (!detector_name_node)
177 std::cout << "detector : Name : " << m_detectorName << " (default)" << std::endl;
178 else
179 std::cout << "detector : Name : " << m_detectorName << std::endl;
180 }
181
187 void read_extractor(const pugi::xml_node &node)
188 {
189 bool extractor_name_node = false;
190
191 for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
192 if (dataNode.type() == pugi::node_element) {
193 std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
194 if (iter_data != m_nodeMap.end()) {
195 switch (iter_data->second) {
196 case name:
197 m_extractorName = dataNode.text().as_string();
198 extractor_name_node = true;
199 break;
200
201 default:
202 break;
203 }
204 }
205 }
206 }
207
208 if (!extractor_name_node)
209 std::cout << "extractor : Name : " << m_extractorName << " (default)" << std::endl;
210 else
211 std::cout << "extractor : Name : " << m_extractorName << std::endl;
212 }
213
219 void read_matcher(const pugi::xml_node &node)
220 {
221 bool matcher_name_node = false;
222 bool matching_method_node = false;
223 std::string matchingMethodName = "ratioDistanceThreshold";
224 bool matching_factor_threshold_node = false;
225 bool matching_ratio_threshold_node = false;
226
227 for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
228 if (dataNode.type() == pugi::node_element) {
229 std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
230 if (iter_data != m_nodeMap.end()) {
231 switch (iter_data->second) {
232 case name:
233 m_matcherName = dataNode.text().as_string();
234 matcher_name_node = true;
235 break;
236
237 case matching_method: {
238 matchingMethodName = dataNode.text().as_string();
239
240 std::map<std::string, int>::iterator iter_data2 = m_nodeMap.find(matchingMethodName);
241 if (iter_data2 != m_nodeMap.end()) {
242 matching_method_node = true;
243 switch (iter_data2->second) {
244 case constant_factor_distance_threshold:
245 m_matchingMethod = constantFactorDistanceThreshold;
246 break;
247
248 case std_distance_threshold:
249 m_matchingMethod = stdDistanceThreshold;
250 break;
251
252 case ratio_distance_threshold:
253 m_matchingMethod = ratioDistanceThreshold;
254 break;
255
256 case std_and_ratio_distance_threshold:
257 m_matchingMethod = stdAndRatioDistanceThreshold;
258 break;
259
260 case no_filter_matching:
261 m_matchingMethod = noFilterMatching;
262 break;
263
264 default:
265 matching_method_node = false;
266 break;
267 }
268 }
269 break;
270 }
271
272 case matching_factor_threshold:
273 m_matchingFactorThreshold = dataNode.text().as_double();
274 matching_factor_threshold_node = true;
275 break;
276
277 case matching_ratio_threshold:
278 m_matchingRatioThreshold = dataNode.text().as_double();
279 matching_ratio_threshold_node = true;
280 break;
281
282 default:
283 break;
284 }
285 }
286 }
287 }
288
289 if (!matcher_name_node)
290 std::cout << "matcher : Name : " << m_matcherName << " (default)" << std::endl;
291 else
292 std::cout << "matcher : Name : " << m_matcherName << std::endl;
293
294 if (!matching_method_node)
295 std::cout << "matcher : Filter method : " << matchingMethodName << " (default)" << std::endl;
296 else
297 std::cout << "matcher : Filter method : " << matchingMethodName << std::endl;
298
299 if (!matching_factor_threshold_node)
300 std::cout << "matcher : matching factor threshold : " << m_matchingFactorThreshold << " (default)" << std::endl;
301 else
302 std::cout << "matcher : matching factor threshold : " << m_matchingFactorThreshold << std::endl;
303
304 if (!matching_ratio_threshold_node)
305 std::cout << "matcher : matching ratio threshold : " << m_matchingRatioThreshold << " (default)" << std::endl;
306 else
307 std::cout << "matcher : matching ratio threshold : " << m_matchingRatioThreshold << std::endl;
308 }
309
315 void read_ransac(const pugi::xml_node &node)
316 {
317 bool use_ransac_vvs_node = false;
318 bool use_ransac_consensus_percentage_node = false;
319 bool nb_ransac_iterations_node = false;
320 bool ransac_reprojection_error_node = false;
321 bool nb_ransac_min_inlier_count_node = false;
322 bool ransac_threshold_node = false;
323 bool ransac_consensus_percentage_node = false;
324
325 for (pugi::xml_node dataNode = node.first_child(); dataNode; dataNode = dataNode.next_sibling()) {
326 if (dataNode.type() == pugi::node_element) {
327 std::map<std::string, int>::iterator iter_data = m_nodeMap.find(dataNode.name());
328 if (iter_data != m_nodeMap.end()) {
329 switch (iter_data->second) {
330 case use_ransac_vvs:
331 m_useRansacVVS = dataNode.text().as_int() != 0;
332 use_ransac_vvs_node = true;
333 break;
334
335 case use_ransac_consensus_percentage:
336 m_useRansacConsensusPercentage = dataNode.text().as_int() != 0;
337 use_ransac_consensus_percentage_node = true;
338 break;
339
340 case nb_ransac_iterations:
341 m_nbRansacIterations = dataNode.text().as_int();
342 nb_ransac_iterations_node = true;
343 break;
344
345 case ransac_reprojection_error:
346 m_ransacReprojectionError = dataNode.text().as_double();
347 ransac_reprojection_error_node = true;
348 break;
349
350 case nb_ransac_min_inlier_count:
351 m_nbRansacMinInlierCount = dataNode.text().as_int();
352 nb_ransac_min_inlier_count_node = true;
353 break;
354
355 case ransac_threshold:
356 m_ransacThreshold = dataNode.text().as_double();
357 ransac_threshold_node = true;
358 break;
359
360 case ransac_consensus_percentage:
361 m_ransacConsensusPercentage = dataNode.text().as_double();
362 ransac_consensus_percentage_node = true;
363 break;
364
365 default:
366 break;
367 }
368 }
369 }
370 }
371
372 if (!use_ransac_vvs_node)
373 std::cout << "ransac: use ransac vvs pose estimation: " << m_useRansacVVS << " (default)" << std::endl;
374 else
375 std::cout << "ransac: use ransac vvs pose estimation: " << m_useRansacVVS << std::endl;
376
377 if (!use_ransac_consensus_percentage_node)
378 std::cout << "ransac: use consensus percentage: " << m_useRansacConsensusPercentage << " (default)" << std::endl;
379 else
380 std::cout << "ransac: use consensus percentage: " << m_useRansacConsensusPercentage << std::endl;
381
382 if (!nb_ransac_iterations_node)
383 std::cout << "ransac: nb ransac iterations: " << m_nbRansacIterations << " (default)" << std::endl;
384 else
385 std::cout << "ransac: nb ransac iterations: " << m_nbRansacIterations << std::endl;
386
387 if (!ransac_reprojection_error_node)
388 std::cout << "ransac: ransac reprojection error in pixel (for OpenCV "
389 "function): "
390 << m_ransacReprojectionError << " (default)" << std::endl;
391 else
392 std::cout << "ransac: ransac reprojection error in pixel (for OpenCV "
393 "function): "
394 << m_ransacReprojectionError << std::endl;
395
396 if (!nb_ransac_min_inlier_count_node)
397 std::cout << "ransac: nb ransac min inlier count: " << m_nbRansacMinInlierCount << " (default)" << std::endl;
398 else
399 std::cout << "ransac: nb ransac min inlier count: " << m_nbRansacMinInlierCount << std::endl;
400
401 if (!ransac_threshold_node)
402 std::cout << "ransac: ransac threshold in meter (for ViSP function): " << m_ransacThreshold << " (default)"
403 << std::endl;
404 else
405 std::cout << "ransac: ransac threshold in meter (for ViSP function): " << m_ransacThreshold << std::endl;
406
407 if (!ransac_consensus_percentage_node)
408 std::cout << "ransac: consensus percentage: " << m_ransacConsensusPercentage << " (default)" << std::endl;
409 else
410 std::cout << "ransac: consensus percentage: " << m_ransacConsensusPercentage << std::endl;
411 }
412
413 std::string getDetectorName() const { return m_detectorName; }
414 std::string getExtractorName() const { return m_extractorName; }
415 std::string getMatcherName() const { return m_matcherName; }
416
417 double getMatchingFactorThreshold() const { return m_matchingFactorThreshold; }
418 vpMatchingMethodEnum getMatchingMethod() const { return m_matchingMethod; }
419 double getMatchingRatioThreshold() const { return m_matchingRatioThreshold; }
420
421 int getNbRansacIterations() const { return m_nbRansacIterations; }
422 int getNbRansacMinInlierCount() const { return m_nbRansacMinInlierCount; }
423 double getRansacConsensusPercentage() const { return m_ransacConsensusPercentage; }
424 double getRansacReprojectionError() const { return m_ransacReprojectionError; }
425 double getRansacThreshold() const { return m_ransacThreshold; }
426 bool getUseRansacConsensusPercentage() const { return m_useRansacConsensusPercentage; }
427 bool getUseRansacVVSPoseEstimation() const { return m_useRansacVVS; }
428
429protected:
431 enum vpNodeIdentifier
432 {
433 conf,
434 detector,
435 extractor,
436 matcher,
437 name,
438 matching_method,
439 constant_factor_distance_threshold,
442 std_distance_threshold,
444 ratio_distance_threshold,
446 std_and_ratio_distance_threshold,
449 no_filter_matching,
451 matching_factor_threshold,
453 matching_ratio_threshold,
455 ransac,
456 use_ransac_vvs,
457 use_ransac_consensus_percentage,
460 nb_ransac_iterations,
462 ransac_reprojection_error,
464 nb_ransac_min_inlier_count,
466 ransac_threshold,
468 ransac_consensus_percentage
470 };
471
473 std::string m_detectorName;
475 std::string m_extractorName;
477 std::string m_matcherName;
479 double m_matchingFactorThreshold;
481 vpMatchingMethodEnum m_matchingMethod;
483 double m_matchingRatioThreshold;
485 int m_nbRansacIterations;
487 int m_nbRansacMinInlierCount;
489 double m_ransacConsensusPercentage;
492 double m_ransacReprojectionError;
495 double m_ransacThreshold;
498 // it is based on a fixed number.
499 bool m_useRansacConsensusPercentage;
502 bool m_useRansacVVS;
503 std::map<std::string, int> m_nodeMap;
504};
505#endif // DOXYGEN_SHOULD_SKIP_THIS
506
508
510
511void vpXmlConfigParserKeyPoint::parse(const std::string &filename) { m_impl->parse(filename); }
512
513std::string vpXmlConfigParserKeyPoint::getDetectorName() const { return m_impl->getDetectorName(); }
514
515std::string vpXmlConfigParserKeyPoint::getExtractorName() const { return m_impl->getExtractorName(); }
516
517std::string vpXmlConfigParserKeyPoint::getMatcherName() const { return m_impl->getMatcherName(); }
518
519double vpXmlConfigParserKeyPoint::getMatchingFactorThreshold() const { return m_impl->getMatchingFactorThreshold(); }
520
525
526double vpXmlConfigParserKeyPoint::getMatchingRatioThreshold() const { return m_impl->getMatchingRatioThreshold(); }
527
528int vpXmlConfigParserKeyPoint::getNbRansacIterations() const { return m_impl->getNbRansacIterations(); }
529
530int vpXmlConfigParserKeyPoint::getNbRansacMinInlierCount() const { return m_impl->getNbRansacMinInlierCount(); }
531
533{
534 return m_impl->getRansacConsensusPercentage();
535}
536
537double vpXmlConfigParserKeyPoint::getRansacReprojectionError() const { return m_impl->getRansacReprojectionError(); }
538
539double vpXmlConfigParserKeyPoint::getRansacThreshold() const { return m_impl->getRansacThreshold(); }
540
542{
543 return m_impl->getUseRansacConsensusPercentage();
544}
545
547{
548 return m_impl->getUseRansacVVSPoseEstimation();
549}
550END_VISP_NAMESPACE
551#elif !defined(VISP_BUILD_SHARED_LIBS)
552// Work around to avoid warning: libvisp_core.a(vpXmlConfigParserKeyPoint.cpp.o) has no symbols
553void dummy_vpXmlConfigParserKeyPoint() { }
554
555#endif
@ ioError
I/O error.
Definition vpException.h:67
void parse(const std::string &filename)
vpMatchingMethodEnum getMatchingMethod() const