40#include <visp3/core/vpDebug.h>
41#include <visp3/core/vpImage.h>
42#include <visp3/core/vpImageTools.h>
43#include <visp3/core/vpIoTools.h>
44#include <visp3/core/vpRGBa.h>
45#include <visp3/core/vpTime.h>
46#include <visp3/io/vpImageIo.h>
47#include <visp3/io/vpParseArgv.h>
59#define GETOPTARGS "cdi:o:t:s:h"
70void usage(
const char *name,
const char *badparam,
const std::string &ipath,
const std::string &opath,
71 const std::string &user)
73#if VISP_HAVE_DATASET_VERSION >= 0x030600
74 std::string ext(
"png");
76 std::string ext(
"pgm");
79Read an image from the disk, undistort it \n\
80and save the undistorted image on the disk.\n\
81(grid36-01_undistorted.pgm).\n\
84 %s [-i <input image path>] [-o <output image path>] [-t <nThreads>] [-s <scale>]\n\
91 -i <input image path> %s\n\
92 Set image input path.\n\
93 From this path read \"calibration/grid36-01.%s\"\n\
95 Setting the VISP_INPUT_IMAGE_PATH environment\n\
96 variable produces the same behaviour than using\n\
99 -o <output image path> %s\n\
100 Set image output path.\n\
101 From this directory, creates the \"%s\"\n\
102 subdirectory depending on the username, where \n\
103 grid36-01_undistorted.pgm output image is written.\n\
106 Set the number of threads to use for vpImageTools::undistort().\n\
109 Resize the image by the specified scale factor.\n\
112 Print the help.\n\n",
113 ext.c_str(), ipath.c_str(), opath.c_str(), user.c_str());
116 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
131bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &opath,
const std::string &user,
132 unsigned int &nThreads,
unsigned int &scale)
146 nThreads = atoi(optarg_);
149 scale = atoi(optarg_);
152 usage(argv[0], NULL, ipath, opath, user);
160 usage(argv[0], optarg_, ipath, opath, user);
165 if ((c == 1) || (c == -1)) {
167 usage(argv[0], NULL, ipath, opath, user);
168 std::cerr <<
"ERROR: " << std::endl;
169 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
176int main(
int argc,
const char **argv)
179 std::string env_ipath;
180 std::string opt_ipath;
181 std::string opt_opath;
184 std::string filename;
185 std::string username;
186 unsigned int nThreads = 2;
187 unsigned int scale = 1;
189#if VISP_HAVE_DATASET_VERSION >= 0x030600
190 std::string ext(
"png");
192 std::string ext(
"pgm");
200 if (!env_ipath.empty())
204#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
207 opt_opath =
"C:\\temp";
214 if (getOptions(argc, argv, opt_ipath, opt_opath, username, nThreads, scale) ==
false) {
219 if (!opt_ipath.empty())
221 if (!opt_opath.empty())
233 usage(argv[0], NULL, ipath, opt_opath, username);
234 std::cerr << std::endl <<
"ERROR:" << std::endl;
235 std::cerr <<
" Cannot create " << opath << std::endl;
236 std::cerr <<
" Check your -o " << opt_opath <<
" option " << std::endl;
243 if (opt_ipath.empty()) {
244 if (ipath != env_ipath) {
245 std::cout << std::endl <<
"WARNING: " << std::endl;
246 std::cout <<
" Since -i <visp image path=" << ipath <<
"> "
247 <<
" is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
248 <<
" we skip the environment variable." << std::endl;
253 if (opt_ipath.empty() && env_ipath.empty()) {
254 usage(argv[0], NULL, ipath, opt_opath, username);
255 std::cerr << std::endl <<
"ERROR:" << std::endl;
256 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
257 <<
" environment variable to specify the location of the " << std::endl
258 <<
" image path where test images are located." << std::endl
277 std::cout <<
"Read image: " << filename << std::endl;
280 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;
434 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)
Definition of the vpImage class member functions.
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()