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