37 #include <visp3/core/vpConfig.h>
39 #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_FEATURES2D) && defined(HAVE_OPENCV_VIDEO)
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>
49 #define GETOPTARGS "cdo:h"
59 void usage(
const char *name,
const char *badparam,
const std::string &opath,
const std::string &user)
62 Test save / load learning files for vpKeyPoint class.\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\
79 opath.c_str(), user.c_str());
82 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
96 bool getOptions(
int argc,
const char **argv, std::string &opath,
const std::string &user)
111 usage(argv[0],
nullptr, opath, user);
116 usage(argv[0], optarg_, opath, user);
124 if ((c == 1) || (c == -1)) {
126 usage(argv[0],
nullptr, opath, user);
127 std::cerr <<
"ERROR: " << std::endl;
128 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
143 bool compareKeyPoints(
const std::vector<cv::KeyPoint> &keypoints1,
const std::vector<cv::KeyPoint> &keypoints2)
145 if (keypoints1.size() != keypoints2.size()) {
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;
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;
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;
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;
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;
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;
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;
204 bool compareDescriptors(
const cv::Mat &descriptors1,
const cv::Mat &descriptors2)
206 if (descriptors1.rows != descriptors2.rows || descriptors1.cols != descriptors2.cols ||
207 descriptors1.type() != descriptors2.type()) {
211 for (
int i = 0; i < descriptors1.rows; i++) {
212 for (
int j = 0; j < descriptors1.cols; j++) {
213 switch (descriptors1.type()) {
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;
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;
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;
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;
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;
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;
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;
284 template <
typename Type>
void run_test(
const std::string &env_ipath,
const std::string &opath,
vpImage<Type> &I)
286 std::string filename;
298 std::string keypointName =
"ORB";
304 std::vector<cv::KeyPoint> trainKeyPoints;
307 if (trainKeyPoints.empty() || trainDescriptors.empty() || (
int)trainKeyPoints.size() != trainDescriptors.rows) {
310 "computing descriptors !");
321 std::stringstream ss;
322 ss <<
"Problem when saving file=" << filename;
331 std::vector<cv::KeyPoint> trainKeyPoints_read;
335 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
337 "in binary with train images saved !");
340 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
342 "learning file saved in "
343 "binary with train images saved !");
354 std::stringstream ss;
355 ss <<
"Problem when saving file=" << filename;
362 trainKeyPoints_read.clear();
366 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
368 "binary without train images !");
371 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
373 "learning file saved in "
374 "binary without train images !");
377 #if defined(VISP_HAVE_PUGYXML)
386 std::stringstream ss;
387 ss <<
"Problem when saving file=" << filename;
394 trainKeyPoints_read.clear();
398 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
400 "xml with train images saved !");
403 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
405 "learning file saved in "
406 "xml with train images saved !");
417 std::stringstream ss;
418 ss <<
"Problem when saving file=" << filename;
425 trainKeyPoints_read.clear();
429 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
431 "xml without train images saved !");
434 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
436 "learning file saved in "
437 "xml without train images saved !");
440 std::cout <<
"Saving / loading learning files with binary descriptor are ok !" << std::endl;
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))
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__))
455 std::string keypointName =
"SIFT";
461 std::vector<cv::KeyPoint> trainKeyPoints;
464 if (trainKeyPoints.empty() || trainDescriptors.empty() || (
int)trainKeyPoints.size() != trainDescriptors.rows) {
466 "computing descriptors (SIFT) !");
477 std::stringstream ss;
478 ss <<
"Problem when saving file=" << filename;
485 std::vector<cv::KeyPoint> trainKeyPoints_read;
489 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
491 "binary with train images saved !");
494 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
496 "learning file saved in "
497 "binary with train images saved !");
508 std::stringstream ss;
509 ss <<
"Problem when saving file=" << filename;
516 trainKeyPoints_read.clear();
520 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
522 "binary without train images saved !");
525 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
527 "learning file saved in "
528 "binary without train images saved !");
531 #if defined(VISP_HAVE_PUGYXML)
540 std::stringstream ss;
541 ss <<
"Problem when saving file=" << filename;
548 trainKeyPoints_read.clear();
552 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
554 "xml with train images saved !");
557 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
559 "learning file saved in "
560 "xml with train images saved !");
571 std::stringstream ss;
572 ss <<
"Problem when saving file=" << filename;
579 trainKeyPoints_read.clear();
583 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
585 "xml without train images saved !");
588 if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
590 "learning file saved in "
591 "xml without train images saved !");
594 std::cout <<
"Saving / loading learning files with floating point descriptor are ok !" << std::endl;
599 keypointName =
"ORB";
606 keypoint_reset.
reset();
608 keypointName =
"SIFT";
614 std::vector<cv::KeyPoint> trainKeyPoints_reset;
620 if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_reset)) {
624 if (!compareDescriptors(trainDescriptors, trainDescriptors_reset)) {
628 std::cout <<
"vpKeyPoint::reset() is ok with trainKeyPoints and "
641 int main(
int argc,
const char **argv)
644 std::string env_ipath;
645 std::string opt_opath;
646 std::string username;
653 if (env_ipath.empty()) {
659 opt_opath =
"C:/temp";
668 if (getOptions(argc, argv, opt_opath, username) ==
false) {
673 if (!opt_opath.empty()) {
683 std::cout <<
"-- Test on gray level images" << std::endl;
684 run_test(env_ipath, opath, I);
690 std::cout <<
"-- Test on color images" << std::endl;
691 run_test(env_ipath, opath, I);
696 std::cerr << e.
what() << std::endl;
700 std::cout <<
"Saving / loading learning files are ok !" << std::endl;
701 std::cout <<
"testKeyPoint-7 is ok !" << std::endl;
707 std::cerr <<
"You need OpenCV library." << std::endl;
error that can be emitted by ViSP classes.
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.
Class that allows keypoints detection (and descriptors extraction) and matching thanks to OpenCV libr...
void getTrainKeyPoints(std::vector< cv::KeyPoint > &keyPoints) const
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)
unsigned int buildReference(const vpImage< unsigned char > &I)
static bool equal(double x, double y, double threshold=0.001)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)