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