Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
testKeyPoint-7.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 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 * Test saving / loading learning files for vpKeyPoint class.
32 */
33
39
40#include <iomanip>
41#include <iostream>
42
43#include <visp3/core/vpConfig.h>
44
45#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_VIDEO) && \
46 (((VISP_HAVE_OPENCV_VERSION < 0x050000) && defined(HAVE_OPENCV_CALIB3D) && defined(HAVE_OPENCV_FEATURES2D)) || \
47 ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && defined(HAVE_OPENCV_3D) && defined(HAVE_OPENCV_FEATURES)))
48
49#include <visp3/core/vpException.h>
50#include <visp3/core/vpImage.h>
51#include <visp3/core/vpIoTools.h>
52#include <visp3/io/vpImageIo.h>
53#include <visp3/io/vpParseArgv.h>
54#include <visp3/vision/vpKeyPoint.h>
55
56// List of allowed command line options
57#define GETOPTARGS "cdo:h"
58
59#ifdef ENABLE_VISP_NAMESPACE
60using namespace VISP_NAMESPACE_NAME;
61#endif
62
63
64void usage(const char *name, const char *badparam, const std::string &opath, const std::string &user);
65bool getOptions(int argc, const char **argv, std::string &opath, const std::string &user);
66bool compareKeyPoints(const std::vector<cv::KeyPoint> &keypoints1, const std::vector<cv::KeyPoint> &keypoints2);
67bool compareDescriptors(const cv::Mat &descriptors1, const cv::Mat &descriptors2);
68
75void usage(const char *name, const char *badparam, const std::string &opath, const std::string &user)
76{
77 fprintf(stdout, "\n\
78Test save / load learning files for vpKeyPoint class.\n\
79\n\
80SYNOPSIS\n\
81 %s [-c] [-d] [-h]\n",
82 name);
83
84 fprintf(stdout, "\n\
85OPTIONS: \n\
86\n\
87 -o <output image path> %s\n\
88 Set image output path.\n\
89 From this directory, creates the \"%s\"\n\
90 subdirectory depending on the username, where \n\
91 learning files will be written.\n\
92\n\
93 -h\n\
94 Print the help.\n",
95 opath.c_str(), user.c_str());
96
97 if (badparam)
98 fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
99}
100
110bool getOptions(int argc, const char **argv, std::string &opath, const std::string &user)
111{
112 const char *optarg_;
113 int c;
114 while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
115
116 switch (c) {
117 case 'c':
118 break; // not used, to avoid error with default arguments ctest
119 case 'd':
120 break; // not used, to avoid error with default arguments ctest
121 case 'o':
122 opath = optarg_;
123 break;
124 case 'h':
125 usage(argv[0], nullptr, opath, user);
126 return false;
127
128 default:
129 usage(argv[0], optarg_, opath, user);
130 return false;
131 return false;
132 }
133 }
134
135 if ((c == 1) || (c == -1)) {
136 // standalone param or error
137 usage(argv[0], nullptr, opath, user);
138 std::cerr << "ERROR: " << std::endl;
139 std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
140 return false;
141 }
142
143 return true;
144}
145
154bool compareKeyPoints(const std::vector<cv::KeyPoint> &keypoints1, const std::vector<cv::KeyPoint> &keypoints2)
155{
156 if (keypoints1.size() != keypoints2.size()) {
157 return false;
158 }
159
160 for (size_t cpt = 0; cpt < keypoints1.size(); cpt++) {
161 if (!vpMath::equal(keypoints1[cpt].angle, keypoints2[cpt].angle, std::numeric_limits<float>::epsilon())) {
162 std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].angle=" << keypoints1[cpt].angle
163 << " ; keypoints2[cpt].angle=" << keypoints2[cpt].angle << std::endl;
164 return false;
165 }
166
167 if (keypoints1[cpt].class_id != keypoints2[cpt].class_id) {
168 std::cerr << "keypoints1[cpt].class_id=" << keypoints1[cpt].class_id
169 << " ; keypoints2[cpt].class_id=" << keypoints2[cpt].class_id << std::endl;
170 return false;
171 }
172
173 if (keypoints1[cpt].octave != keypoints2[cpt].octave) {
174 std::cerr << "keypoints1[cpt].octave=" << keypoints1[cpt].octave
175 << " ; keypoints2[cpt].octave=" << keypoints2[cpt].octave << std::endl;
176 return false;
177 }
178
179 if (!vpMath::equal(keypoints1[cpt].pt.x, keypoints2[cpt].pt.x, std::numeric_limits<float>::epsilon())) {
180 std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].pt.x=" << keypoints1[cpt].pt.x
181 << " ; keypoints2[cpt].pt.x=" << keypoints2[cpt].pt.x << std::endl;
182 return false;
183 }
184
185 if (!vpMath::equal(keypoints1[cpt].pt.y, keypoints2[cpt].pt.y, std::numeric_limits<float>::epsilon())) {
186 std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].pt.y=" << keypoints1[cpt].pt.y
187 << " ; keypoints2[cpt].pt.y=" << keypoints2[cpt].pt.y << std::endl;
188 return false;
189 }
190
191 if (!vpMath::equal(keypoints1[cpt].response, keypoints2[cpt].response, std::numeric_limits<float>::epsilon())) {
192 std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].response=" << keypoints1[cpt].response
193 << " ; keypoints2[cpt].response=" << keypoints2[cpt].response << std::endl;
194 return false;
195 }
196
197 if (!vpMath::equal(keypoints1[cpt].size, keypoints2[cpt].size, std::numeric_limits<float>::epsilon())) {
198 std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].size=" << keypoints1[cpt].size
199 << " ; keypoints2[cpt].size=" << keypoints2[cpt].size << std::endl;
200 return false;
201 }
202 }
203
204 return true;
205}
206
215bool compareDescriptors(const cv::Mat &descriptors1, const cv::Mat &descriptors2)
216{
217 if (descriptors1.rows != descriptors2.rows || descriptors1.cols != descriptors2.cols ||
218 descriptors1.type() != descriptors2.type()) {
219 return false;
220 }
221
222 for (int i = 0; i < descriptors1.rows; i++) {
223 for (int j = 0; j < descriptors1.cols; j++) {
224 switch (descriptors1.type()) {
225 case CV_8U:
226 if (descriptors1.at<unsigned char>(i, j) != descriptors2.at<unsigned char>(i, j)) {
227 std::cerr << "descriptors1.at<unsigned char>(i,j)=" << descriptors1.at<unsigned char>(i, j)
228 << " ; descriptors2.at<unsigned char>(i,j)=" << descriptors2.at<unsigned char>(i, j) << std::endl;
229 return false;
230 }
231 break;
232
233 case CV_8S:
234 if (descriptors1.at<char>(i, j) != descriptors2.at<char>(i, j)) {
235 std::cerr << "descriptors1.at<char>(i,j)=" << descriptors1.at<char>(i, j)
236 << " ; descriptors2.at<char>(i,j)=" << descriptors2.at<char>(i, j) << std::endl;
237 return false;
238 }
239 break;
240
241 case CV_16U:
242 if (descriptors1.at<unsigned short>(i, j) != descriptors2.at<unsigned short>(i, j)) {
243 std::cerr << "descriptors1.at<unsigned short>(i,j)=" << descriptors1.at<unsigned short>(i, j)
244 << " ; descriptors2.at<unsigned short>(i,j)=" << descriptors2.at<unsigned short>(i, j) << std::endl;
245 return false;
246 }
247 break;
248
249 case CV_16S:
250 if (descriptors1.at<short>(i, j) != descriptors2.at<short>(i, j)) {
251 std::cerr << "descriptors1.at<short>(i,j)=" << descriptors1.at<short>(i, j)
252 << " ; descriptors2.at<short>(i,j)=" << descriptors2.at<short>(i, j) << std::endl;
253 return false;
254 }
255 break;
256
257 case CV_32S:
258 if (descriptors1.at<int>(i, j) != descriptors2.at<int>(i, j)) {
259 std::cerr << "descriptors1.at<int>(i,j)=" << descriptors1.at<int>(i, j)
260 << " ; descriptors2.at<int>(i,j)=" << descriptors2.at<int>(i, j) << std::endl;
261 return false;
262 }
263 break;
264
265 case CV_32F:
266 if (!vpMath::equal(descriptors1.at<float>(i, j), descriptors2.at<float>(i, j),
267 std::numeric_limits<float>::epsilon())) {
268 std::cerr << std::fixed << std::setprecision(9)
269 << "descriptors1.at<float>(i,j)=" << descriptors1.at<float>(i, j)
270 << " ; descriptors2.at<float>(i,j)=" << descriptors2.at<float>(i, j) << std::endl;
271 return false;
272 }
273 break;
274
275 case CV_64F:
276 if (!vpMath::equal(descriptors1.at<double>(i, j), descriptors2.at<double>(i, j),
277 std::numeric_limits<double>::epsilon())) {
278 std::cerr << std::fixed << std::setprecision(17)
279 << "descriptors1.at<double>(i,j)=" << descriptors1.at<double>(i, j)
280 << " ; descriptors2.at<double>(i,j)=" << descriptors2.at<double>(i, j) << std::endl;
281 return false;
282 }
283 break;
284
285 default:
286 return false;
287 break;
288 }
289 }
290 }
291
292 return true;
293}
294
295template <typename Type> void run_test(const std::string &env_ipath, const std::string &opath, vpImage<Type> &I)
296{
297 std::string filename;
298 // Set the path location of the image sequence
299 std::string dirname = vpIoTools::createFilePath(env_ipath, "Klimt");
300
301 // Build the name of the image files
302 std::string img_filename = vpIoTools::createFilePath(dirname, "/Klimt.ppm");
303 vpImageIo::read(I, img_filename);
304
305 vpKeyPoint keyPoints;
306
307 // Test with binary descriptor
308 {
309 std::cout << "Detect ORB keypoints" << std::endl;
310 std::string keypointName = "ORB";
311 keyPoints.setDetector(keypointName);
312 keyPoints.setExtractor(keypointName);
313
314 keyPoints.buildReference(I);
315
316 std::vector<cv::KeyPoint> trainKeyPoints;
317 keyPoints.getTrainKeyPoints(trainKeyPoints);
318 cv::Mat trainDescriptors = keyPoints.getTrainDescriptors();
319 if (trainKeyPoints.empty() || trainDescriptors.empty() || static_cast<int>(trainKeyPoints.size()) != trainDescriptors.rows) {
320 throw vpException(vpException::fatalError, "Problem when detecting "
321 "keypoints or when "
322 "computing descriptors !");
323 }
324
325 // Save in binary with training images
326 filename = vpIoTools::createFilePath(opath, "bin_with_img");
327 vpIoTools::makeDirectory(filename);
328 filename = vpIoTools::createFilePath(filename, "test_save_in_bin_with_img.bin");
329 std::cout << "Save keypoints in binary with image in: " << filename << std::endl;
330 keyPoints.saveLearningData(filename, true, true);
331
332 // Test if save is ok
333 if (!vpIoTools::checkFilename(filename)) {
334 std::stringstream ss;
335 ss << "Problem when saving file=" << filename;
336 throw vpException(vpException::ioError, ss.str().c_str());
337 }
338
339 // Test if read is ok
340 vpKeyPoint read_keypoint1;
341 std::cout << "Read keypoints from file: " << filename << std::endl;
342 read_keypoint1.loadLearningData(filename, true);
343
344 std::vector<cv::KeyPoint> trainKeyPoints_read;
345 read_keypoint1.getTrainKeyPoints(trainKeyPoints_read);
346 cv::Mat trainDescriptors_read = read_keypoint1.getTrainDescriptors();
347
348 std::cout << "Compare keypoints" << std::endl;
349 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
350 throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved "
351 "in binary with train images saved !");
352 }
353
354 std::cout << "Compare descriptors" << std::endl;
355 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
356 throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
357 "learning file saved in "
358 "binary with train images saved !");
359 }
360
361 // Save in binary without training images
362 filename = vpIoTools::createFilePath(opath, "bin_without_img");
363 vpIoTools::makeDirectory(filename);
364 filename = vpIoTools::createFilePath(filename, "test_save_in_bin_without_img.bin");
365 std::cout << "Save keypoints in binary without image in: " << filename << std::endl;
366 keyPoints.saveLearningData(filename, true, false);
367
368 // Test if save is ok
369 if (!vpIoTools::checkFilename(filename)) {
370 std::stringstream ss;
371 ss << "Problem when saving file=" << filename;
372 throw vpException(vpException::ioError, ss.str().c_str());
373 }
374
375 // Test if read is ok
376 vpKeyPoint read_keypoint2;
377 std::cout << "Read keypoints from file: " << filename << std::endl;
378 read_keypoint2.loadLearningData(filename, true);
379 trainKeyPoints_read.clear();
380 read_keypoint2.getTrainKeyPoints(trainKeyPoints_read);
381 trainDescriptors_read = read_keypoint2.getTrainDescriptors();
382
383 std::cout << "Compare keypoints" << std::endl;
384 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
385 throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
386 "binary without train images !");
387 }
388
389 std::cout << "Compare descriptors" << std::endl;
390 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
391 throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
392 "learning file saved in "
393 "binary without train images !");
394 }
395
396#if defined(VISP_HAVE_PUGIXML)
397 // Save in xml with training images
398 filename = vpIoTools::createFilePath(opath, "xml_with_img");
399 vpIoTools::makeDirectory(filename);
400 filename = vpIoTools::createFilePath(filename, "test_save_in_xml_with_img.xml");
401 std::cout << "Save keypoints in xml with image in: " << filename << std::endl;
402 keyPoints.saveLearningData(filename, false, true);
403
404 // Test if save is ok
405 if (!vpIoTools::checkFilename(filename)) {
406 std::stringstream ss;
407 ss << "Problem when saving file=" << filename;
408 throw vpException(vpException::ioError, ss.str().c_str());
409 }
410
411 // Test if read is ok
412 vpKeyPoint read_keypoint3;
413 std::cout << "Read keypoints from file: " << filename << std::endl;
414 read_keypoint3.loadLearningData(filename, false);
415 trainKeyPoints_read.clear();
416 read_keypoint3.getTrainKeyPoints(trainKeyPoints_read);
417 trainDescriptors_read = read_keypoint3.getTrainDescriptors();
418
419 std::cout << "Compare keypoints" << std::endl;
420 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
421 throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
422 "xml with train images saved !");
423 }
424
425 std::cout << "Compare descriptors" << std::endl;
426 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
427 throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
428 "learning file saved in "
429 "xml with train images saved !");
430 }
431
432 // Save in xml without training images
433 filename = vpIoTools::createFilePath(opath, "xml_without_img");
434 vpIoTools::makeDirectory(filename);
435 filename = vpIoTools::createFilePath(filename, "test_save_in_xml_without_img.xml");
436 std::cout << "Save keypoints in xml without image in: " << filename << std::endl;
437 keyPoints.saveLearningData(filename, false, false);
438
439 // Test if save is ok
440 if (!vpIoTools::checkFilename(filename)) {
441 std::stringstream ss;
442 ss << "Problem when saving file=" << filename;
443 throw vpException(vpException::ioError, ss.str().c_str());
444 }
445
446 // Test if read is ok
447 vpKeyPoint read_keypoint4;
448 read_keypoint4.loadLearningData(filename, false);
449 trainKeyPoints_read.clear();
450 std::cout << "Read keypoints from file: " << filename << std::endl;
451 read_keypoint4.getTrainKeyPoints(trainKeyPoints_read);
452 trainDescriptors_read = read_keypoint4.getTrainDescriptors();
453
454 std::cout << "Compare keypoints" << std::endl;
455 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
456 throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
457 "xml without train images saved !");
458 }
459
460 std::cout << "Compare descriptors" << std::endl;
461 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
462 throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
463 "learning file saved in "
464 "xml without train images saved !");
465 }
466#endif
467 std::cout << "Saving / loading learning files with binary descriptor are ok !" << std::endl;
468 }
469
470 // Test with floating point descriptor
471#if defined(VISP_HAVE_OPENCV) && \
472 (((VISP_HAVE_OPENCV_VERSION < 0x050000) && defined(HAVE_OPENCV_XFEATURES2D)) || \
473 ((VISP_HAVE_OPENCV_VERSION >= 0x050000) && defined(HAVE_OPENCV_FEATURES)))
474 {
475#if (VISP_HAVE_OPENCV_VERSION != 0x040504) && (VISP_HAVE_OPENCV_VERSION != 0x040505) && \
476 (VISP_HAVE_OPENCV_VERSION != 0x040600) && (VISP_HAVE_OPENCV_VERSION != 0x040700) && \
477 (VISP_HAVE_OPENCV_VERSION != 0x040900) && (VISP_HAVE_OPENCV_VERSION != 0x040A00) && \
478 (defined(__APPLE__) && defined(__MACH__))
479 // SIFT is known to be unstable with OpenCV 4.5.4 and 4.5.5 on macOS (see #1048)
480 // Same for OpenCV 4.6.0 (see #1106) where it produces an Illegal Instruction error when OpenCV 4.6.0 is
481 // installed with brew. It seems working when OpenCV is build from source
482 std::string keypointName = "SIFT";
483 std::cout << "Use " << keypointName << " keypoints" << std::endl;
484 keyPoints.setDetector(keypointName);
485 keyPoints.setExtractor(keypointName);
486
487 std::cout << "Detect keypoints" << std::endl;
488 keyPoints.buildReference(I);
489
490 std::vector<cv::KeyPoint> trainKeyPoints;
491 keyPoints.getTrainKeyPoints(trainKeyPoints);
492 std::cout << "Get descriptors" << std::endl;
493 cv::Mat trainDescriptors = keyPoints.getTrainDescriptors();
494 if (trainKeyPoints.empty() || trainDescriptors.empty() ||static_cast<int>(trainKeyPoints.size()) != trainDescriptors.rows) {
495 throw vpException(vpException::fatalError, "Problem when detecting keypoints or when "
496 "computing descriptors (SIFT) !");
497 }
498
499 // Save in binary with training images
500 filename = vpIoTools::createFilePath(opath, "bin_with_img");
501 vpIoTools::makeDirectory(filename);
502 filename = vpIoTools::createFilePath(filename, "test_save_in_bin_with_img.bin");
503 std::cout << "Save keypoints in binary with image in: " << filename << std::endl;
504 keyPoints.saveLearningData(filename, true, true);
505
506 // Test if save is ok
507 if (!vpIoTools::checkFilename(filename)) {
508 std::stringstream ss;
509 ss << "Problem when saving file=" << filename;
510 throw vpException(vpException::ioError, ss.str().c_str());
511 }
512
513 // Test if read is ok
514 vpKeyPoint read_keypoint1;
515 std::cout << "Load keypoints from: " << filename << std::endl;
516 read_keypoint1.loadLearningData(filename, true);
517 std::vector<cv::KeyPoint> trainKeyPoints_read;
518 read_keypoint1.getTrainKeyPoints(trainKeyPoints_read);
519 cv::Mat trainDescriptors_read = read_keypoint1.getTrainDescriptors();
520
521 std::cout << "Compare keypoints" << std::endl;
522 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
523 throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
524 "binary with train images saved !");
525 }
526
527 std::cout << "Compare descriptors" << std::endl;
528 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
529 throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
530 "learning file saved in "
531 "binary with train images saved !");
532 }
533
534 // Save in binary with no training images
535 filename = vpIoTools::createFilePath(opath, "bin_without_img");
536 vpIoTools::makeDirectory(filename);
537 filename = vpIoTools::createFilePath(filename, "test_save_in_bin_without_img.bin");
538 std::cout << "Save keypoints in binary without image in: " << filename << std::endl;
539 keyPoints.saveLearningData(filename, true, false);
540
541 // Test if save is ok
542 if (!vpIoTools::checkFilename(filename)) {
543 std::stringstream ss;
544 ss << "Problem when saving file=" << filename;
545 throw vpException(vpException::ioError, ss.str().c_str());
546 }
547
548 // Test if read is ok
549 vpKeyPoint read_keypoint2;
550 std::cout << "Load keypoints from: " << filename << std::endl;
551 read_keypoint2.loadLearningData(filename, true);
552 trainKeyPoints_read.clear();
553 read_keypoint2.getTrainKeyPoints(trainKeyPoints_read);
554 trainDescriptors_read = read_keypoint2.getTrainDescriptors();
555
556 std::cout << "Compare keypoints" << std::endl;
557 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
558 throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
559 "binary without train images saved !");
560 }
561
562 std::cout << "Compare descriptors" << std::endl;
563 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
564 throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
565 "learning file saved in "
566 "binary without train images saved !");
567 }
568
569#if defined(VISP_HAVE_PUGIXML)
570 // Save in xml with training images
571 filename = vpIoTools::createFilePath(opath, "xml_with_img");
572 vpIoTools::makeDirectory(filename);
573 filename = vpIoTools::createFilePath(filename, "test_save_in_xml_with_img.xml");
574 keyPoints.saveLearningData(filename, false, true);
575
576 // Test if save is ok
577 if (!vpIoTools::checkFilename(filename)) {
578 std::stringstream ss;
579 ss << "Problem when saving file=" << filename;
580 throw vpException(vpException::ioError, ss.str().c_str());
581 }
582
583 // Test if read is ok
584 vpKeyPoint read_keypoint3;
585 read_keypoint3.loadLearningData(filename, false);
586 trainKeyPoints_read.clear();
587 read_keypoint3.getTrainKeyPoints(trainKeyPoints_read);
588 trainDescriptors_read = read_keypoint3.getTrainDescriptors();
589
590 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
591 throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
592 "xml with train images saved !");
593 }
594
595 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
596 throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
597 "learning file saved in "
598 "xml with train images saved !");
599 }
600
601 // Save in xml without training images
602 filename = vpIoTools::createFilePath(opath, "xml_without_img");
603 vpIoTools::makeDirectory(filename);
604 filename = vpIoTools::createFilePath(filename, "test_save_in_xml_without_img.xml");
605 keyPoints.saveLearningData(filename, false, false);
606
607 // Test if save is ok
608 if (!vpIoTools::checkFilename(filename)) {
609 std::stringstream ss;
610 ss << "Problem when saving file=" << filename;
611 throw vpException(vpException::ioError, ss.str().c_str());
612 }
613
614 // Test if read is ok
615 vpKeyPoint read_keypoint4;
616 read_keypoint4.loadLearningData(filename, false);
617 trainKeyPoints_read.clear();
618 read_keypoint4.getTrainKeyPoints(trainKeyPoints_read);
619 trainDescriptors_read = read_keypoint4.getTrainDescriptors();
620
621 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
622 throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
623 "xml without train images saved !");
624 }
625
626 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
627 throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
628 "learning file saved in "
629 "xml without train images saved !");
630 }
631#endif
632 std::cout << "Saving / loading learning files with floating point descriptor are ok !" << std::endl;
633
634 // Test vpKeyPoint::reset()
635 vpKeyPoint keypoint_reset;
636
637 keypointName = "ORB";
638 std::cout << "Use " << keypointName << " as keypoints" << std::endl;
639 keypoint_reset.setDetector(keypointName);
640 keypoint_reset.setExtractor(keypointName);
641
642 keypoint_reset.buildReference(I);
643 std::cout << keypointName << " keypoints are detected" << std::endl;
644
645 // reset
646 keypoint_reset.reset();
647
648 keypointName = "SIFT";
649 std::cout << "Use " << keypointName << " as keypoints" << std::endl;
650 keypoint_reset.setDetector(keypointName);
651 keypoint_reset.setExtractor(keypointName);
652
653 keypoint_reset.buildReference(I);
654 std::cout << keypointName << " keypoints are detected" << std::endl;
655
656 std::vector<cv::KeyPoint> trainKeyPoints_reset;
657 keypoint_reset.getTrainKeyPoints(trainKeyPoints_reset);
658 std::cout << "Get descriptors" << std::endl;
659 cv::Mat trainDescriptors_reset = keypoint_reset.getTrainDescriptors();
660
661 // If reset is ok, we should get the same keypoints and the same descriptors
662 std::cout << "Compare keypoints" << std::endl;
663 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_reset)) {
664 throw vpException(vpException::fatalError, "Problem with vpKeyPoint::reset() and trainKeyPoints !");
665 }
666
667 std::cout << "Compare descriptors" << std::endl;
668 if (!compareDescriptors(trainDescriptors, trainDescriptors_reset)) {
669 throw vpException(vpException::fatalError, "Problem with vpKeyPoint::reset() and trainDescriptors !");
670 }
671
672 std::cout << "vpKeyPoint::reset() is ok with trainKeyPoints and trainDescriptors !" << std::endl;
673#endif // OpenCV != 4.5.4 on macOS
674 }
675#endif
676}
677
678int main(int argc, const char **argv)
679{
680 try {
681 std::string env_ipath;
682 std::string opt_opath;
683 std::string username;
684 std::string opath;
685
686 // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
687 // environment variable value
689
690 if (env_ipath.empty()) {
691 throw vpException(vpException::ioError, "Please set the VISP_INPUT_IMAGE_PATH environment variable value.");
692 }
693
694// Set the default output path
695#if defined(_WIN32)
696 opt_opath = "C:/temp";
697#else
698 opt_opath = "/tmp";
699#endif
700
701 // Get the user login name
702 vpIoTools::getUserName(username);
703
704 // Read the command line options
705 if (getOptions(argc, argv, opt_opath, username) == false) {
706 throw vpException(vpException::fatalError, "getOptions(argc, argv, opt_opath, username) == false");
707 }
708
709 // Get the option values
710 if (!opt_opath.empty()) {
711 opath = opt_opath;
712 }
713
714 // Append to the output path string, the login name of the user
715 opath = vpIoTools::createFilePath(opath, username);
716
717 {
719
720 std::cout << "-- Test on gray level images" << std::endl;
721 run_test(env_ipath, opath, I);
722 }
723
724 {
726
727 std::cout << "-- Test on color images" << std::endl;
728 run_test(env_ipath, opath, I);
729 }
730
731 }
732 catch (const vpException &e) {
733 std::cerr << e.what() << std::endl;
734 return EXIT_FAILURE;
735 }
736
737 std::cout << "Saving / loading learning files are ok !" << std::endl;
738 std::cout << "testKeyPoint-7 is ok !" << std::endl;
739 return EXIT_SUCCESS;
740}
741#else
742int main()
743{
744 std::cerr << "You need OpenCV library." << std::endl;
745
746 return EXIT_SUCCESS;
747}
748
749#endif
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ ioError
I/O error.
Definition vpException.h:67
@ fatalError
Fatal error.
Definition vpException.h:72
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition of the vpImage class member functions.
Definition vpImage.h:131
static std::string getViSPImagesDataPath()
static bool checkFilename(const std::string &filename)
static std::string getUserName()
static std::string createFilePath(const std::string &parent, const std::string &child)
static void makeDirectory(const std::string &dirname)
Class that allows keypoints 2D features detection (and descriptors extraction) and matching thanks to...
Definition vpKeyPoint.h:274
void getTrainKeyPoints(std::vector< cv::KeyPoint > &keyPoints) const
unsigned int buildReference(const vpImage< unsigned char > &I) VP_OVERRIDE
cv::Mat getTrainDescriptors() const
void setExtractor(const vpFeatureDescriptorType &extractorType)
void loadLearningData(const std::string &filename, bool binaryMode=false, bool append=false)
void saveLearningData(const std::string &filename, bool binaryMode=false, bool saveTrainingImages=true)
void setDetector(const vpFeatureDetectorType &detectorType)
static bool equal(double x, double y, double threshold=0.001)
Definition vpMath.h:470
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)