Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
testKeyPoint-7.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Test saving / loading learning files for vpKeyPoint class.
33  *
34  * Authors:
35  * Souriya Trinh
36  *
37  *****************************************************************************/
38 
39 #include <iomanip>
40 #include <iostream>
41 
42 #include <visp3/core/vpConfig.h>
43 
44 #if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020301)
45 
46 #include <visp3/core/vpException.h>
47 #include <visp3/core/vpImage.h>
48 #include <visp3/core/vpIoTools.h>
49 #include <visp3/io/vpImageIo.h>
50 #include <visp3/io/vpParseArgv.h>
51 #include <visp3/vision/vpKeyPoint.h>
52 
53 // List of allowed command line options
54 #define GETOPTARGS "cdo:h"
55 
64 void usage(const char *name, const char *badparam, const std::string &opath, const std::string &user)
65 {
66  fprintf(stdout, "\n\
67 Test save / load learning files for vpKeyPoint class.\n\
68 \n\
69 SYNOPSIS\n\
70  %s [-c] [-d] [-h]\n", name);
71 
72  fprintf(stdout, "\n\
73 OPTIONS: \n\
74 \n\
75  -o <output image path> %s\n\
76  Set image output path.\n\
77  From this directory, creates the \"%s\"\n\
78  subdirectory depending on the username, where \n\
79  learning files will be written.\n\
80 \n\
81  -h\n\
82  Print the help.\n", opath.c_str(), user.c_str());
83 
84  if (badparam)
85  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
86 }
87 
99 bool getOptions(int argc, const char **argv, std::string &opath, const std::string &user)
100 {
101  const char *optarg_;
102  int c;
103  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
104 
105  switch (c) {
106  case 'c':
107  break; // not used, to avoid error with default arguments ctest
108  case 'd':
109  break; // not used, to avoid error with default arguments ctest
110  case 'o':
111  opath = optarg_;
112  break;
113  case 'h':
114  usage(argv[0], NULL, opath, user);
115  return false;
116  break;
117 
118  default:
119  usage(argv[0], optarg_, opath, user);
120  return false;
121  break;
122  return false;
123  break;
124  }
125  }
126 
127  if ((c == 1) || (c == -1)) {
128  // standalone param or error
129  usage(argv[0], NULL, opath, user);
130  std::cerr << "ERROR: " << std::endl;
131  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
132  return false;
133  }
134 
135  return true;
136 }
137 
146 bool compareKeyPoints(const std::vector<cv::KeyPoint> &keypoints1, const std::vector<cv::KeyPoint> &keypoints2)
147 {
148  if (keypoints1.size() != keypoints2.size()) {
149  return false;
150  }
151 
152  for (size_t cpt = 0; cpt < keypoints1.size(); cpt++) {
153  if (!vpMath::equal(keypoints1[cpt].angle, keypoints2[cpt].angle, std::numeric_limits<float>::epsilon())) {
154  std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].angle=" << keypoints1[cpt].angle
155  << " ; keypoints2[cpt].angle=" << keypoints2[cpt].angle << std::endl;
156  return false;
157  }
158 
159  if (keypoints1[cpt].class_id != keypoints2[cpt].class_id) {
160  std::cerr << "keypoints1[cpt].class_id=" << keypoints1[cpt].class_id
161  << " ; keypoints2[cpt].class_id=" << keypoints2[cpt].class_id << std::endl;
162  return false;
163  }
164 
165  if (keypoints1[cpt].octave != keypoints2[cpt].octave) {
166  std::cerr << "keypoints1[cpt].octave=" << keypoints1[cpt].octave
167  << " ; keypoints2[cpt].octave=" << keypoints2[cpt].octave << std::endl;
168  return false;
169  }
170 
171  if (!vpMath::equal(keypoints1[cpt].pt.x, keypoints2[cpt].pt.x, std::numeric_limits<float>::epsilon())) {
172  std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].pt.x=" << keypoints1[cpt].pt.x
173  << " ; keypoints2[cpt].pt.x=" << keypoints2[cpt].pt.x << std::endl;
174  return false;
175  }
176 
177  if (!vpMath::equal(keypoints1[cpt].pt.y, keypoints2[cpt].pt.y, std::numeric_limits<float>::epsilon())) {
178  std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].pt.y=" << keypoints1[cpt].pt.y
179  << " ; keypoints2[cpt].pt.y=" << keypoints2[cpt].pt.y << std::endl;
180  return false;
181  }
182 
183  if (!vpMath::equal(keypoints1[cpt].response, keypoints2[cpt].response, std::numeric_limits<float>::epsilon())) {
184  std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].response=" << keypoints1[cpt].response
185  << " ; keypoints2[cpt].response=" << keypoints2[cpt].response << std::endl;
186  return false;
187  }
188 
189  if (!vpMath::equal(keypoints1[cpt].size, keypoints2[cpt].size, std::numeric_limits<float>::epsilon())) {
190  std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].size=" << keypoints1[cpt].size
191  << " ; keypoints2[cpt].size=" << keypoints2[cpt].size << std::endl;
192  return false;
193  }
194  }
195 
196  return true;
197 }
198 
207 bool compareDescriptors(const cv::Mat &descriptors1, const cv::Mat &descriptors2)
208 {
209  if (descriptors1.rows != descriptors2.rows || descriptors1.cols != descriptors2.cols ||
210  descriptors1.type() != descriptors2.type()) {
211  return false;
212  }
213 
214  for (int i = 0; i < descriptors1.rows; i++) {
215  for (int j = 0; j < descriptors1.cols; j++) {
216  switch (descriptors1.type()) {
217  case CV_8U:
218  if (descriptors1.at<unsigned char>(i, j) != descriptors2.at<unsigned char>(i, j)) {
219  std::cerr << "descriptors1.at<unsigned char>(i,j)=" << descriptors1.at<unsigned char>(i, j)
220  << " ; descriptors2.at<unsigned char>(i,j)=" << descriptors2.at<unsigned char>(i, j) << std::endl;
221  return false;
222  }
223  break;
224 
225  case CV_8S:
226  if (descriptors1.at<char>(i, j) != descriptors2.at<char>(i, j)) {
227  std::cerr << "descriptors1.at<char>(i,j)=" << descriptors1.at<char>(i, j)
228  << " ; descriptors2.at<char>(i,j)=" << descriptors2.at<char>(i, j) << std::endl;
229  return false;
230  }
231  break;
232 
233  case CV_16U:
234  if (descriptors1.at<unsigned short>(i, j) != descriptors2.at<unsigned short>(i, j)) {
235  std::cerr << "descriptors1.at<unsigned short>(i,j)=" << descriptors1.at<unsigned short>(i, j)
236  << " ; descriptors2.at<unsigned short>(i,j)=" << descriptors2.at<unsigned short>(i, j) << std::endl;
237  return false;
238  }
239  break;
240 
241  case CV_16S:
242  if (descriptors1.at<short>(i, j) != descriptors2.at<short>(i, j)) {
243  std::cerr << "descriptors1.at<short>(i,j)=" << descriptors1.at<short>(i, j)
244  << " ; descriptors2.at<short>(i,j)=" << descriptors2.at<short>(i, j) << std::endl;
245  return false;
246  }
247  break;
248 
249  case CV_32S:
250  if (descriptors1.at<int>(i, j) != descriptors2.at<int>(i, j)) {
251  std::cerr << "descriptors1.at<int>(i,j)=" << descriptors1.at<int>(i, j)
252  << " ; descriptors2.at<int>(i,j)=" << descriptors2.at<int>(i, j) << std::endl;
253  return false;
254  }
255  break;
256 
257  case CV_32F:
258  if (!vpMath::equal(descriptors1.at<float>(i, j), descriptors2.at<float>(i, j),
259  std::numeric_limits<float>::epsilon())) {
260  std::cerr << std::fixed << std::setprecision(9)
261  << "descriptors1.at<float>(i,j)=" << descriptors1.at<float>(i, j)
262  << " ; descriptors2.at<float>(i,j)=" << descriptors2.at<float>(i, j) << std::endl;
263  return false;
264  }
265  break;
266 
267  case CV_64F:
268  if (!vpMath::equal(descriptors1.at<double>(i, j), descriptors2.at<double>(i, j),
269  std::numeric_limits<double>::epsilon())) {
270  std::cerr << std::fixed << std::setprecision(17)
271  << "descriptors1.at<double>(i,j)=" << descriptors1.at<double>(i, j)
272  << " ; descriptors2.at<double>(i,j)=" << descriptors2.at<double>(i, j) << std::endl;
273  return false;
274  }
275  break;
276 
277  default:
278  return false;
279  break;
280  }
281  }
282  }
283 
284  return true;
285 }
286 
287 template<typename Type>
288 void run_test(const std::string &env_ipath, const std::string &opath, vpImage<Type> &I)
289 {
290  std::string filename;
291  // Set the path location of the image sequence
292  std::string dirname = vpIoTools::createFilePath(env_ipath, "Klimt");
293 
294  // Build the name of the image files
295  std::string img_filename = vpIoTools::createFilePath(dirname, "/Klimt.ppm");
296  vpImageIo::read(I, img_filename);
297 
298  vpKeyPoint keyPoints;
299 
300  // Test with binary descriptor
301  {
302  std::string keypointName = "ORB";
303  keyPoints.setDetector(keypointName);
304  keyPoints.setExtractor(keypointName);
305 
306  keyPoints.buildReference(I);
307 
308  std::vector<cv::KeyPoint> trainKeyPoints;
309  keyPoints.getTrainKeyPoints(trainKeyPoints);
310  cv::Mat trainDescriptors = keyPoints.getTrainDescriptors();
311  if (trainKeyPoints.empty() || trainDescriptors.empty() || (int)trainKeyPoints.size() != trainDescriptors.rows) {
312  throw vpException(vpException::fatalError, "Problem when detecting "
313  "keypoints or when "
314  "computing descriptors !");
315  }
316 
317  // Save in binary with training images
318  filename = vpIoTools::createFilePath(opath, "bin_with_img");
319  vpIoTools::makeDirectory(filename);
320  filename = vpIoTools::createFilePath(filename, "test_save_in_bin_with_img.bin");
321  keyPoints.saveLearningData(filename, true, true);
322 
323  // Test if save is ok
324  if (!vpIoTools::checkFilename(filename)) {
325  std::stringstream ss;
326  ss << "Problem when saving file=" << filename;
327  throw vpException(vpException::ioError, ss.str().c_str());
328  }
329 
330  // Test if read is ok
331  vpKeyPoint read_keypoint1;
332  read_keypoint1.loadLearningData(filename, true);
333  std::vector<cv::KeyPoint> trainKeyPoints_read;
334  read_keypoint1.getTrainKeyPoints(trainKeyPoints_read);
335  cv::Mat trainDescriptors_read = read_keypoint1.getTrainDescriptors();
336 
337  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
338  throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved "
339  "in binary with train images saved !");
340  }
341 
342  if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
343  throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
344  "learning file saved in "
345  "binary with train images saved !");
346  }
347 
348  // Save in binary with no training images
349  filename = vpIoTools::createFilePath(opath, "bin_without_img");
350  vpIoTools::makeDirectory(filename);
351  filename = vpIoTools::createFilePath(filename, "test_save_in_bin_without_img.bin");
352  keyPoints.saveLearningData(filename, true, false);
353 
354  // Test if save is ok
355  if (!vpIoTools::checkFilename(filename)) {
356  std::stringstream ss;
357  ss << "Problem when saving file=" << filename;
358  throw vpException(vpException::ioError, ss.str().c_str());
359  }
360 
361  // Test if read is ok
362  vpKeyPoint read_keypoint2;
363  read_keypoint2.loadLearningData(filename, true);
364  trainKeyPoints_read.clear();
365  read_keypoint2.getTrainKeyPoints(trainKeyPoints_read);
366  trainDescriptors_read = read_keypoint2.getTrainDescriptors();
367 
368  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
369  throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
370  "binary without train images !");
371  }
372 
373  if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
374  throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
375  "learning file saved in "
376  "binary without train images !");
377  }
378 
379  // Save in xml with training images
380  filename = vpIoTools::createFilePath(opath, "xml_with_img");
381  vpIoTools::makeDirectory(filename);
382  filename = vpIoTools::createFilePath(filename, "test_save_in_xml_with_img.xml");
383  keyPoints.saveLearningData(filename, false, true);
384 
385  // Test if save is ok
386  if (!vpIoTools::checkFilename(filename)) {
387  std::stringstream ss;
388  ss << "Problem when saving file=" << filename;
389  throw vpException(vpException::ioError, ss.str().c_str());
390  }
391 
392  // Test if read is ok
393  vpKeyPoint read_keypoint3;
394  read_keypoint3.loadLearningData(filename, false);
395  trainKeyPoints_read.clear();
396  read_keypoint3.getTrainKeyPoints(trainKeyPoints_read);
397  trainDescriptors_read = read_keypoint3.getTrainDescriptors();
398 
399  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
400  throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
401  "xml with train images saved !");
402  }
403 
404  if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
405  throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
406  "learning file saved in "
407  "xml with train images saved !");
408  }
409 
410  // Save in xml without training images
411  filename = vpIoTools::createFilePath(opath, "xml_without_img");
412  vpIoTools::makeDirectory(filename);
413  filename = vpIoTools::createFilePath(filename, "test_save_in_xml_without_img.xml");
414  keyPoints.saveLearningData(filename, false, false);
415 
416  // Test if save is ok
417  if (!vpIoTools::checkFilename(filename)) {
418  std::stringstream ss;
419  ss << "Problem when saving file=" << filename;
420  throw vpException(vpException::ioError, ss.str().c_str());
421  }
422 
423  // Test if read is ok
424  vpKeyPoint read_keypoint4;
425  read_keypoint4.loadLearningData(filename, false);
426  trainKeyPoints_read.clear();
427  read_keypoint4.getTrainKeyPoints(trainKeyPoints_read);
428  trainDescriptors_read = read_keypoint4.getTrainDescriptors();
429 
430  if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
431  throw vpException(vpException::fatalError, "Problem with trainKeyPoints when reading learning file saved in "
432  "xml without train images saved !");
433  }
434 
435  if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
436  throw vpException(vpException::fatalError, "Problem with trainDescriptors when reading "
437  "learning file saved in "
438  "xml without train images saved !");
439  }
440 
441  std::cout << "Saving / loading learning files with binary descriptor are ok !" << std::endl;
442  }
443 
444 
445 // Test with floating point descriptor
446 #if defined(VISP_HAVE_OPENCV_NONFREE) || \
447  ((VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(VISP_HAVE_OPENCV_XFEATURES2D) || \
448  (VISP_HAVE_OPENCV_VERSION >= 0x030411 && CV_MAJOR_VERSION < 4) || (VISP_HAVE_OPENCV_VERSION >= 0x040400))
449  {
450 #if !((VISP_HAVE_OPENCV_VERSION == 0x040504) && (defined(__APPLE__) && defined(__MACH__))) // OpenCV != 4.5.4 on macOS
451  std::string keypointName = "SIFT"; // SIFT is known unstable with OpenCV 4.5.4
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 
638 int 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
648  env_ipath = vpIoTools::getViSPImagesDataPath();
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  {
685  vpImage<vpRGBa> I;
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 -1;
694  }
695 
696  std::cout << "Saving / loading learning files are ok !" << std::endl;
697  std::cout << "testKeyPoint-7 is ok !" << std::endl;
698  return 0;
699 }
700 #else
701 int main()
702 {
703  std::cerr << "You need OpenCV library." << std::endl;
704 
705  return 0;
706 }
707 
708 #endif
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:149
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:570
void loadLearningData(const std::string &filename, bool binaryMode=false, bool append=false)
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1365
static bool equal(double x, double y, double s=0.001)
Definition: vpMath.h:295
error that can be emited by ViSP classes.
Definition: vpException.h:71
cv::Mat getTrainDescriptors() const
Definition: vpKeyPoint.h:688
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1670
void getTrainKeyPoints(std::vector< cv::KeyPoint > &keyPoints) const
static std::string getUserName()
Definition: vpIoTools.cpp:316
void setDetector(const vpFeatureDetectorType &detectorType)
Definition: vpKeyPoint.h:782
unsigned int buildReference(const vpImage< unsigned char > &I)
Definition: vpKeyPoint.cpp:238
void saveLearningData(const std::string &filename, bool binaryMode=false, bool saveTrainingImages=true)
const char * what() const
Class that allows keypoints detection (and descriptors extraction) and matching thanks to OpenCV libr...
Definition: vpKeyPoint.h:222
static bool checkFilename(const std::string &filename)
Definition: vpIoTools.cpp:802
void reset()
void setExtractor(const vpFeatureDescriptorType &extractorType)
Definition: vpKeyPoint.h:840
Definition of the vpImage class member functions.
Definition: vpImage.h:126