36 #include <visp3/core/vpDebug.h>
37 #include <visp3/core/vpImage.h>
38 #include <visp3/core/vpImageTools.h>
39 #include <visp3/core/vpIoTools.h>
40 #include <visp3/core/vpRGBa.h>
41 #include <visp3/core/vpTime.h>
42 #include <visp3/io/vpImageIo.h>
43 #include <visp3/io/vpParseArgv.h>
54 #define GETOPTARGS "cdi:o:t:s:h"
65 void usage(
const char *name,
const char *badparam,
const std::string &ipath,
const std::string &opath,
66 const std::string &user)
68 #if VISP_HAVE_DATASET_VERSION >= 0x030600
69 std::string ext(
"png");
71 std::string ext(
"pgm");
74 Read an image from the disk, undistort it \n\
75 and save the undistorted image on the disk.\n\
76 (grid36-01_undistorted.pgm).\n\
79 %s [-i <input image path>] [-o <output image path>] [-t <nThreads>] [-s <scale>]\n\
86 -i <input image path> %s\n\
87 Set image input path.\n\
88 From this path read \"calibration/grid36-01.%s\"\n\
90 Setting the VISP_INPUT_IMAGE_PATH environment\n\
91 variable produces the same behaviour than using\n\
94 -o <output image path> %s\n\
95 Set image output path.\n\
96 From this directory, creates the \"%s\"\n\
97 subdirectory depending on the username, where \n\
98 grid36-01_undistorted.pgm output image is written.\n\
101 Set the number of threads to use for vpImageTools::undistort().\n\
104 Resize the image by the specified scale factor.\n\
107 Print the help.\n\n",
108 ext.c_str(), ipath.c_str(), opath.c_str(), user.c_str());
111 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
126 bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &opath,
const std::string &user,
127 unsigned int &nThreads,
unsigned int &scale)
141 nThreads = atoi(optarg_);
144 scale = atoi(optarg_);
147 usage(argv[0],
nullptr, ipath, opath, user);
155 usage(argv[0], optarg_, ipath, opath, user);
160 if ((c == 1) || (c == -1)) {
162 usage(argv[0],
nullptr, ipath, opath, user);
163 std::cerr <<
"ERROR: " << std::endl;
164 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
171 int main(
int argc,
const char **argv)
174 std::string env_ipath;
175 std::string opt_ipath;
176 std::string opt_opath;
179 std::string filename;
180 std::string username;
181 unsigned int nThreads = 2;
182 unsigned int scale = 1;
184 #if VISP_HAVE_DATASET_VERSION >= 0x030600
185 std::string ext(
"png");
187 std::string ext(
"pgm");
195 if (!env_ipath.empty())
199 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
201 #elif defined(_WIN32)
202 opt_opath =
"C:\\temp";
209 if (getOptions(argc, argv, opt_ipath, opt_opath, username, nThreads, scale) ==
false) {
214 if (!opt_ipath.empty())
216 if (!opt_opath.empty())
229 usage(argv[0],
nullptr, ipath, opt_opath, username);
230 std::cerr << std::endl <<
"ERROR:" << std::endl;
231 std::cerr <<
" Cannot create " << opath << std::endl;
232 std::cerr <<
" Check your -o " << opt_opath <<
" option " << std::endl;
239 if (opt_ipath.empty()) {
240 if (ipath != env_ipath) {
241 std::cout << std::endl <<
"WARNING: " << std::endl;
242 std::cout <<
" Since -i <visp image path=" << ipath <<
"> "
243 <<
" is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
244 <<
" we skip the environment variable." << std::endl;
249 if (opt_ipath.empty() && env_ipath.empty()) {
250 usage(argv[0],
nullptr, ipath, opt_opath, username);
251 std::cerr << std::endl <<
"ERROR:" << std::endl;
252 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
253 <<
" environment variable to specify the location of the " << std::endl
254 <<
" image path where test images are located." << std::endl
273 std::cout <<
"Read image: " << filename << std::endl;
276 std::cout <<
"Scale the image by a factor of " << scale << std::endl;
282 std::cout <<
"Input image: " << I.
getWidth() <<
"x" << I.
getHeight() << std::endl;
285 std::cout <<
"Nb threads to use for vpImageTools::undistort(): " << nThreads << std::endl;
287 double t_undistort = 0.0, t_remap = 0.0;
289 std::cout <<
"\nUndistortion in process (color image)... " << std::endl;
296 for (
unsigned int i = 0; i < 10; i++)
301 t_undistort = endtime - begintime;
303 std::cout <<
"Time for 10 color image undistortion (ms): " << t_undistort << std::endl;
307 std::cout <<
"Undistortion in process with remap (color image)... " << std::endl;
315 for (
unsigned int i = 0; i < 10; i++) {
323 t_remap = endtime - begintime;
325 std::cout <<
"Time for 10 color image undistortion with remap (ms): " << t_remap << std::endl;
326 std::cout <<
"Speed-up: " << t_undistort / t_remap <<
"X" << std::endl;
330 std::cout <<
"\nUndistortion in process (gray image)... " << std::endl;
337 for (
unsigned int i = 0; i < 100; i++)
342 t_undistort = endtime - begintime;
344 std::cout <<
"Time for 100 gray image undistortion (ms): " << t_undistort << std::endl;
348 std::cout <<
"Undistortion in process with remap (gray image)... " << std::endl;
356 for (
unsigned int i = 0; i < 10; i++) {
364 t_remap = endtime - begintime;
366 std::cout <<
"Time for 100 gray image undistortion with remap (ms): " << t_remap << std::endl;
367 std::cout <<
"Speed-up: " << t_undistort / t_remap <<
"X" << std::endl;
372 std::cout <<
"\nWrite undistorted image: " << filename << std::endl;
376 std::cout <<
"Write undistorted image: " << filename << std::endl;
380 std::cout <<
"\nWrite undistorted image with remap: " << filename << std::endl;
384 std::cout <<
"Write undistorted image with remap: " << filename << std::endl;
390 double mean_diff = 0.0;
391 for (
unsigned int i = 0; i < U_diff_abs.
getHeight(); i++) {
392 for (
unsigned int j = 0; j < U_diff_abs.
getWidth(); j++) {
393 mean_diff += U_diff_abs[i][j].R;
394 mean_diff += U_diff_abs[i][j].G;
395 mean_diff += U_diff_abs[i][j].B;
396 mean_diff += U_diff_abs[i][j].A;
399 double remap_mean_error = mean_diff / (4 * U_diff_abs.
getSize());
400 std::cout <<
"U_diff_abs mean value: " << remap_mean_error << std::endl;
401 const double remap_error_threshold = 0.5;
402 if (remap_mean_error > remap_error_threshold) {
403 std::cerr <<
"Issue with vpImageTools::remap() with vpRGBa image" << std::endl;
409 double remap_mean_error_gray = U_diff_gray_abs.
getSum() / U_diff_gray_abs.
getSize();
410 std::cout <<
"U_diff_gray_abs mean value: " << remap_mean_error_gray << std::endl;
411 if (remap_mean_error_gray > remap_error_threshold) {
412 std::cerr <<
"Issue with vpImageTools::remap() with unsigned char image" << std::endl;
421 std::cout <<
"\nWrite undistorted image: " << filename << std::endl;
426 std::cout <<
"Write undistorted image: " << filename << std::endl;
432 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()