Visual Servoing Platform  version 3.6.1 under development (2024-05-13)
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 
59 void usage(const char *name, const char *badparam, const std::string &opath, const std::string &user)
60 {
61  fprintf(stdout, "\n\
62 Test save / load learning files for vpKeyPoint class.\n\
63 \n\
64 SYNOPSIS\n\
65  %s [-c] [-d] [-h]\n",
66  name);
67 
68  fprintf(stdout, "\n\
69 OPTIONS: \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 
96 bool 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], nullptr, 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], nullptr, 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 
143 bool 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 
204 bool 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 
284 template <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 
329  read_keypoint1.loadLearningData(filename, true);
330 
331  std::vector<cv::KeyPoint> trainKeyPoints_read;
332  read_keypoint1.getTrainKeyPoints(trainKeyPoints_read);
333  cv::Mat trainDescriptors_read = read_keypoint1.getTrainDescriptors();
334 
335  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
336  throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved "
337  "in binary with train images saved !");
338  }
339 
340  if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
341  throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
342  "learning file saved in "
343  "binary with train images saved !");
344  }
345 
346  // Save in binary without training images
347  filename = vpIoTools::createFilePath(opath, "bin_without_img");
348  vpIoTools::makeDirectory(filename);
349  filename = vpIoTools::createFilePath(filename, "test_save_in_bin_without_img.bin");
350  keyPoints.saveLearningData(filename, true, false);
351 
352  // Test if save is ok
353  if (!vpIoTools::checkFilename(filename)) {
354  std::stringstream ss;
355  ss << "Problem when saving file=" << filename;
356  throw vpException(vpException::ioError, ss.str().c_str());
357  }
358 
359  // Test if read is ok
360  vpKeyPoint read_keypoint2;
361  read_keypoint2.loadLearningData(filename, true);
362  trainKeyPoints_read.clear();
363  read_keypoint2.getTrainKeyPoints(trainKeyPoints_read);
364  trainDescriptors_read = read_keypoint2.getTrainDescriptors();
365 
366  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
367  throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
368  "binary without train images !");
369  }
370 
371  if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
372  throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
373  "learning file saved in "
374  "binary without train images !");
375  }
376 
377 #if defined(VISP_HAVE_PUGYXML)
378  // Save in xml with training images
379  filename = vpIoTools::createFilePath(opath, "xml_with_img");
380  vpIoTools::makeDirectory(filename);
381  filename = vpIoTools::createFilePath(filename, "test_save_in_xml_with_img.xml");
382  keyPoints.saveLearningData(filename, false, true);
383 
384  // Test if save is ok
385  if (!vpIoTools::checkFilename(filename)) {
386  std::stringstream ss;
387  ss << "Problem when saving file=" << filename;
388  throw vpException(vpException::ioError, ss.str().c_str());
389  }
390 
391  // Test if read is ok
392  vpKeyPoint read_keypoint3;
393  read_keypoint3.loadLearningData(filename, false);
394  trainKeyPoints_read.clear();
395  read_keypoint3.getTrainKeyPoints(trainKeyPoints_read);
396  trainDescriptors_read = read_keypoint3.getTrainDescriptors();
397 
398  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
399  throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
400  "xml with train images saved !");
401  }
402 
403  if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
404  throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
405  "learning file saved in "
406  "xml with train images saved !");
407  }
408 
409  // Save in xml without training images
410  filename = vpIoTools::createFilePath(opath, "xml_without_img");
411  vpIoTools::makeDirectory(filename);
412  filename = vpIoTools::createFilePath(filename, "test_save_in_xml_without_img.xml");
413  keyPoints.saveLearningData(filename, false, false);
414 
415  // Test if save is ok
416  if (!vpIoTools::checkFilename(filename)) {
417  std::stringstream ss;
418  ss << "Problem when saving file=" << filename;
419  throw vpException(vpException::ioError, ss.str().c_str());
420  }
421 
422  // Test if read is ok
423  vpKeyPoint read_keypoint4;
424  read_keypoint4.loadLearningData(filename, false);
425  trainKeyPoints_read.clear();
426  read_keypoint4.getTrainKeyPoints(trainKeyPoints_read);
427  trainDescriptors_read = read_keypoint4.getTrainDescriptors();
428 
429  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
430  throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
431  "xml without train images saved !");
432  }
433 
434  if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
435  throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
436  "learning file saved in "
437  "xml without train images saved !");
438  }
439 #endif
440  std::cout << "Saving / loading learning files with binary descriptor are ok !" << std::endl;
441  }
442 
443 // Test with floating point descriptor
444 #if defined(VISP_HAVE_OPENCV_NONFREE) || \
445  ((VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(VISP_HAVE_OPENCV_XFEATURES2D) || \
446  (VISP_HAVE_OPENCV_VERSION >= 0x030411 && CV_MAJOR_VERSION < 4) || (VISP_HAVE_OPENCV_VERSION >= 0x040400))
447  {
448 #if (VISP_HAVE_OPENCV_VERSION != 0x040504) && (VISP_HAVE_OPENCV_VERSION != 0x040505) && \
449  (VISP_HAVE_OPENCV_VERSION != 0x040600) && (VISP_HAVE_OPENCV_VERSION != 0x040700) && \
450  (VISP_HAVE_OPENCV_VERSION != 0x040900) && \
451  (defined(__APPLE__) && defined(__MACH__))
452  // SIFT is known to be unstable with OpenCV 4.5.4 and 4.5.5 on macOS (see #1048)
453  // Same for OpenCV 4.6.0 (see #1106) where it produces an Illegal Instruction error when OpenCV 4.6.0 is
454  // installed with brew. It seems working when OpenCV is build from source
455  std::string keypointName = "SIFT";
456  keyPoints.setDetector(keypointName);
457  keyPoints.setExtractor(keypointName);
458 
459  keyPoints.buildReference(I);
460 
461  std::vector<cv::KeyPoint> trainKeyPoints;
462  keyPoints.getTrainKeyPoints(trainKeyPoints);
463  cv::Mat trainDescriptors = keyPoints.getTrainDescriptors();
464  if (trainKeyPoints.empty() || trainDescriptors.empty() || (int)trainKeyPoints.size() != trainDescriptors.rows) {
465  throw vpException(vpException::fatalError, "Problem when detecting keypoints or when "
466  "computing descriptors (SIFT) !");
467  }
468 
469  // Save in binary with training images
470  filename = vpIoTools::createFilePath(opath, "bin_with_img");
471  vpIoTools::makeDirectory(filename);
472  filename = vpIoTools::createFilePath(filename, "test_save_in_bin_with_img.bin");
473  keyPoints.saveLearningData(filename, true, true);
474 
475  // Test if save is ok
476  if (!vpIoTools::checkFilename(filename)) {
477  std::stringstream ss;
478  ss << "Problem when saving file=" << filename;
479  throw vpException(vpException::ioError, ss.str().c_str());
480  }
481 
482  // Test if read is ok
483  vpKeyPoint read_keypoint1;
484  read_keypoint1.loadLearningData(filename, true);
485  std::vector<cv::KeyPoint> trainKeyPoints_read;
486  read_keypoint1.getTrainKeyPoints(trainKeyPoints_read);
487  cv::Mat trainDescriptors_read = read_keypoint1.getTrainDescriptors();
488 
489  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
490  throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
491  "binary with train images saved !");
492  }
493 
494  if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
495  throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
496  "learning file saved in "
497  "binary with train images saved !");
498  }
499 
500  // Save in binary with no training images
501  filename = vpIoTools::createFilePath(opath, "bin_without_img");
502  vpIoTools::makeDirectory(filename);
503  filename = vpIoTools::createFilePath(filename, "test_save_in_bin_without_img.bin");
504  keyPoints.saveLearningData(filename, true, false);
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_keypoint2;
515  read_keypoint2.loadLearningData(filename, true);
516  trainKeyPoints_read.clear();
517  read_keypoint2.getTrainKeyPoints(trainKeyPoints_read);
518  trainDescriptors_read = read_keypoint2.getTrainDescriptors();
519 
520  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
521  throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
522  "binary without train images saved !");
523  }
524 
525  if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
526  throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
527  "learning file saved in "
528  "binary without train images saved !");
529  }
530 
531 #if defined(VISP_HAVE_PUGYXML)
532  // Save in xml with training images
533  filename = vpIoTools::createFilePath(opath, "xml_with_img");
534  vpIoTools::makeDirectory(filename);
535  filename = vpIoTools::createFilePath(filename, "test_save_in_xml_with_img.xml");
536  keyPoints.saveLearningData(filename, false, true);
537 
538  // Test if save is ok
539  if (!vpIoTools::checkFilename(filename)) {
540  std::stringstream ss;
541  ss << "Problem when saving file=" << filename;
542  throw vpException(vpException::ioError, ss.str().c_str());
543  }
544 
545  // Test if read is ok
546  vpKeyPoint read_keypoint3;
547  read_keypoint3.loadLearningData(filename, false);
548  trainKeyPoints_read.clear();
549  read_keypoint3.getTrainKeyPoints(trainKeyPoints_read);
550  trainDescriptors_read = read_keypoint3.getTrainDescriptors();
551 
552  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
553  throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
554  "xml with train images saved !");
555  }
556 
557  if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
558  throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
559  "learning file saved in "
560  "xml with train images saved !");
561  }
562 
563  // Save in xml without training images
564  filename = vpIoTools::createFilePath(opath, "xml_without_img");
565  vpIoTools::makeDirectory(filename);
566  filename = vpIoTools::createFilePath(filename, "test_save_in_xml_without_img.xml");
567  keyPoints.saveLearningData(filename, false, false);
568 
569  // Test if save is ok
570  if (!vpIoTools::checkFilename(filename)) {
571  std::stringstream ss;
572  ss << "Problem when saving file=" << filename;
573  throw vpException(vpException::ioError, ss.str().c_str());
574  }
575 
576  // Test if read is ok
577  vpKeyPoint read_keypoint4;
578  read_keypoint4.loadLearningData(filename, false);
579  trainKeyPoints_read.clear();
580  read_keypoint4.getTrainKeyPoints(trainKeyPoints_read);
581  trainDescriptors_read = read_keypoint4.getTrainDescriptors();
582 
583  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
584  throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
585  "xml without train images saved !");
586  }
587 
588  if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
589  throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
590  "learning file saved in "
591  "xml without train images saved !");
592  }
593 #endif
594  std::cout << "Saving / loading learning files with floating point descriptor are ok !" << std::endl;
595 
596  // Test vpKeyPoint::reset()
597  vpKeyPoint keypoint_reset;
598 
599  keypointName = "ORB";
600  keypoint_reset.setDetector(keypointName);
601  keypoint_reset.setExtractor(keypointName);
602 
603  keypoint_reset.buildReference(I);
604 
605  // reset
606  keypoint_reset.reset();
607 
608  keypointName = "SIFT";
609  keypoint_reset.setDetector(keypointName);
610  keypoint_reset.setExtractor(keypointName);
611 
612  keypoint_reset.buildReference(I);
613 
614  std::vector<cv::KeyPoint> trainKeyPoints_reset;
615  keypoint_reset.getTrainKeyPoints(trainKeyPoints_reset);
616  cv::Mat trainDescriptors_reset = keypoint_reset.getTrainDescriptors();
617 
618  // If reset is ok, we should get the same keypoints and the same
619  // descriptors
620  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_reset)) {
621  throw vpException(vpException::fatalError, "Problem with vpKeyPoint::reset() and trainKeyPoints !");
622  }
623 
624  if (!compareDescriptors(trainDescriptors, trainDescriptors_reset)) {
625  throw vpException(vpException::fatalError, "Problem with vpKeyPoint::reset() and trainDescriptors !");
626  }
627 
628  std::cout << "vpKeyPoint::reset() is ok with trainKeyPoints and "
629  "trainDescriptors !"
630  << std::endl;
631 #endif // OpenCV != 4.5.4 on macOS
632  }
633 #endif
634 }
635 
641 int main(int argc, const char **argv)
642 {
643  try {
644  std::string env_ipath;
645  std::string opt_opath;
646  std::string username;
647  std::string opath;
648 
649  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
650  // environment variable value
651  env_ipath = vpIoTools::getViSPImagesDataPath();
652 
653  if (env_ipath.empty()) {
654  throw vpException(vpException::ioError, "Please set the VISP_INPUT_IMAGE_PATH environment variable value.");
655  }
656 
657 // Set the default output path
658 #if defined(_WIN32)
659  opt_opath = "C:/temp";
660 #else
661  opt_opath = "/tmp";
662 #endif
663 
664  // Get the user login name
665  vpIoTools::getUserName(username);
666 
667  // Read the command line options
668  if (getOptions(argc, argv, opt_opath, username) == false) {
669  throw vpException(vpException::fatalError, "getOptions(argc, argv, opt_opath, username) == false");
670  }
671 
672  // Get the option values
673  if (!opt_opath.empty()) {
674  opath = opt_opath;
675  }
676 
677  // Append to the output path string, the login name of the user
678  opath = vpIoTools::createFilePath(opath, username);
679 
680  {
682 
683  std::cout << "-- Test on gray level images" << std::endl;
684  run_test(env_ipath, opath, I);
685  }
686 
687  {
688  vpImage<vpRGBa> I;
689 
690  std::cout << "-- Test on color images" << std::endl;
691  run_test(env_ipath, opath, I);
692  }
693 
694  }
695  catch (const vpException &e) {
696  std::cerr << e.what() << std::endl;
697  return EXIT_FAILURE;
698  }
699 
700  std::cout << "Saving / loading learning files are ok !" << std::endl;
701  std::cout << "testKeyPoint-7 is ok !" << std::endl;
702  return EXIT_SUCCESS;
703 }
704 #else
705 int main()
706 {
707  std::cerr << "You need OpenCV library." << std::endl;
708 
709  return EXIT_SUCCESS;
710 }
711 
712 #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
Definition: vpException.cpp:70
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:143
Definition of the vpImage class member functions.
Definition: vpImage.h:69
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1832
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:1213
static std::string getUserName()
Definition: vpIoTools.cpp:725
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:2195
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:981
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:1223
void setExtractor(const vpFeatureDescriptorType &extractorType)
Definition: vpKeyPoint.h:1624
void reset()
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:1566
unsigned int buildReference(const vpImage< unsigned char > &I)
Definition: vpKeyPoint.cpp:189
static bool equal(double x, double y, double threshold=0.001)
Definition: vpMath.h:449
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69