Visual Servoing Platform  version 3.4.1 under development (2021-09-25)
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 ", name);
96 
97  fprintf(stdout, "\n\
98 OPTIONS: Default\n\
99  -i <input image path> %s\n\
100  Set image input path.\n\
101  From this path read \"Klimt/Klimt.pgm\"\n\
102  image.\n\
103  Setting the VISP_INPUT_IMAGE_PATH environment\n\
104  variable produces the same behaviour than using\n\
105  this option.\n\
106 \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  Klimt_grey.overlay.ppm output image is written.\n\
112 \n\
113  -c\n\
114  Disable the mouse click. Useful to automate the \n\
115  execution of this program without humain intervention.\n\
116 \n\
117  -d \n\
118  Disable the image display. This can be useful \n\
119  for automatic tests using crontab under Unix or \n\
120  using the task manager under Windows.\n\
121 \n\
122  -h\n\
123  Print the help.\n\n", ipath.c_str(), opath.c_str(), user.c_str());
124 
125  if (badparam) {
126  fprintf(stderr, "ERROR: \n");
127  fprintf(stderr, "\nBad parameter [%s]\n", badparam);
128  }
129 }
130 
149 bool getOptions(int argc, const char **argv, std::string &ipath, std::string &opath, bool &click_allowed,
150  const std::string &user, bool &display)
151 {
152  const char *optarg_;
153  int c;
154  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
155 
156  switch (c) {
157  case 'c':
158  click_allowed = false;
159  break;
160  case 'd':
161  display = false;
162  break;
163  case 'i':
164  ipath = optarg_;
165  break;
166  case 'o':
167  opath = optarg_;
168  break;
169  case 'h':
170  usage(argv[0], NULL, ipath, opath, user);
171  return false;
172  break;
173 
174  default:
175  usage(argv[0], optarg_, ipath, opath, user);
176  return false;
177  break;
178  }
179  }
180 
181  if ((c == 1) || (c == -1)) {
182  // standalone param or error
183  usage(argv[0], NULL, ipath, opath, user);
184  std::cerr << "ERROR: " << std::endl;
185  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
186  return false;
187  }
188 
189  return true;
190 }
191 
192 int main(int argc, const char **argv)
193 {
194  try {
195  std::string env_ipath;
196  std::string opt_ipath;
197  std::string opt_opath;
198  std::string ipath;
199  std::string opath;
200  std::string filename;
201  std::string username;
202  bool opt_click_allowed = true;
203  bool opt_display = true;
204 
205  // Get the visp-images-data package path or VISP_INPUT_IMAGE_PATH
206  // environment variable value
207  env_ipath = vpIoTools::getViSPImagesDataPath();
208 
209  // Set the default input path
210  if (!env_ipath.empty())
211  ipath = env_ipath;
212 
213 // Set the default output path
214 #if !defined(_WIN32) && (defined(__unix__) || defined(__unix) || (defined(__APPLE__) && defined(__MACH__))) // UNIX
215  opt_opath = "/tmp";
216 #elif defined(_WIN32)
217  opt_opath = "C:\\temp";
218 #endif
219 
220  // Get the user login name
221  vpIoTools::getUserName(username);
222 
223  // Read the command line options
224  if (getOptions(argc, argv, opt_ipath, opt_opath, opt_click_allowed, username, opt_display) == false) {
225  exit(-1);
226  }
227 
228  // Get the option values
229  if (!opt_ipath.empty())
230  ipath = opt_ipath;
231  if (!opt_opath.empty())
232  opath = opt_opath;
233 
234  // Append to the output path string, the login name of the user
235  std::string odirname = vpIoTools::createFilePath(opath, username);
236 
237  // Test if the output path exist. If no try to create it
238  if (vpIoTools::checkDirectory(odirname) == false) {
239  try {
240  // Create the dirname
241  vpIoTools::makeDirectory(odirname);
242  } catch (...) {
243  usage(argv[0], NULL, ipath, opath, username);
244  std::cerr << std::endl << "ERROR:" << std::endl;
245  std::cerr << " Cannot create " << odirname << std::endl;
246  std::cerr << " Check your -o " << opath << " option " << std::endl;
247  exit(-1);
248  }
249  }
250 
251  // Compare ipath and env_ipath. If they differ, we take into account
252  // the input path comming from the command line option
253  if (!opt_ipath.empty() && !env_ipath.empty()) {
254  if (ipath != env_ipath) {
255  std::cout << std::endl << "WARNING: " << std::endl;
256  std::cout << " Since -i <visp image path=" << ipath << "> "
257  << " is different from VISP_IMAGE_PATH=" << env_ipath << std::endl
258  << " we skip the environment variable." << std::endl;
259  }
260  }
261 
262  // Test if an input path is set
263  if (opt_ipath.empty() && env_ipath.empty()) {
264  usage(argv[0], NULL, ipath, opath, username);
265  std::cerr << std::endl << "ERROR:" << std::endl;
266  std::cerr << " Use -i <visp image path> option or set VISP_INPUT_IMAGE_PATH " << std::endl
267  << " environment variable to specify the location of the " << std::endl
268  << " image path where test images are located." << std::endl
269  << std::endl;
270  exit(-1);
271  }
272 
273  // Create a grey level image
275  vpImagePoint ip, ip1, ip2;
276 
277  // Load a grey image from the disk
278  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.pgm");
279  vpImageIo::read(I, filename);
280 
281  // Create a display using X11
282  vpDisplayOpenCV display;
283 
284  if (opt_display) {
285  // For this grey level image, open a X11 display at position 100,100
286  // in the screen, and with title "X11 display"
287  display.init(I, 100, 100, "X11 display");
288 
289  // Display the image
291 
292  // Display in overlay a red cross at position 10,10 in the
293  // image. The lines are 10 pixels long
294  ip.set_i(100);
295  ip.set_j(10);
296 
298 
299  // Display in overlay horizontal red lines
300  for (unsigned i = 0; i < I.getHeight(); i += 20) {
301  ip1.set_i(i);
302  ip1.set_j(0);
303  ip2.set_i(i);
304  ip2.set_j(I.getWidth());
305  vpDisplay::displayLine(I, ip1, ip2, vpColor::red);
306  }
307 
308  // Display a ligne in the diagonal
309  ip1.set_i(-10);
310  ip1.set_j(-10);
311  ip2.set_i(I.getHeight() + 10);
312  ip2.set_j(I.getWidth() + 10);
313 
314  vpDisplay::displayLine(I, ip1, ip2, vpColor::red);
315 
316  // Display in overlay vertical green dot lines
317  for (unsigned i = 0; i < I.getWidth(); i += 20) {
318  ip1.set_i(0);
319  ip1.set_j(i);
320  ip2.set_i(I.getWidth());
321  ip2.set_j(i);
323  }
324 
325  // Display a transparent rectangle
326  ip.set_i(I.getHeight() - 45);
327  ip.set_j(-10);
328  vpDisplay::displayRectangle(I, ip, 60, 80, vpColor(vpColor::orange, 127), true, 2U);
329 
330  // Display a transparent circle onto the image
331  vpColor transparent_red(vpColor::red, 127);
332  vpDisplay::displayCircle(I, vpImagePoint(I.getHeight() / 3, I.getWidth() / 2), I.getHeight() / 4,
333  transparent_red, true);
334 
335  // Display a second transparent circle
336  vpColor very_transparent_blue(0, 0, 255, 63);
337  vpDisplay::displayCircle(I, vpImagePoint(2 * I.getHeight() / 3, I.getWidth() / 2), I.getHeight() / 4,
338  very_transparent_blue, true);
339 
340  // Display in overlay a blue arrow
341  ip1.set_i(0);
342  ip1.set_j(0);
343  ip2.set_i(100);
344  ip2.set_j(100);
346 
347  // Display in overlay some circles. The position of the center is 200,
348  // 200 the radius is increased by 20 pixels for each circle
349 
350  for (unsigned int i = 0; i < 100; i += 20) {
351  ip.set_i(80);
352  ip.set_j(80);
354  }
355 
356  ip.set_i(-10);
357  ip.set_j(300);
359 
360  // Display in overlay a yellow string
361  ip.set_i(85);
362  ip.set_j(100);
363  vpDisplay::displayText(I, ip, "ViSP is a marvelous software", vpColor::yellow);
364  // Flush the display
365  vpDisplay::flush(I);
366 
367  // Create a color image
368  vpImage<vpRGBa> Ioverlay;
369  // Updates the color image with the original loaded image and the
370  // overlay
371  vpDisplay::getImage(I, Ioverlay);
372 
373  // Write the color image on the disk
374  filename = vpIoTools::createFilePath(odirname, "Klimt_grey.overlay.ppm");
375  vpImageIo::write(Ioverlay, filename);
376 
377  // If click is allowed, wait for a mouse click to close the display
378  if (opt_click_allowed) {
379  std::cout << "\nA click to close the windows..." << std::endl;
380  // Wait for a blocking mouse click
382  }
383 
384  // Close the display
385  vpDisplay::close(I);
386  }
387 
388  // Create a color image
389  vpImage<vpRGBa> Irgba;
390 
391  // Load a grey image from the disk and convert it to a color image
392  filename = vpIoTools::createFilePath(ipath, "Klimt/Klimt.ppm");
393  vpImageIo::read(Irgba, filename);
394 
395  // Create a new display
396  vpDisplayOpenCV displayRGBa;
397 
398  if (opt_display) {
399  // For this color image, open a X11 display at position 100,100
400  // in the screen, and with title "X11 color display"
401  displayRGBa.init(Irgba, 100, 100, "X11 color display");
402 
403  // Display the color image
404  vpDisplay::display(Irgba);
405  vpDisplay::flush(Irgba);
406 
407  // If click is allowed, wait for a blocking mouse click to display a
408  // cross at the clicked pixel position
409  if (opt_click_allowed) {
410  std::cout << "\nA click to display a cross..." << std::endl;
411  // Blocking wait for a click. Get the position of the selected pixel
412  // (i correspond to the row and j to the column coordinates in the
413  // image)
414  vpDisplay::getClick(Irgba, ip);
415  // Display a red cross on the click pixel position
416  std::cout << "Cross position: " << ip << std::endl;
417  vpDisplay::displayCross(Irgba, ip, 15, vpColor::red);
418  } else {
419  ip.set_i(10);
420  ip.set_j(20);
421  // Display a red cross at position i, j (i correspond to the row
422  // and j to the column coordinates in the image)
423  std::cout << "Cross position: " << ip << std::endl;
424  vpDisplay::displayCross(Irgba, ip, 15, vpColor::red);
425  }
426  // Flush the display. Sometimes the display content is
427  // bufferized. Force to display the content that has been bufferized.
428  vpDisplay::flush(Irgba);
429 
430  // Create a color image
431  vpImage<vpRGBa> Ioverlay;
432  // Updates the color image with the original loaded image and the
433  // overlay
434  vpDisplay::getImage(Irgba, Ioverlay);
435 
436  // Write the color image on the disk
437  filename = vpIoTools::createFilePath(odirname, "Klimt_color.overlay.ppm");
438  vpImageIo::write(Ioverlay, filename);
439 
440  // If click is allowed, wait for a blocking mouse click to exit.
441  if (opt_click_allowed) {
442  std::cout << "\nA click to exit the program..." << std::endl;
443  vpDisplay::getClick(Irgba);
444  std::cout << "Bye" << std::endl;
445  }
446  }
447  return EXIT_SUCCESS;
448  } catch (const vpException &e) {
449  std::cout << "Catch an exception: " << e << std::endl;
450  return EXIT_FAILURE;
451  }
452 }
453 #else
454 int main()
455 {
456  std::cout << "You do not have OpenCV functionalities to display images..." << std::endl;
457  std::cout << "Tip:" << std::endl;
458  std::cout << "- Install OpenCV, configure again ViSP using cmake and build again this example" << std::endl;
459  return EXIT_SUCCESS;
460 }
461 #endif
static void makeDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:482
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static std::string getViSPImagesDataPath()
Definition: vpIoTools.cpp:1202
static void close(vpImage< unsigned char > &I)
Class to define RGB colors available for display functionnalities.
Definition: vpColor.h:157
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emited by ViSP classes.
Definition: vpException.h:71
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
static const vpColor green
Definition: vpColor.h:220
static void flush(const vpImage< unsigned char > &I)
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
static const vpColor red
Definition: vpColor.h:217
static const vpColor orange
Definition: vpColor.h:227
static bool checkDirectory(const std::string &dirname)
Definition: vpIoTools.cpp:332
static void write(const vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:445
static std::string createFilePath(const std::string &parent, const std::string &child)
Definition: vpIoTools.cpp:1446
void set_i(double ii)
Definition: vpImagePoint.h:166
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 display(const vpImage< unsigned char > &I)
The vpDisplayOpenCV allows to display image using the OpenCV library. Thus to enable this class OpenC...
static std::string getUserName()
Definition: vpIoTools.cpp:228
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 getImage(const vpImage< unsigned char > &Is, vpImage< vpRGBa > &Id)
Definition: vpDisplay.cpp:144
static void displayCircle(const vpImage< unsigned char > &I, const vpImagePoint &center, unsigned int radius, const vpColor &color, bool fill=false, unsigned int thickness=1)
void set_j(double jj)
Definition: vpImagePoint.h:177
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
unsigned int getHeight() const
Definition: vpImage.h:188
static void read(vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:244
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition: vpImagePoint.h:87
static const vpColor yellow
Definition: vpColor.h:225
unsigned int getWidth() const
Definition: vpImage.h:246
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 displayDotLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1)
static const vpColor blue
Definition: vpColor.h:223