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
59void usage(
const char *name,
const char *badparam,
const std::string &ipath,
const std::string &opath,
60 const std::string &user);
61bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &opath,
const std::string &user,
62 unsigned int &nThreads,
unsigned int &scale);
73void usage(
const char *name,
const char *badparam,
const std::string &ipath,
const std::string &opath,
74 const std::string &user)
76#if defined(VISP_HAVE_DATASET)
77#if VISP_HAVE_DATASET_VERSION >= 0x030600
78 std::string ext(
"png");
80 std::string ext(
"pgm");
84 std::string ext(
"png");
87Read an image from the disk, undistort it \n\
88and save the undistorted image on the disk.\n\
89(grid36-01_undistorted.pgm).\n\
92 %s [-i <input image path>] [-o <output image path>] [-t <nThreads>] [-s <scale>]\n\
99 -i <input image path> %s\n\
100 Set image input path.\n\
101 From this path read \"calibration/grid36-01.%s\"\n\
103 Setting the VISP_INPUT_IMAGE_PATH environment\n\
104 variable produces the same behaviour than using\n\
107 -o <output image path> %s\n\
108 Set image output path.\n\
109 From this directory, creates the \"%s\"\n\
110 subdirectory depending on the username, where \n\
111 grid36-01_undistorted.pgm output image is written.\n\
114 Set the number of threads to use for vpImageTools::undistort().\n\
117 Resize the image by the specified scale factor.\n\
120 Print the help.\n\n",
121 ext.c_str(), ipath.c_str(), opath.c_str(), user.c_str());
124 fprintf(stdout,
"\nERROR: Bad parameter [%s]\n", badparam);
139bool getOptions(
int argc,
const char **argv, std::string &ipath, std::string &opath,
const std::string &user,
140 unsigned int &nThreads,
unsigned int &scale)
154 nThreads = atoi(optarg_);
157 scale = atoi(optarg_);
160 usage(argv[0],
nullptr, ipath, opath, user);
168 usage(argv[0], optarg_, ipath, opath, user);
173 if ((c == 1) || (c == -1)) {
175 usage(argv[0],
nullptr, ipath, opath, user);
176 std::cerr <<
"ERROR: " << std::endl;
177 std::cerr <<
" Bad argument " << optarg_ << std::endl << std::endl;
184int main(
int argc,
const char **argv)
187 std::string env_ipath;
188 std::string opt_ipath;
189 std::string opt_opath;
193 std::string username;
194 unsigned int nThreads = 2;
195 unsigned int scale = 1;
197#if defined(VISP_HAVE_DATASET)
198#if VISP_HAVE_DATASET_VERSION >= 0x030600
199 std::string ext(
"png");
201 std::string ext(
"pgm");
205 std::string ext(
"png");
213 if (!env_ipath.empty())
217#if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__)))
220 opt_opath =
"C:\\temp";
227 if (getOptions(argc, argv, opt_ipath, opt_opath, username, nThreads, scale) ==
false) {
232 if (!opt_ipath.empty())
234 if (!opt_opath.empty())
247 usage(argv[0],
nullptr, ipath, opt_opath, username);
248 std::cerr << std::endl <<
"ERROR:" << std::endl;
249 std::cerr <<
" Cannot create " << opath << std::endl;
250 std::cerr <<
" Check your -o " << opt_opath <<
" option " << std::endl;
257 if (opt_ipath.empty()) {
258 if (ipath != env_ipath) {
259 std::cout << std::endl <<
"WARNING: " << std::endl;
260 std::cout <<
" Since -i <visp image path=" << ipath <<
"> "
261 <<
" is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
262 <<
" we skip the environment variable." << std::endl;
267 if (opt_ipath.empty() && env_ipath.empty()) {
268 usage(argv[0],
nullptr, ipath, opt_opath, username);
269 std::cerr << std::endl <<
"ERROR:" << std::endl;
270 std::cerr <<
" Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
271 <<
" environment variable to specify the location of the " << std::endl
272 <<
" image path where test images are located." << std::endl
288 cam.initPersProjWithDistortion(600, 600, 320, 240, -0.17, 0.17);
291 std::cout <<
"Read image: " <<
filename << std::endl;
294 std::cout <<
"Scale the image by a factor of " << scale << std::endl;
300 std::cout <<
"Input image: " << I.getWidth() <<
"x" << I.getHeight() << std::endl;
303 std::cout <<
"Nb threads to use for vpImageTools::undistort(): " << nThreads << std::endl;
305 double t_undistort = 0.0, t_remap = 0.0;
307 std::cout <<
"\nUndistortion in process (color image)... " << std::endl;
314 for (
unsigned int i = 0;
i < 10;
i++)
319 t_undistort = endtime - begintime;
321 std::cout <<
"Time for 10 color image undistortion (ms): " << t_undistort << std::endl;
325 std::cout <<
"Undistortion in process with remap (color image)... " << std::endl;
333 for (
unsigned int i = 0;
i < 10;
i++) {
341 t_remap = endtime - begintime;
343 std::cout <<
"Time for 10 color image undistortion with remap (ms): " << t_remap << std::endl;
344 std::cout <<
"Speed-up: " << t_undistort / t_remap <<
"X" << std::endl;
348 std::cout <<
"\nUndistortion in process (gray image)... " << std::endl;
355 for (
unsigned int i = 0;
i < 100;
i++)
360 t_undistort = endtime - begintime;
362 std::cout <<
"Time for 100 gray image undistortion (ms): " << t_undistort << std::endl;
366 std::cout <<
"Undistortion in process with remap (gray image)... " << std::endl;
374 for (
unsigned int i = 0;
i < 10;
i++) {
382 t_remap = endtime - begintime;
384 std::cout <<
"Time for 100 gray image undistortion with remap (ms): " << t_remap << std::endl;
385 std::cout <<
"Speed-up: " << t_undistort / t_remap <<
"X" << std::endl;
390 std::cout <<
"\nWrite undistorted image: " <<
filename << std::endl;
394 std::cout <<
"Write undistorted image: " <<
filename << std::endl;
398 std::cout <<
"\nWrite undistorted image with remap: " <<
filename << std::endl;
402 std::cout <<
"Write undistorted image with remap: " <<
filename << std::endl;
408 double mean_diff = 0.0;
409 for (
unsigned int i = 0;
i < U_diff_abs.
getHeight();
i++) {
410 for (
unsigned int j = 0;
j < U_diff_abs.
getWidth();
j++) {
411 mean_diff += U_diff_abs[
i][
j].R;
412 mean_diff += U_diff_abs[
i][
j].G;
413 mean_diff += U_diff_abs[
i][
j].B;
414 mean_diff += U_diff_abs[
i][
j].A;
417 double remap_mean_error = mean_diff / (4 * U_diff_abs.
getSize());
418 std::cout <<
"U_diff_abs mean value: " << remap_mean_error << std::endl;
419 const double remap_error_threshold = 0.5;
420 if (remap_mean_error > remap_error_threshold) {
421 std::cerr <<
"Issue with vpImageTools::remap() with vpRGBa image" << std::endl;
427 double remap_mean_error_gray = U_diff_gray_abs.
getSum() / U_diff_gray_abs.
getSize();
428 std::cout <<
"U_diff_gray_abs mean value: " << remap_mean_error_gray << std::endl;
429 if (remap_mean_error_gray > remap_error_threshold) {
430 std::cerr <<
"Issue with vpImageTools::remap() with unsigned char image" << std::endl;
439 std::cout <<
"\nWrite undistorted image: " <<
filename << std::endl;
444 std::cout <<
"Write undistorted image: " <<
filename << std::endl;
450 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.
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.
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()