Visual Servoing Platform  version 3.5.0 under development (2022-02-15)
grabV4l2.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  * Acquire images using 1394 device with cfox (MAC OSX) and display it
33  * using GTK or GTK.
34  *
35  * Authors:
36  * Fabien Spindler
37  *
38  *****************************************************************************/
39 
40 #include <stdlib.h>
41 #include <visp3/core/vpConfig.h>
42 #include <visp3/core/vpDebug.h>
50 #ifdef VISP_HAVE_V4L2
51 
52 #if (defined(VISP_HAVE_X11) || defined(VISP_HAVE_GTK))
53 
54 #include <visp3/core/vpDisplay.h>
55 #include <visp3/core/vpImage.h>
56 #include <visp3/core/vpTime.h>
57 #include <visp3/gui/vpDisplayGTK.h>
58 #include <visp3/gui/vpDisplayX.h>
59 #include <visp3/io/vpImageIo.h>
60 #include <visp3/io/vpParseArgv.h>
61 #include <visp3/sensor/vpV4l2Grabber.h>
62 
63 // List of allowed command line options
64 #define GETOPTARGS "df:i:hn:o:p:s:t:v:x"
65 
66 typedef enum {
67  grey_image = 0, // for ViSP unsigned char grey images
68  color_image // for ViSP vpRGBa color images
69 } vpImage_type;
70 
87 void usage(const char *name, const char *badparam, unsigned fps, unsigned input, unsigned scale, long niter,
88  char *device, vpV4l2Grabber::vpV4l2PixelFormatType pixelformat, const vpImage_type &image_type,
89  const std::string &opath)
90 {
91  fprintf(stdout, "\n\
92 Grab grey level images using the Video For Linux Two framegrabber. \n\
93 Display these images using X11 or GTK.\n\
94 \n\
95 SYNOPSIS\n\
96  %s [-v <video device>] [-f <fps=25|50>] \n\
97  [-i <input=0|1|2|3> [-s <scale=1|2|4>] [-p <pixel format>]\n\
98  [-n <niter>] [-t <image type>] [-o <filename>] [-x] [-d] [-h]\n", name);
99 
100  fprintf(stdout, "\n\
101 OPTIONS: Default\n\
102  -v <video device> %s\n\
103  Video device to access to the camera\n\
104 \n\
105  -f <fps> %u\n\
106  Framerate in term od number of images per second.\n\
107  Possible values are 25 (for 25Hz) or 50 (for %%) Hz)\n\
108 \n\
109  -i <input> %u\n\
110  Framegrabber active input. Values can be 0, 1, 2, 4\n\
111 \n\
112  -p <pixel format> %d\n\
113  Camera pixel format. Values must be in [0-%d]:\n\
114  0 for gray format\n\
115  1 for RGB24 format\n\
116  2 for RGB32 format\n\
117  3 for BGR24 format\n\
118  4 for YUYV format\n\
119 \n\
120  -t <image type> %d\n\
121  Kind of images that are acquired/displayed by ViSP. \n\
122  Values must be in [0-1]:\n\
123  0 for grey images in unsigned char \n\
124  1 for color images in vpRGBa\n\
125 \n\
126  -s <scale> %u\n\
127  Framegrabber subsampling factor. \n\
128  If 1, full resolution image acquisition.\n\
129  If 2, half resolution image acquisition. The \n\
130  subsampling is achieved by the hardware.\n\
131 \n\
132  -n <niter> %ld\n\
133  Number of images to acquire.\n\
134 \n\
135  -d \n\
136  Turn off the display.\n\
137 \n\
138  -x \n\
139  Activates the extra verbose mode.\n\
140 \n\
141  -o [%%s] : Filename for image saving. \n\
142  Example: -o %s\n\
143  The %%d is for the image numbering. The format is set \n\
144  by the extension of the file (ex .png, .pgm, ...) \n\
145  \n\
146  -h \n\
147  Print the help.\n\n", device, fps, input, pixelformat, vpV4l2Grabber::V4L2_MAX_FORMAT - 1, image_type, scale, niter,
148  opath.c_str());
149 
150  if (badparam)
151  fprintf(stdout, "\nERROR: Bad parameter [%s]\n", badparam);
152 }
153 
175 bool getOptions(int argc, const char **argv, unsigned &fps, unsigned &input, unsigned &scale, bool &display,
176  bool &verbose, long &niter, char *device, vpV4l2Grabber::vpV4l2PixelFormatType &pixelformat,
177  vpImage_type &image_type, bool &save, std::string &opath)
178 {
179  const char *optarg_;
180  int c;
181  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
182 
183  switch (c) {
184  case 'd':
185  display = false;
186  break;
187  case 'f':
188  fps = (unsigned)atoi(optarg_);
189  break;
190  case 'i':
191  input = (unsigned)atoi(optarg_);
192  break;
193  case 'n':
194  niter = atol(optarg_);
195  break;
196  case 'o':
197  save = true;
198  opath = optarg_;
199  break;
200  case 'p':
201  pixelformat = (vpV4l2Grabber::vpV4l2PixelFormatType)atoi(optarg_);
202  break;
203  case 's':
204  scale = (unsigned)atoi(optarg_);
205  break;
206  case 't':
207  image_type = (vpImage_type)atoi(optarg_);
208  break;
209  case 'v':
210  sprintf(device, "%s", optarg_);
211  break;
212  case 'x':
213  verbose = true;
214  break;
215  case 'h':
216  usage(argv[0], NULL, fps, input, scale, niter, device, pixelformat, image_type, opath);
217  return false;
218  break;
219 
220  default:
221  usage(argv[0], optarg_, fps, input, scale, niter, device, pixelformat, image_type, opath);
222  return false;
223  break;
224  }
225  }
226 
227  if ((c == 1) || (c == -1)) {
228  // standalone param or error
229  usage(argv[0], NULL, fps, input, scale, niter, device, pixelformat, image_type, opath);
230  std::cerr << "ERROR: " << std::endl;
231  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
232  return false;
233  }
234 
235  return true;
236 }
237 
247 int main(int argc, const char **argv)
248 {
249  try {
250  unsigned int opt_fps = 25;
251  unsigned int opt_input = 0;
252  unsigned int opt_scale = 1;
254  long opt_iter = 100;
255  bool opt_verbose = false;
256  bool opt_display = true;
257  char opt_device[20];
258  bool opt_save = false;
259  sprintf(opt_device, "/dev/video0");
260  // Default output path for image saving
261  std::string opt_opath = "/tmp/I%04d.ppm";
262 
263  vpImage_type opt_image_type = color_image;
264 
265  // Read the command line options
266  if (getOptions(argc, argv, opt_fps, opt_input, opt_scale, opt_display, opt_verbose, opt_iter, opt_device,
267  opt_pixelformat, opt_image_type, opt_save, opt_opath) == false) {
268  exit(-1);
269  }
270 
271  // Declare an image, this is a gray level image (unsigned char) and
272  // an other one that is a color image. There size is not defined
273  // yet. It will be defined when the image will acquired the first
274  // time.
275  vpImage<unsigned char> Ig; // grey level image
276  vpImage<vpRGBa> Ic; // color image
277 
278  // Creates the grabber
279  vpV4l2Grabber g;
280 
281  // Initialize the grabber
282  g.setVerboseMode(opt_verbose);
283  g.setDevice(opt_device);
284  g.setInput(opt_input);
285  g.setScale(opt_scale);
286  g.setPixelFormat(opt_pixelformat);
287  if (opt_fps == 25)
289  else
291  if (opt_image_type == grey_image) {
292  // Open the framegrabber with the specified settings on grey images
293  g.open(Ig);
294  // Acquire an image
295  g.acquire(Ig);
296  std::cout << "Grey image size: width : " << Ig.getWidth() << " height: " << Ig.getHeight() << std::endl;
297  } else {
298  // Open the framegrabber with the specified settings on color images
299  g.open(Ic);
300  // Acquire an image
301  g.acquire(Ic);
302  std::cout << "Color image size: width : " << Ic.getWidth() << " height: " << Ic.getHeight() << std::endl;
303  }
304 
305 // We open a window using either X11 or GTK.
306 // Its size is automatically defined by the image (I) size
307 #if defined VISP_HAVE_X11
308  vpDisplayX display;
309 #elif defined VISP_HAVE_GTK
310  vpDisplayGTK display;
311 #endif
312 
313  if (opt_display) {
314  // Display the image
315  // The image class has a member that specify a pointer toward
316  // the display that has been initialized in the display declaration
317  // therefore is is no longuer necessary to make a reference to the
318  // display variable.
319  if (opt_image_type == grey_image) {
320  display.init(Ig, 100, 100, "V4L2 grey images framegrabbing");
321  vpDisplay::display(Ig);
322  vpDisplay::flush(Ig);
323  } else {
324  display.init(Ic, 100, 100, "V4L2 color images framegrabbing");
325  vpDisplay::display(Ic);
326  vpDisplay::flush(Ic);
327  }
328  }
329  // Acquisition loop
330  long cpt = 1;
331  while (cpt++ < opt_iter) {
332  // Measure the initial time of an iteration
333  double t = vpTime::measureTimeMs();
334  // Acquire the image
335  if (opt_image_type == grey_image) {
336  g.acquire(Ig);
337  if (opt_display) {
338  // Display the image
339  vpDisplay::display(Ig);
340  // Flush the display
341  vpDisplay::flush(Ig);
342  }
343  } else {
344  g.acquire(Ic);
345  if (opt_display) {
346  // Display the image
347  vpDisplay::display(Ic);
348  // Flush the display
349  vpDisplay::flush(Ic);
350  }
351  }
352 
353  if (opt_save) {
354  char buf[FILENAME_MAX];
355  sprintf(buf, opt_opath.c_str(), cpt);
356  std::string filename(buf);
357  std::cout << "Write: " << filename << std::endl;
358  if (opt_image_type == grey_image) {
359  vpImageIo::write(Ig, filename);
360  } else {
361  vpImageIo::write(Ic, filename);
362  }
363  }
364 
365  // Print the iteration duration
366  std::cout << "time: " << vpTime::measureTimeMs() - t << " (ms)" << std::endl;
367  }
368 
369  g.close();
370  return EXIT_SUCCESS;
371  } catch (const vpException &e) {
372  std::cout << "Catch an exception: " << e << std::endl;
373  return EXIT_FAILURE;
374  }
375 }
376 #else
377 int main()
378 {
379  std::cout << "You do not have X11, or GTK functionalities to display images..." << std::endl;
380  std::cout << "Tip if you are on a unix-like system:" << std::endl;
381  std::cout << "- Install X11, configure again ViSP using cmake and build again this example" << std::endl;
382  std::cout << "Tip if you are on a windows-like system:" << std::endl;
383  std::cout << "- Install GTK, configure again ViSP using cmake and build again this example" << std::endl;
384  return EXIT_SUCCESS;
385 }
386 #endif
387 #else
388 int main()
389 {
390  std::cout << "You do not have Video 4 Linux 2 functionality enabled" << std::endl;
391  std::cout << "Tip if you are on a unix-like system:" << std::endl;
392  std::cout << "- Install libv4l2, configure again ViSP using cmake and build again this example" << std::endl;
393  return EXIT_SUCCESS;
394 }
395 #endif
void acquire(vpImage< unsigned char > &I)
50 frames per second
void open(vpImage< unsigned char > &I)
Use the X11 console to display images on unix-like OS. Thus to enable this class X11 should be instal...
Definition: vpDisplayX.h:134
void setDevice(const std::string &devname)
error that can be emited by ViSP classes.
Definition: vpException.h:71
void setVerboseMode(bool verbose)
static void flush(const vpImage< unsigned char > &I)
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:293
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:126
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
static void display(const vpImage< unsigned char > &I)
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="")
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:134
void setScale(unsigned scale=vpV4l2Grabber::DEFAULT_SCALE)
void setInput(unsigned input=vpV4l2Grabber::DEFAULT_INPUT)
Class that is a wrapper over the Video4Linux2 (V4L2) driver.
unsigned int getHeight() const
Definition: vpImage.h:188
25 frames per second
unsigned int getWidth() const
Definition: vpImage.h:246
void setPixelFormat(vpV4l2PixelFormatType pixelformat)
void setFramerate(vpV4l2FramerateType framerate)