35 #include <visp3/core/vpDebug.h>
36 #include <visp3/core/vpImage.h>
37 #include <visp3/core/vpImageTools.h>
38 #include <visp3/core/vpIoTools.h>
39 #include <visp3/core/vpRGBa.h>
40 #include <visp3/core/vpTime.h>
41 #include <visp3/io/vpImageIo.h>
42 #include <visp3/io/vpParseArgv.h>
53 #define GETOPTARGS "cdi:o:t:s:h"
55 #ifdef ENABLE_VISP_NAMESPACE
68 void usage(
const char *name,
const char *badparam,
const std::string &ipath,
const std::string &opath,
69 const std::string &user)
71 #if VISP_HAVE_DATASET_VERSION >= 0x030600
72 std::string ext(
"png");
74 std::string ext(
"pgm");
77 Read an image from the disk, undistort it \n\
78 and save the undistorted image on the disk.\n\
79 (grid36-01_undistorted.pgm).\n\
82 %s [-i <input image path>] [-o <output image path>] [-t <nThreads>] [-s <scale>]\n\
89 -i <input image path> %s\n\
90 Set image input path.\n\
91 From this path read \"calibration/grid36-01.%s\"\n\
93 Setting the VISP_INPUT_IMAGE_PATH environment\n\
94 variable produces the same behaviour than using\n\
97 -o <output image path> %s\n\
98 Set image output path.\n\
99 From this directory, creates the \"%s\"\n\
100 subdirectory depending on the username, where \n\
101 grid36-01_undistorted.pgm output image is written.\n\
104 Set the number of threads to use for vpImageTools::undistort().\n\
107 Resize the image by the specified scale factor.\n\
110 Print the help.\n\n",
111 ext.c_str(), ipath.c_str(), opath.c_str(), user.c_str());
114 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
129 bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &opath,
const std::string &user,
130 unsigned int &nThreads,
unsigned int &scale)
144 nThreads = atoi(optarg_);
147 scale = atoi(optarg_);
150 usage(argv[0],
nullptr, ipath, opath, user);
158 usage(argv[0], optarg_, ipath, opath, user);
163 if ((c == 1) || (c == -1)) {
165 usage(argv[0],
nullptr, ipath, opath, user);
166 std::cerr <<
"ERROR: " << std::endl;
167 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
174 int main(
int argc,
const char **argv)
177 std::string env_ipath;
178 std::string opt_ipath;
179 std::string opt_opath;
182 std::string filename;
183 std::string username;
184 unsigned int nThreads = 2;
185 unsigned int scale = 1;
187 #if VISP_HAVE_DATASET_VERSION >= 0x030600
188 std::string ext(
"png");
190 std::string ext(
"pgm");
198 if (!env_ipath.empty())
202 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
204 #elif defined(_WIN32)
205 opt_opath =
"C:\\temp";
212 if (getOptions(argc, argv, opt_ipath, opt_opath, username, nThreads, scale) ==
false) {
217 if (!opt_ipath.empty())
219 if (!opt_opath.empty())
232 usage(argv[0],
nullptr, ipath, opt_opath, username);
233 std::cerr << std::endl <<
"ERROR:" << std::endl;
234 std::cerr <<
" Cannot create " << opath << std::endl;
235 std::cerr <<
" Check your -o " << opt_opath <<
" option " << std::endl;
242 if (opt_ipath.empty()) {
243 if (ipath != env_ipath) {
244 std::cout << std::endl <<
"WARNING: " << std::endl;
245 std::cout <<
" Since -i <visp image path=" << ipath <<
"> "
246 <<
" is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
247 <<
" we skip the environment variable." << std::endl;
252 if (opt_ipath.empty() && env_ipath.empty()) {
253 usage(argv[0],
nullptr, ipath, opt_opath, username);
254 std::cerr << std::endl <<
"ERROR:" << std::endl;
255 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
256 <<
" environment variable to specify the location of the " << std::endl
257 <<
" image path where test images are located." << std::endl
276 std::cout <<
"Read image: " << filename << std::endl;
279 std::cout <<
"Scale the image by a factor of " << scale << std::endl;
285 std::cout <<
"Input image: " << I.
getWidth() <<
"x" << I.
getHeight() << std::endl;
288 std::cout <<
"Nb threads to use for vpImageTools::undistort(): " << nThreads << std::endl;
290 double t_undistort = 0.0, t_remap = 0.0;
292 std::cout <<
"\nUndistortion in process (color image)... " << std::endl;
299 for (
unsigned int i = 0; i < 10; i++)
304 t_undistort = endtime - begintime;
306 std::cout <<
"Time for 10 color image undistortion (ms): " << t_undistort << std::endl;
310 std::cout <<
"Undistortion in process with remap (color image)... " << std::endl;
318 for (
unsigned int i = 0; i < 10; i++) {
326 t_remap = endtime - begintime;
328 std::cout <<
"Time for 10 color image undistortion with remap (ms): " << t_remap << std::endl;
329 std::cout <<
"Speed-up: " << t_undistort / t_remap <<
"X" << std::endl;
333 std::cout <<
"\nUndistortion in process (gray image)... " << std::endl;
340 for (
unsigned int i = 0; i < 100; i++)
345 t_undistort = endtime - begintime;
347 std::cout <<
"Time for 100 gray image undistortion (ms): " << t_undistort << std::endl;
351 std::cout <<
"Undistortion in process with remap (gray image)... " << std::endl;
359 for (
unsigned int i = 0; i < 10; i++) {
367 t_remap = endtime - begintime;
369 std::cout <<
"Time for 100 gray image undistortion with remap (ms): " << t_remap << std::endl;
370 std::cout <<
"Speed-up: " << t_undistort / t_remap <<
"X" << std::endl;
375 std::cout <<
"\nWrite undistorted image: " << filename << std::endl;
379 std::cout <<
"Write undistorted image: " << filename << std::endl;
383 std::cout <<
"\nWrite undistorted image with remap: " << filename << std::endl;
387 std::cout <<
"Write undistorted image with remap: " << filename << std::endl;
393 double mean_diff = 0.0;
394 for (
unsigned int i = 0; i < U_diff_abs.
getHeight(); i++) {
395 for (
unsigned int j = 0; j < U_diff_abs.
getWidth(); j++) {
396 mean_diff += U_diff_abs[i][j].R;
397 mean_diff += U_diff_abs[i][j].G;
398 mean_diff += U_diff_abs[i][j].B;
399 mean_diff += U_diff_abs[i][j].A;
402 double remap_mean_error = mean_diff / (4 * U_diff_abs.
getSize());
403 std::cout <<
"U_diff_abs mean value: " << remap_mean_error << std::endl;
404 const double remap_error_threshold = 0.5;
405 if (remap_mean_error > remap_error_threshold) {
406 std::cerr <<
"Issue with vpImageTools::remap() with vpRGBa image" << std::endl;
412 double remap_mean_error_gray = U_diff_gray_abs.
getSum() / U_diff_gray_abs.
getSize();
413 std::cout <<
"U_diff_gray_abs mean value: " << remap_mean_error_gray << std::endl;
414 if (remap_mean_error_gray > remap_error_threshold) {
415 std::cerr <<
"Issue with vpImageTools::remap() with unsigned char image" << std::endl;
424 std::cout <<
"\nWrite undistorted image: " << filename << std::endl;
429 std::cout <<
"Write undistorted image: " << filename << std::endl;
435 std::cout <<
"Catch an exception: " << e << std::endl;
Implementation of a generic 2D array used as base class for matrices and vectors.
Generic class defining intrinsic camera parameters.
void initPersProjWithDistortion(double px, double py, double u0, double v0, double kud, double kdu)
error that can be emitted by ViSP classes.
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
double getSum(const vpImage< bool > *p_mask=nullptr, unsigned int *nbValidPoints=nullptr) const
Compute the sum of image intensities.
unsigned int getWidth() const
unsigned int getSize() const
unsigned int getHeight() const
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
VISP_EXPORT double measureTimeMs()