Visual Servoing Platform  version 3.5.1 under development (2023-05-30)
displayOpenCV.cpp
1 /****************************************************************************
2  *
3  * ViSP, open source Visual Servoing Platform software.
4  * Copyright (C) 2005 - 2019 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  * See the file LICENSE.txt at the root directory of this source
11  * distribution for additional information about the GNU GPL.
12  *
13  * For using ViSP with software that can not be combined with the GNU
14  * GPL, please contact Inria about acquiring a ViSP Professional
15  * Edition License.
16  *
17  * See http://visp.inria.fr for more information.
18  *
19  * This software was developed at:
20  * Inria Rennes - Bretagne Atlantique
21  * Campus Universitaire de Beaulieu
22  * 35042 Rennes Cedex
23  * France
24  *
25  * If you have questions regarding the use of this file, please contact
26  * Inria at visp@inria.fr
27  *
28  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
29  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
30  *
31  * Description:
32  * Read an image on the disk and display it using OpenCV.
33  *
34  * Authors:
35  * Nicolas Melchior
36  *
37  *****************************************************************************/
47 #include <iostream>
48 #include <stdlib.h>
49 #include <visp3/core/vpConfig.h>
50 #include <visp3/core/vpDebug.h>
51 
52 #if defined(VISP_HAVE_OPENCV)
53 
54 #include <visp3/core/vpImage.h>
55 #include <visp3/core/vpIoTools.h>
56 #include <visp3/gui/vpDisplayOpenCV.h>
57 #include <visp3/io/vpImageIo.h>
58 #include <visp3/io/vpParseArgv.h>
59 
60 #include <visp3/core/vpTime.h>
61 
71 // List of allowed command line options
72 #define GETOPTARGS "cdi:o:p:h"
73 
85 void usage(const char *name, const char *badparam, std::string ipath, std::string opath, std::string user)
86 {
87  fprintf(stdout, "\n\
88 Read an image on the disk, display it using OpenCV, display some\n\
89 features (line, circle, caracters) in overlay and finaly write \n\
90 the image and the overlayed features in an image on the disk.\n\
91 \n\
92 SYNOPSIS\n\
93  %s [-i <input image path>] [-o <output image path>]\n\
94  [-c] [-d] [-h]\n \
95 ",
96  name);
97 
98  fprintf(stdout, "\n\
99 OPTIONS: Default\n\
100  -i <input image path> %s\n\
101  Set image input path.\n\
102  From this path read \"Klimt/Klimt.pgm\"\n\
103  image.\n\
104  Setting the VISP_INPUT_IMAGE_PATH environment\n\
105  variable produces the same behaviour than using\n\
106  this option.\n\
107 \n\
108  -o <output image path> %s\n\
109  Set image output path.\n\
110  From this directory, creates the \"%s\"\n\
111  subdirectory depending on the username, where \n\
112  Klimt_grey.overlay.ppm output image is written.\n\
113 \n\
114  -c\n\
115  Disable the mouse click. Useful to automate the \n\
116  execution of this program without humain intervention.\n\
117 \n\
118  -d \n\
119  Disable the image display. This can be useful \n\
120  for automatic tests using crontab under Unix or \n\
121  using the task manager under Windows.\n\
122 \n\
123  -h\n\
124  Print the help.\n\n",
125  ipath.c_str(), opath.c_str(), user.c_str());
126 
127  if (badparam) {
128  fprintf(stderr, "ERROR: \n");
129  fprintf(stderr, "\nBad parameter [%s]\n", badparam);
130  }
131 }
132 
151 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &opath, bool &click_allowed,
152  const std::string &user, bool &display)
153 {
154  const char *optarg_;
155  int c;
156  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
157 
158  switch (c) {
159  case 'c':
160  click_allowed = false;
161  break;
162  case 'd':
163  display = false;
164  break;
165  case 'i':
166  ipath = optarg_;
167  break;
168  case 'o':
169  opath = optarg_;
170  break;
171  case 'h':
172  usage(argv[0], NULL, ipath, opath, user);
173  return false;
174  break;
175 
176  default:
177  usage(argv[0], optarg_, ipath, opath, user);
178  return false;
179  break;
180  }
181  }
182 
183  if ((c == 1) || (c == -1)) {
184  // standalone param or error
185  usage(argv[0], NULL, ipath, opath, user);
186  std::cerr << "ERROR: " << std::endl;
187  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
188  return false;
189  }
190 
191  return true;
192 }
193 
194 int main(int argc, const char **argv)
195 {
196  try {
197  std::string env_ipath;
198  std::string opt_ipath;
199  std::string opt_opath;
200  std::string ipath;
201  std::string opath;
202  std::string filename;
203  std::string username;
204  bool opt_click_allowed = true;
205  bool opt_display = true;
206 
207  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
208  // environment variable value
209  env_ipath = vpIoTools::getViSPImagesDataPath();
210 
211  // Set the default input path
212  if (!env_ipath.empty())
213  ipath = env_ipath;
214 
215 // Set the default output path
216 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
217  opt_opath = "/tmp";
218 #elif defined(_WIN32)
219  opt_opath = "C:\\temp";
220 #endif
221 
222  // Get the user login name
223  vpIoTools::getUserName(username);
224 
225  // Read the command line options
226  if (getOptions(argc, argv, opt_ipath, opt_opath, opt_click_allowed, username, opt_display) == false) {
227  return EXIT_FAILURE;
228  }
229 
230  // Get the option values
231  if (!opt_ipath.empty())
232  ipath = opt_ipath;
233  if (!opt_opath.empty())
234  opath = opt_opath;
235 
236  // Append to the output path string, the login name of the user
237  std::string odirname = vpIoTools::createFilePath(opath, username);
238 
239  // Test if the output path exist. If no try to create it
240  if (vpIoTools::checkDirectory(odirname) == false) {
241  try {
242  // Create the dirname
243  vpIoTools::makeDirectory(odirname);
244  } catch (...) {
245  usage(argv[0], NULL, ipath, opath, username);
246  std::cerr << std::endl << "ERROR:" << std::endl;
247  std::cerr << " Cannot create " << odirname << std::endl;
248  std::cerr << " Check your -o " << opath << " option " << std::endl;
249  return EXIT_FAILURE;
250  }
251  }
252 
253  // Compare ipath and env_ipath. If they differ, we take into account
254  // the input path comming from the command line option
255  if (!opt_ipath.empty() && !env_ipath.empty()) {
256  if (ipath != env_ipath) {
257  std::cout << std::endl << "WARNING: " << std::endl;
258  std::cout << " Since -i <visp image path=" << ipath << "> "
259  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
260  << " we skip the environment variable." << std::endl;
261  }
262  }
263 
264  // Test if an input path is set
265  if (opt_ipath.empty() && env_ipath.empty()) {
266  usage(argv[0], NULL, ipath, opath, username);
267  std::cerr << std::endl << "ERROR:" << std::endl;
268  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
269  << " environment variable to specify the location of the " << std::endl
270  << " image path where test images are located." << std::endl
271  << std::endl;
272  return EXIT_FAILURE;
273  }
274 
275  // Create a grey level image
277  vpImagePoint ip, ip1, ip2;
278 
279  // Load a grey image from the disk
280  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
281  vpImageIo::read(I, filename);
282 
283  // Create a display using X11
284  vpDisplayOpenCV display;
285 
286  if (opt_display) {
287  // For this grey level image, open a X11 display at position 100,100
288  // in the screen, and with title "X11 display"
289  display.init(I, 100, 100, "X11 display");
290 
291  // Display the image
293 
294  // Display in overlay a red cross at position 10,10 in the
295  // image. The lines are 10 pixels long
296  ip.set_i(100);
297  ip.set_j(10);
298 
300 
301  // Display in overlay horizontal red lines
302  for (unsigned i = 0; i < I.getHeight(); i += 20) {
303  ip1.set_i(i);
304  ip1.set_j(0);
305  ip2.set_i(i);
306  ip2.set_j(I.getWidth());
307  vpDisplay::displayLine(I, ip1, ip2, vpColor::red);
308  }
309 
310  // Display a ligne in the diagonal
311  ip1.set_i(-10);
312  ip1.set_j(-10);
313  ip2.set_i(I.getHeight() + 10);
314  ip2.set_j(I.getWidth() + 10);
315 
316  vpDisplay::displayLine(I, ip1, ip2, vpColor::red);
317 
318  // Display in overlay vertical green dot lines
319  for (unsigned i = 0; i < I.getWidth(); i += 20) {
320  ip1.set_i(0);
321  ip1.set_j(i);
322  ip2.set_i(I.getWidth());
323  ip2.set_j(i);
325  }
326 
327  // Display a transparent rectangle
328  ip.set_i(I.getHeight() - 45);
329  ip.set_j(-10);
330  vpDisplay::displayRectangle(I, ip, 60, 80, vpColor(vpColor::orange, 127), true, 2U);
331 
332  // Display a transparent circle onto the image
333  vpColor transparent_red(vpColor::red, 127);
334  vpDisplay::displayCircle(I, vpImagePoint(I.getHeight() / 3, I.getWidth() / 2), I.getHeight() / 4, transparent_red,
335  true);
336 
337  // Display a second transparent circle
338  vpColor very_transparent_blue(0, 0, 255, 63);
339  vpDisplay::displayCircle(I, vpImagePoint(2 * I.getHeight() / 3, I.getWidth() / 2), I.getHeight() / 4,
340  very_transparent_blue, true);
341 
342  // Display in overlay a blue arrow
343  ip1.set_i(0);
344  ip1.set_j(0);
345  ip2.set_i(100);
346  ip2.set_j(100);
348 
349  // Display in overlay some circles. The position of the center is 200,
350  // 200 the radius is increased by 20 pixels for each circle
351 
352  for (unsigned int i = 0; i < 100; i += 20) {
353  ip.set_i(80);
354  ip.set_j(80);
356  }
357 
358  ip.set_i(-10);
359  ip.set_j(300);
361 
362  // Display in overlay a yellow string
363  ip.set_i(85);
364  ip.set_j(100);
365  vpDisplay::displayText(I, ip, "ViSP is a marvelous software", vpColor::yellow);
366  // Flush the display
367  vpDisplay::flush(I);
368 
369  // Create a color image
370  vpImage<vpRGBa> Ioverlay;
371  // Updates the color image with the original loaded image and the
372  // overlay
373  vpDisplay::getImage(I, Ioverlay);
374 
375  // Write the color image on the disk
376  filename = vpIoTools::createFilePath(odirname, "Klimt_grey.overlay.ppm");
377  vpImageIo::write(Ioverlay, filename);
378 
379  // If click is allowed, wait for a mouse click to close the display
380  if (opt_click_allowed) {
381  std::cout << "\nA click to close the windows..." << std::endl;
382  // Wait for a blocking mouse click
384  }
385 
386  // Close the display
387  vpDisplay::close(I);
388  }
389 
390  // Create a color image
391  vpImage<vpRGBa> Irgba;
392 
393  // Load a grey image from the disk and convert it to a color image
394  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
395  vpImageIo::read(Irgba, filename);
396 
397  // Create a new display
398  vpDisplayOpenCV displayRGBa;
399 
400  if (opt_display) {
401  // For this color image, open a X11 display at position 100,100
402  // in the screen, and with title "X11 color display"
403  displayRGBa.init(Irgba, 100, 100, "X11 color display");
404 
405  // Display the color image
406  vpDisplay::display(Irgba);
407  vpDisplay::flush(Irgba);
408 
409  // If click is allowed, wait for a blocking mouse click to display a
410  // cross at the clicked pixel position
411  if (opt_click_allowed) {
412  std::cout << "\nA click to display a cross..." << std::endl;
413  // Blocking wait for a click. Get the position of the selected pixel
414  // (i correspond to the row and j to the column coordinates in the
415  // image)
416  vpDisplay::getClick(Irgba, ip);
417  // Display a red cross on the click pixel position
418  std::cout << "Cross position: " << ip << std::endl;
419  vpDisplay::displayCross(Irgba, ip, 15, vpColor::red);
420  } else {
421  ip.set_i(10);
422  ip.set_j(20);
423  // Display a red cross at position i, j (i correspond to the row
424  // and j to the column coordinates in the image)
425  std::cout << "Cross position: " << ip << std::endl;
426  vpDisplay::displayCross(Irgba, ip, 15, vpColor::red);
427  }
428  // Flush the display. Sometimes the display content is
429  // bufferized. Force to display the content that has been bufferized.
430  vpDisplay::flush(Irgba);
431 
432  // Create a color image
433  vpImage<vpRGBa> Ioverlay;
434  // Updates the color image with the original loaded image and the
435  // overlay
436  vpDisplay::getImage(Irgba, Ioverlay);
437 
438  // Write the color image on the disk
439  filename = vpIoTools::createFilePath(odirname, "Klimt_color.overlay.ppm");
440  vpImageIo::write(Ioverlay, filename);
441 
442  // If click is allowed, wait for a blocking mouse click to exit.
443  if (opt_click_allowed) {
444  std::cout << "\nA click to exit the program..." << std::endl;
445  vpDisplay::getClick(Irgba);
446  std::cout << "Bye" << std::endl;
447  }
448  }
449  return EXIT_SUCCESS;
450  } catch (const vpException &e) {
451  std::cout << "Catch an exception: " << e << std::endl;
452  return EXIT_FAILURE;
453  }
454 }
455 #else
456 int main()
457 {
458  std::cout << "You do not have OpenCV functionalities to display images..." << std::endl;
459  std::cout << "Tip:" << std::endl;
460  std::cout << "- Install OpenCV, configure again ViSP using cmake and build again this example" << std::endl;
461  return EXIT_SUCCESS;
462 }
463 #endif
Class to define RGB colors available for display functionnalities.
Definition: vpColor.h:158
static const vpColor red
Definition: vpColor.h:217
static const vpColor orange
Definition: vpColor.h:227
static const vpColor blue
Definition: vpColor.h:223
static const vpColor yellow
Definition: vpColor.h:225
static const vpColor green
Definition: vpColor.h:220
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
static void close(vpImage< unsigned char > &I)
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
static void getImage(const vpImage< unsigned char > &Is, vpImage< vpRGBa > &Id)
Definition: vpDisplay.cpp:144
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
static void flush(const vpImage< unsigned char > &I)
static void displayArrow(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color=vpColor::white, unsigned int w=4, unsigned int h=2, unsigned int thickness=1)
static void displayDotLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
static void displayRectangle(const vpImage< unsigned char > &I, const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
static void displayCircle(const vpImage< unsigned char > &I, const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1)
error that can be emited by ViSP classes.
Definition: vpException.h:72
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:148
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:292
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:89
void set_j(double jj)
Definition: vpImagePoint.h:309
void set_i(double ii)
Definition: vpImagePoint.h:298
unsigned int getWidth() const
Definition: vpImage.h:247
unsigned int getHeight() const
Definition: vpImage.h:189
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1399
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:435
static std::string getUserName()
Definition: vpIoTools.cpp:328
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1764
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:585
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69