41 #include <visp3/core/vpConfig.h>
43 #if defined(VISP_HAVE_OPENCV) && (VISP_HAVE_OPENCV_VERSION >= 0x020301)
45 #include <visp3/core/vpImage.h>
46 #include <visp3/io/vpImageIo.h>
47 #include <visp3/core/vpIoTools.h>
48 #include <visp3/io/vpParseArgv.h>
49 #include <visp3/vision/vpKeyPoint.h>
50 #include <visp3/core/vpException.h>
53 #define GETOPTARGS "cdo:h"
55 void usage(
const char *name,
const char *badparam, std::string opath, std::string user);
56 bool getOptions(
int argc,
const char **argv, std::string &opath, std::string user);
66 void usage(
const char *name,
const char *badparam, std::string opath, std::string user)
69 Test save / load learning files for vpKeyPoint class.\n\
72 %s [-c] [-d] [-h]\n", name);
77 -o <output image path> %s\n\
78 Set image output path.\n\
79 From this directory, creates the \"%s\"\n\
80 subdirectory depending on the username, where \n\
81 learning files will be written.\n\
85 opath.c_str(), user.c_str());
88 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
102 bool getOptions(
int argc,
const char **argv, std::string &opath, std::string user)
111 case 'o': opath = optarg_;
break;
112 case 'h': usage(argv[0], NULL, opath, user);
return false;
break;
115 usage(argv[0], optarg_, opath, user);
return false;
break;
120 if ((c == 1) || (c == -1)) {
122 usage(argv[0], NULL, opath, user);
123 std::cerr <<
"ERROR: " << std::endl;
124 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
139 bool compareKeyPoints(
const std::vector<cv::KeyPoint> &keypoints1,
const std::vector<cv::KeyPoint> &keypoints2) {
140 if(keypoints1.size() != keypoints2.size()) {
144 for(
size_t cpt = 0; cpt < keypoints1.size(); cpt++) {
145 if(!
vpMath::equal(keypoints1[cpt].angle, keypoints2[cpt].angle, std::numeric_limits<float>::epsilon())) {
146 std::cerr << std::fixed << std::setprecision(9) <<
"keypoints1[cpt].angle=" << keypoints1[cpt].angle <<
147 " ; keypoints2[cpt].angle=" << keypoints2[cpt].angle << std::endl;
151 if(keypoints1[cpt].class_id != keypoints2[cpt].class_id) {
152 std::cerr <<
"keypoints1[cpt].class_id=" << keypoints1[cpt].class_id <<
" ; keypoints2[cpt].class_id=" <<
153 keypoints2[cpt].class_id << std::endl;
157 if(keypoints1[cpt].octave != keypoints2[cpt].octave) {
158 std::cerr <<
"keypoints1[cpt].octave=" << keypoints1[cpt].octave <<
" ; keypoints2[cpt].octave=" <<
159 keypoints2[cpt].octave << std::endl;
163 if(!
vpMath::equal(keypoints1[cpt].pt.x, keypoints2[cpt].pt.x, std::numeric_limits<float>::epsilon())) {
164 std::cerr << std::fixed << std::setprecision(9) <<
"keypoints1[cpt].pt.x=" << keypoints1[cpt].pt.x <<
165 " ; keypoints2[cpt].pt.x=" << keypoints2[cpt].pt.x << std::endl;
169 if(!
vpMath::equal(keypoints1[cpt].pt.y, keypoints2[cpt].pt.y, std::numeric_limits<float>::epsilon())) {
170 std::cerr << std::fixed << std::setprecision(9) <<
"keypoints1[cpt].pt.y=" << keypoints1[cpt].pt.y <<
171 " ; keypoints2[cpt].pt.y=" << keypoints2[cpt].pt.y << std::endl;
175 if(!
vpMath::equal(keypoints1[cpt].response, keypoints2[cpt].response, std::numeric_limits<float>::epsilon())) {
176 std::cerr << std::fixed << std::setprecision(9) <<
"keypoints1[cpt].response=" << keypoints1[cpt].response <<
177 " ; keypoints2[cpt].response=" << keypoints2[cpt].response << std::endl;
181 if(!
vpMath::equal(keypoints1[cpt].size, keypoints2[cpt].size, std::numeric_limits<float>::epsilon())) {
182 std::cerr << std::fixed << std::setprecision(9) <<
"keypoints1[cpt].size=" << keypoints1[cpt].size <<
183 " ; keypoints2[cpt].size=" << keypoints2[cpt].size << std::endl;
199 bool compareDescriptors(
const cv::Mat &descriptors1,
const cv::Mat &descriptors2) {
200 if(descriptors1.rows != descriptors2.rows || descriptors1.cols != descriptors2.cols ||
201 descriptors1.type() != descriptors2.type()) {
205 for(
int i = 0; i < descriptors1.rows; i++) {
206 for(
int j = 0; j < descriptors1.cols; j++) {
207 switch(descriptors1.type()) {
209 if(descriptors1.at<
unsigned char>(i,j) != descriptors2.at<
unsigned char>(i,j)) {
210 std::cerr <<
"descriptors1.at<unsigned char>(i,j)=" << descriptors1.at<
unsigned char>(i,j) <<
211 " ; descriptors2.at<unsigned char>(i,j)=" << descriptors2.at<
unsigned char>(i,j) << std::endl;
217 if(descriptors1.at<
char>(i,j) != descriptors2.at<
char>(i,j)) {
218 std::cerr <<
"descriptors1.at<char>(i,j)=" << descriptors1.at<
char>(i,j) <<
219 " ; descriptors2.at<char>(i,j)=" << descriptors2.at<
char>(i,j) << std::endl;
225 if(descriptors1.at<
unsigned short>(i,j) != descriptors2.at<
unsigned short>(i,j)) {
226 std::cerr <<
"descriptors1.at<unsigned short>(i,j)=" << descriptors1.at<
unsigned short>(i,j) <<
227 " ; descriptors2.at<unsigned short>(i,j)=" << descriptors2.at<
unsigned short>(i,j) << std::endl;
233 if(descriptors1.at<
short>(i,j) != descriptors2.at<
short>(i,j)) {
234 std::cerr <<
"descriptors1.at<short>(i,j)=" << descriptors1.at<
short>(i,j) <<
235 " ; descriptors2.at<short>(i,j)=" << descriptors2.at<
short>(i,j) << std::endl;
241 if(descriptors1.at<
int>(i,j) != descriptors2.at<
int>(i,j)) {
242 std::cerr <<
"descriptors1.at<int>(i,j)=" << descriptors1.at<
int>(i,j) <<
243 " ; descriptors2.at<int>(i,j)=" << descriptors2.at<
int>(i,j) << std::endl;
249 if(!
vpMath::equal(descriptors1.at<
float>(i,j), descriptors2.at<
float>(i,j), std::numeric_limits<float>::epsilon())) {
250 std::cerr << std::fixed << std::setprecision(9) <<
"descriptors1.at<float>(i,j)=" << descriptors1.at<
float>(i,j)
251 <<
" ; descriptors2.at<float>(i,j)=" << descriptors2.at<
float>(i,j) << std::endl;
257 if(!
vpMath::equal(descriptors1.at<
double>(i,j), descriptors2.at<
double>(i,j), std::numeric_limits<double>::epsilon())) {
258 std::cerr << std::fixed << std::setprecision(17) <<
"descriptors1.at<double>(i,j)=" << descriptors1.at<
double>(i,j)
259 <<
" ; descriptors2.at<double>(i,j)=" << descriptors2.at<
double>(i,j) << std::endl;
279 int main(
int argc,
const char ** argv) {
281 std::string env_ipath;
282 std::string opt_opath;
283 std::string username;
285 std::string filename;
290 if(env_ipath.empty()) {
296 opt_opath =
"C:/temp";
305 if (getOptions(argc, argv, opt_opath, username) ==
false) {
310 if (!opt_opath.empty()) {
324 usage(argv[0], NULL, opt_opath, username);
325 std::stringstream ss;
326 ss << std::endl <<
"ERROR:" << std::endl;
327 ss <<
" Cannot create " << opath << std::endl;
328 ss <<
" Check your -o " << opt_opath <<
" option " << std::endl;
346 std::string keypointName =
"ORB";
352 std::vector<cv::KeyPoint> trainKeyPoints;
355 if(trainKeyPoints.empty() || trainDescriptors.empty() || (int) trainKeyPoints.size() != trainDescriptors.rows) {
367 std::stringstream ss;
368 ss <<
"Problem when saving file=" << filename;
375 std::vector<cv::KeyPoint> trainKeyPoints_read;
379 if(!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
381 "in binary with train images saved !");
384 if(!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
386 "binary with train images saved !");
398 std::stringstream ss;
399 ss <<
"Problem when saving file=" << filename;
406 trainKeyPoints_read.clear();
410 if(!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
412 "binary without train images !");
415 if(!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
417 "binary without train images !");
421 #if defined(VISP_HAVE_XML2)
430 std::stringstream ss;
431 ss <<
"Problem when saving file=" << filename;
438 trainKeyPoints_read.clear();
442 if(!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
444 "xml with train images saved !");
447 if(!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
449 "xml with train images saved !");
461 std::stringstream ss;
462 ss <<
"Problem when saving file=" << filename;
469 trainKeyPoints_read.clear();
473 if(!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
475 "xml without train images saved !");
478 if(!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
480 "xml without train images saved !");
484 std::cout <<
"Saving / loading learning files with binary descriptor are ok !" << std::endl;
489 #if defined(VISP_HAVE_OPENCV_NONFREE) || ( (VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(VISP_HAVE_OPENCV_XFEATURES2D) )
491 std::string keypointName =
"SIFT";
497 std::vector<cv::KeyPoint> trainKeyPoints;
500 if(trainKeyPoints.empty() || trainDescriptors.empty() || (int) trainKeyPoints.size() != trainDescriptors.rows) {
512 std::stringstream ss;
513 ss <<
"Problem when saving file=" << filename;
520 std::vector<cv::KeyPoint> trainKeyPoints_read;
524 if(!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
526 "binary with train images saved !");
529 if(!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
531 "binary with train images saved !");
543 std::stringstream ss;
544 ss <<
"Problem when saving file=" << filename;
551 trainKeyPoints_read.clear();
555 if(!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
557 "binary without train images saved !");
560 if(!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
562 "binary without train images saved !");
566 #if defined(VISP_HAVE_XML2)
575 std::stringstream ss;
576 ss <<
"Problem when saving file=" << filename;
583 trainKeyPoints_read.clear();
587 if(!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
589 "xml with train images saved !");
592 if(!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
594 "xml with train images saved !");
606 std::stringstream ss;
607 ss <<
"Problem when saving file=" << filename;
614 trainKeyPoints_read.clear();
618 if(!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
620 "xml without train images saved !");
623 if(!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
625 "xml without train images saved !");
629 std::cout <<
"Saving / loading learning files with floating point descriptor are ok !" << std::endl;
635 keypointName =
"ORB";
642 keypoint_reset.
reset();
644 keypointName =
"SIFT";
650 std::vector<cv::KeyPoint> trainKeyPoints_reset;
655 if(!compareKeyPoints(trainKeyPoints, trainKeyPoints_reset)) {
659 if(!compareDescriptors(trainDescriptors, trainDescriptors_reset)) {
663 std::cout <<
"vpKeyPoint::reset() is ok with trainKeyPoints and trainDescriptors !" << std::endl;
669 std::cerr << e.
what() << std::endl;
673 std::cout <<
"Saving / loading learning files are ok !" << std::endl;
674 std::cout <<
"testKeyPoint-7 is ok !" << std::endl;
679 std::cerr <<
"You need OpenCV library." << std::endl;
void getTrainKeyPoints(std::vector< cv::KeyPoint > &keyPoints) const
static bool equal(double x, double y, double s=0.001)
error that can be emited by ViSP classes.
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
const char * what() const
void setDetector(const vpFeatureDetectorType &detectorType)
unsigned int buildReference(const vpImage< unsigned char > &I)
void loadLearningData(const std::string &filename, const bool binaryMode=false, const bool append=false)
static void read(vpImage< unsigned char > &I, const std::string &filename)
Class that allows keypoints detection (and descriptors extraction) and matching thanks to OpenCV libr...
void saveLearningData(const std::string &filename, const bool binaryMode=false, const bool saveTrainingImages=true)
cv::Mat getTrainDescriptors() const
void setExtractor(const vpFeatureDescriptorType &extractorType)