Test saving / loading learning file.
#include <iomanip>
#include <iostream>
#include <visp3/core/vpConfig.h>
#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) && defined(HAVE_OPENCV_FEATURES2D) && defined(HAVE_OPENCV_VIDEO)
#include <visp3/core/vpException.h>
#include <visp3/core/vpImage.h>
#include <visp3/core/vpIoTools.h>
#include <visp3/io/vpImageIo.h>
#include <visp3/io/vpParseArgv.h>
#include <visp3/vision/vpKeyPoint.h>
#define GETOPTARGS "cdo:h"
#ifdef ENABLE_VISP_NAMESPACE
#endif
void usage(const char *name, const char *badparam, const std::string &opath, const std::string &user)
{
fprintf(stdout, "\n\
Test save / load learning files for vpKeyPoint class.\n\
\n\
SYNOPSIS\n\
%s [-c] [-d] [-h]\n",
name);
fprintf(stdout, "\n\
OPTIONS: \n\
\n\
-o <output image path> %s\n\
Set image output path.\n\
From this directory, creates the \"%s\"\n\
subdirectory depending on the username, where \n\
learning files will be written.\n\
\n\
-h\n\
Print the help.\n",
opath.c_str(), user.c_str());
if (badparam)
fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
}
bool getOptions(int argc, const char **argv, std::string &opath, const std::string &user)
{
const char *optarg_;
int c;
switch (c) {
case 'c':
break;
case 'd':
break;
case 'o':
opath = optarg_;
break;
case 'h':
usage(argv[0], nullptr, opath, user);
return false;
break;
default:
usage(argv[0], optarg_, opath, user);
return false;
break;
return false;
break;
}
}
if ((c == 1) || (c == -1)) {
usage(argv[0], nullptr, opath, user);
std::cerr << "ERROR: " << std::endl;
std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
return false;
}
return true;
}
bool compareKeyPoints(const std::vector<cv::KeyPoint> &keypoints1, const std::vector<cv::KeyPoint> &keypoints2)
{
if (keypoints1.size() != keypoints2.size()) {
return false;
}
for (size_t cpt = 0; cpt < keypoints1.size(); cpt++) {
if (!
vpMath::equal(keypoints1[cpt].angle, keypoints2[cpt].angle, std::numeric_limits<float>::epsilon())) {
std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].angle=" << keypoints1[cpt].angle
<< " ; keypoints2[cpt].angle=" << keypoints2[cpt].angle << std::endl;
return false;
}
if (keypoints1[cpt].class_id != keypoints2[cpt].class_id) {
std::cerr << "keypoints1[cpt].class_id=" << keypoints1[cpt].class_id
<< " ; keypoints2[cpt].class_id=" << keypoints2[cpt].class_id << std::endl;
return false;
}
if (keypoints1[cpt].octave != keypoints2[cpt].octave) {
std::cerr << "keypoints1[cpt].octave=" << keypoints1[cpt].octave
<< " ; keypoints2[cpt].octave=" << keypoints2[cpt].octave << std::endl;
return false;
}
if (!
vpMath::equal(keypoints1[cpt].pt.x, keypoints2[cpt].pt.x, std::numeric_limits<float>::epsilon())) {
std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].pt.x=" << keypoints1[cpt].pt.x
<< " ; keypoints2[cpt].pt.x=" << keypoints2[cpt].pt.x << std::endl;
return false;
}
if (!
vpMath::equal(keypoints1[cpt].pt.y, keypoints2[cpt].pt.y, std::numeric_limits<float>::epsilon())) {
std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].pt.y=" << keypoints1[cpt].pt.y
<< " ; keypoints2[cpt].pt.y=" << keypoints2[cpt].pt.y << std::endl;
return false;
}
if (!
vpMath::equal(keypoints1[cpt].response, keypoints2[cpt].response, std::numeric_limits<float>::epsilon())) {
std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].response=" << keypoints1[cpt].response
<< " ; keypoints2[cpt].response=" << keypoints2[cpt].response << std::endl;
return false;
}
if (!
vpMath::equal(keypoints1[cpt].size, keypoints2[cpt].size, std::numeric_limits<float>::epsilon())) {
std::cerr << std::fixed << std::setprecision(9) << "keypoints1[cpt].size=" << keypoints1[cpt].size
<< " ; keypoints2[cpt].size=" << keypoints2[cpt].size << std::endl;
return false;
}
}
return true;
}
bool compareDescriptors(const cv::Mat &descriptors1, const cv::Mat &descriptors2)
{
if (descriptors1.rows != descriptors2.rows || descriptors1.cols != descriptors2.cols ||
descriptors1.type() != descriptors2.type()) {
return false;
}
for (int i = 0; i < descriptors1.rows; i++) {
for (int j = 0; j < descriptors1.cols; j++) {
switch (descriptors1.type()) {
case CV_8U:
if (descriptors1.at<unsigned char>(i, j) != descriptors2.at<unsigned char>(i, j)) {
std::cerr << "descriptors1.at<unsigned char>(i,j)=" << descriptors1.at<unsigned char>(i, j)
<< " ; descriptors2.at<unsigned char>(i,j)=" << descriptors2.at<unsigned char>(i, j) << std::endl;
return false;
}
break;
case CV_8S:
if (descriptors1.at<char>(i, j) != descriptors2.at<char>(i, j)) {
std::cerr << "descriptors1.at<char>(i,j)=" << descriptors1.at<char>(i, j)
<< " ; descriptors2.at<char>(i,j)=" << descriptors2.at<char>(i, j) << std::endl;
return false;
}
break;
case CV_16U:
if (descriptors1.at<unsigned short>(i, j) != descriptors2.at<unsigned short>(i, j)) {
std::cerr << "descriptors1.at<unsigned short>(i,j)=" << descriptors1.at<unsigned short>(i, j)
<< " ; descriptors2.at<unsigned short>(i,j)=" << descriptors2.at<unsigned short>(i, j) << std::endl;
return false;
}
break;
case CV_16S:
if (descriptors1.at<short>(i, j) != descriptors2.at<short>(i, j)) {
std::cerr << "descriptors1.at<short>(i,j)=" << descriptors1.at<short>(i, j)
<< " ; descriptors2.at<short>(i,j)=" << descriptors2.at<short>(i, j) << std::endl;
return false;
}
break;
case CV_32S:
if (descriptors1.at<int>(i, j) != descriptors2.at<int>(i, j)) {
std::cerr << "descriptors1.at<int>(i,j)=" << descriptors1.at<int>(i, j)
<< " ; descriptors2.at<int>(i,j)=" << descriptors2.at<int>(i, j) << std::endl;
return false;
}
break;
case CV_32F:
if (!
vpMath::equal(descriptors1.at<
float>(i, j), descriptors2.at<
float>(i, j),
std::numeric_limits<float>::epsilon())) {
std::cerr << std::fixed << std::setprecision(9)
<< "descriptors1.at<float>(i,j)=" << descriptors1.at<float>(i, j)
<< " ; descriptors2.at<float>(i,j)=" << descriptors2.at<float>(i, j) << std::endl;
return false;
}
break;
case CV_64F:
if (!
vpMath::equal(descriptors1.at<
double>(i, j), descriptors2.at<
double>(i, j),
std::numeric_limits<double>::epsilon())) {
std::cerr << std::fixed << std::setprecision(17)
<< "descriptors1.at<double>(i,j)=" << descriptors1.at<double>(i, j)
<< " ; descriptors2.at<double>(i,j)=" << descriptors2.at<double>(i, j) << std::endl;
return false;
}
break;
default:
return false;
break;
}
}
}
return true;
}
template <
typename Type>
void run_test(
const std::string &env_ipath,
const std::string &opath,
vpImage<Type> &I)
{
std::string filename;
{
std::cout << "Detect ORB keypoints" << std::endl;
std::string keypointName = "ORB";
std::vector<cv::KeyPoint> trainKeyPoints;
if (trainKeyPoints.empty() || trainDescriptors.empty() || (int)trainKeyPoints.size() != trainDescriptors.rows) {
"keypoints or when "
"computing descriptors !");
}
std::cout << "Save keypoints in binary with image in: " << filename << std::endl;
std::stringstream ss;
ss << "Problem when saving file=" << filename;
}
std::cout << "Read keypoints from file: " << filename << std::endl;
std::vector<cv::KeyPoint> trainKeyPoints_read;
std::cout << "Compare keypoints" << std::endl;
if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
"in binary with train images saved !");
}
std::cout << "Compare descriptors" << std::endl;
if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
"learning file saved in "
"binary with train images saved !");
}
std::cout << "Save keypoints in binary without image in: " << filename << std::endl;
std::stringstream ss;
ss << "Problem when saving file=" << filename;
}
std::cout << "Read keypoints from file: " << filename << std::endl;
trainKeyPoints_read.clear();
std::cout << "Compare keypoints" << std::endl;
if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
"binary without train images !");
}
std::cout << "Compare descriptors" << std::endl;
if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
"learning file saved in "
"binary without train images !");
}
#if defined(VISP_HAVE_PUGIXML)
std::cout << "Save keypoints in xml with image in: " << filename << std::endl;
std::stringstream ss;
ss << "Problem when saving file=" << filename;
}
std::cout << "Read keypoints from file: " << filename << std::endl;
trainKeyPoints_read.clear();
std::cout << "Compare keypoints" << std::endl;
if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
"xml with train images saved !");
}
std::cout << "Compare descriptors" << std::endl;
if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
"learning file saved in "
"xml with train images saved !");
}
std::cout << "Save keypoints in xml without image in: " << filename << std::endl;
std::stringstream ss;
ss << "Problem when saving file=" << filename;
}
trainKeyPoints_read.clear();
std::cout << "Read keypoints from file: " << filename << std::endl;
std::cout << "Compare keypoints" << std::endl;
if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
"xml without train images saved !");
}
std::cout << "Compare descriptors" << std::endl;
if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
"learning file saved in "
"xml without train images saved !");
}
#endif
std::cout << "Saving / loading learning files with binary descriptor are ok !" << std::endl;
}
#if defined(VISP_HAVE_OPENCV_NONFREE) || \
((VISP_HAVE_OPENCV_VERSION >= 0x030000) && defined(VISP_HAVE_OPENCV_XFEATURES2D) || \
(VISP_HAVE_OPENCV_VERSION >= 0x030411 && CV_MAJOR_VERSION < 4) || (VISP_HAVE_OPENCV_VERSION >= 0x040400))
{
#if (VISP_HAVE_OPENCV_VERSION != 0x040504) && (VISP_HAVE_OPENCV_VERSION != 0x040505) && \
(VISP_HAVE_OPENCV_VERSION != 0x040600) && (VISP_HAVE_OPENCV_VERSION != 0x040700) && \
(VISP_HAVE_OPENCV_VERSION != 0x040900) && (VISP_HAVE_OPENCV_VERSION != 0x040A00) && \
(defined(__APPLE__) && defined(__MACH__))
std::string keypointName = "SIFT";
std::cout << "Use " << keypointName << " keypoints" << std::endl;
std::cout << "Detect keypoints" << std::endl;
std::vector<cv::KeyPoint> trainKeyPoints;
std::cout << "Get descriptors" << std::endl;
if (trainKeyPoints.empty() || trainDescriptors.empty() || (int)trainKeyPoints.size() != trainDescriptors.rows) {
"computing descriptors (SIFT) !");
}
std::cout << "Save keypoints in binary with image in: " << filename << std::endl;
std::stringstream ss;
ss << "Problem when saving file=" << filename;
}
std::cout << "Load keypoints from: " << filename << std::endl;
std::vector<cv::KeyPoint> trainKeyPoints_read;
std::cout << "Compare keypoints" << std::endl;
if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
"binary with train images saved !");
}
std::cout << "Compare descriptors" << std::endl;
if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
"learning file saved in "
"binary with train images saved !");
}
std::cout << "Save keypoints in binary without image in: " << filename << std::endl;
std::stringstream ss;
ss << "Problem when saving file=" << filename;
}
std::cout << "Load keypoints from: " << filename << std::endl;
trainKeyPoints_read.clear();
std::cout << "Compare keypoints" << std::endl;
if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
"binary without train images saved !");
}
std::cout << "Compare descriptors" << std::endl;
if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
"learning file saved in "
"binary without train images saved !");
}
#if defined(VISP_HAVE_PUGIXML)
std::stringstream ss;
ss << "Problem when saving file=" << filename;
}
trainKeyPoints_read.clear();
if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
"xml with train images saved !");
}
if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
"learning file saved in "
"xml with train images saved !");
}
std::stringstream ss;
ss << "Problem when saving file=" << filename;
}
trainKeyPoints_read.clear();
if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_read)) {
"xml without train images saved !");
}
if (!compareDescriptors(trainDescriptors, trainDescriptors_read)) {
"learning file saved in "
"xml without train images saved !");
}
#endif
std::cout << "Saving / loading learning files with floating point descriptor are ok !" << std::endl;
keypointName = "ORB";
std::cout << "Use " << keypointName << " as keypoints" << std::endl;
std::cout << keypointName << " keypoints are detected" << std::endl;
keypointName = "SIFT";
std::cout << "Use " << keypointName << " as keypoints" << std::endl;
std::cout << keypointName << " keypoints are detected" << std::endl;
std::vector<cv::KeyPoint> trainKeyPoints_reset;
std::cout << "Get descriptors" << std::endl;
std::cout << "Compare keypoints" << std::endl;
if (!compareKeyPoints(trainKeyPoints, trainKeyPoints_reset)) {
}
std::cout << "Compare descriptors" << std::endl;
if (!compareDescriptors(trainDescriptors, trainDescriptors_reset)) {
}
std::cout << "vpKeyPoint::reset() is ok with trainKeyPoints and trainDescriptors !" << std::endl;
#endif
}
#endif
}
int main(int argc, const char **argv)
{
try {
std::string env_ipath;
std::string opt_opath;
std::string username;
std::string opath;
if (env_ipath.empty()) {
}
#if defined(_WIN32)
opt_opath = "C:/temp";
#else
opt_opath = "/tmp";
#endif
if (getOptions(argc, argv, opt_opath, username) == false) {
}
if (!opt_opath.empty()) {
opath = opt_opath;
}
{
std::cout << "-- Test on gray level images" << std::endl;
run_test(env_ipath, opath, I);
}
{
std::cout << "-- Test on color images" << std::endl;
run_test(env_ipath, opath, I);
}
}
std::cerr << e.
what() << std::endl;
return EXIT_FAILURE;
}
std::cout << "Saving / loading learning files are ok !" << std::endl;
std::cout << "testKeyPoint-7 is ok !" << std::endl;
return EXIT_SUCCESS;
}
#else
int main()
{
std::cerr << "You need OpenCV library." << std::endl;
return EXIT_SUCCESS;
}
#endif
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)