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