Visual Servoing Platform  version 3.6.1 under development (2024-11-15)
grabDirectShowMulti.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 DirectShow (under Windows only) and display it
33  * using GTK or GDI.
34  *
35 *****************************************************************************/
36 
37 #include <visp3/core/vpConfig.h>
38 #include <visp3/core/vpDebug.h>
39 
47 #include <iostream>
48 #include <sstream>
49 #include <vector>
50 
51 #if defined(VISP_HAVE_DIRECTSHOW)
52 #if (defined(VISP_HAVE_GTK) || defined(VISP_HAVE_GDI))
53 
54 #include <visp3/core/vpImage.h>
55 #include <visp3/core/vpTime.h>
56 #include <visp3/gui/vpDisplayGDI.h>
57 #include <visp3/gui/vpDisplayGTK.h>
58 #include <visp3/io/vpImageIo.h>
59 #include <visp3/io/vpParseArgv.h>
60 #include <visp3/sensor/vpDirectShowGrabber.h>
61 
62 // List of allowed command line options
63 #define GETOPTARGS "c:df:hmn:io:st:?"
64 
65 #define GRAB_COLOR
66 
67 #ifdef ENABLE_VISP_NAMESPACE
68 using namespace VISP_NAMESPACE_NAME;
69 #endif
70 
82 void usage(const char *name, const char *badparam, unsigned int camera, unsigned int &nframes, std::string &opath)
83 {
84  if (badparam)
85  fprintf(stderr, "\nERREUR: Bad parameter [%s]\n", badparam);
86 
87  fprintf(stdout, "\n\
88 Acquire images using DirectShow (under Windows only) and display\n\
89 it using GTK or the windows GDI if GTK is not available.\n\
90 For a given camera, mediatype (or video mode) as well as framerate\n\
91 can be set.\n\
92 If more than one camera is connected, this example allows also to \n\
93 acquire images from all the cameras.\n\
94 \n\
95 SYNOPSIS\n\
96 %s [-t <mediatype>] [-f <framerate>] \n\
97  [-c <camera id>] [-m] [-n <frames>] [-i] [-s] [-d] \n\
98  [-o <filename>] [-h]\n\
99  \n\
100 OPTIONS Default\n\
101  -t [%%u] \n\
102  MediaType (or video mode) to set for the active \n\
103  camera. Use -s option so see which are the supported \n\
104  Mediatypes. You can select the active camera \n\
105  using -c option.\n\
106 \n\
107  -f [%%d] \n\
108  Framerate to set for the active camera.\n\
109  You can select the active camera using -c option.\n",
110  name);
111 
112  fprintf(stdout, "\n\
113  -c [%%u] %u\n\
114  Active camera identifier.\n\
115  Zero is for the first camera found on the bus.\n\
116 \n\
117  -m \n\
118  Flag to active multi camera acquisition. \n\
119  You need at least two cameras connected on the bus.\n\
120 \n\
121  -n [%%u] %u\n\
122  Number of frames to acquire.\n\
123 \n\
124  -i \n\
125  Flag to print camera information.\n\
126 \n\
127  -s \n\
128  Print camera settings capabilities such as MediaType \n\
129  and sizes available and exit.\n\
130 \n\
131  -d \n\
132  Flag to turn off image display.\n\
133 \n\
134  -o [%%s] \n\
135  Filename for image saving. \n\
136  Example: -o %s\n\
137  The first %%d is for the camera id, %%04d\n\
138  is for the image numbering.\n\
139 \n\
140  -h \n\
141  Print the help.\n\
142 \n",
143 camera, nframes, opath.c_str());
144 
145  exit(0);
146 }
147 
173 void read_options(int argc, const char **argv, bool &multi, unsigned int &camera, unsigned int &nframes,
174  bool &verbose_info, bool &verbose_settings, bool &mediatype_is_set, unsigned int &mediatypeID,
175  bool &framerate_is_set, double &framerate, bool &display, bool &save, std::string &opath)
176 {
177  const char *optarg;
178  int c;
179  /*
180  * Lecture des options.
181  */
182 
183  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg)) > 1) {
184  switch (c) {
185  case 'c':
186  camera = atoi(optarg);
187  break;
188  case 'd':
189  display = false;
190  break;
191  case 'f':
192  framerate_is_set = true;
193  framerate = atoi(optarg);
194  break;
195  case 'i':
196  verbose_info = true;
197  break;
198  case 'm':
199  multi = true;
200  break;
201  case 'n':
202  nframes = atoi(optarg);
203  break;
204  case 'o':
205  save = true;
206  opath = optarg;
207  break;
208  case 's':
209  verbose_settings = true;
210  break;
211  case 't':
212  mediatype_is_set = true;
213  mediatypeID = atoi(optarg);
214  break;
215  default:
216  usage(argv[0], nullptr, camera, nframes, opath);
217  break;
218  }
219  }
220 
221  if ((c == 1) || (c == -1)) {
222  // standalone param or error
223  usage(argv[0], nullptr, camera, nframes, opath);
224  std::cerr << "ERROR: " << std::endl;
225  std::cerr << " Bad argument " << optarg << std::endl << std::endl;
226  }
227 }
228 
237 int main(int argc, const char **argv)
238 {
239  try {
240  unsigned int camera = 0;
241  bool multi = false;
242  bool verbose_info = false;
243  bool verbose_settings = false;
244  bool display = true;
245  unsigned int nframes = 50;
246  bool mediatype_is_set = false;
247  unsigned int mediatypeID;
248  bool framerate_is_set = false;
249  double framerate;
250  bool save = false;
251 
252 #ifdef GRAB_COLOR
253  vpImage<vpRGBa> *I;
254  std::string opath = "C:/temp/I%d-%04d.ppm";
255 #else
257  std::string opath = "C:/temp/I%d-%04d.pgm";
258 #endif
259 #if defined(VISP_HAVE_GDI)
260 
261  vpDisplayGDI *d;
262 #elif defined(VISP_HAVE_GTK)
263  vpDisplayGTK *d;
264 #endif
265  read_options(argc, argv, multi, camera, nframes, verbose_info, verbose_settings, mediatype_is_set, mediatypeID,
266  framerate_is_set, framerate, display, save, opath);
267 
268  // Number of cameras connected on the bus
270  g = new vpDirectShowGrabber();
271  unsigned int ncameras = g->getDeviceNumber();
272  // Check the consistancy of the options
273  if (multi) {
274  // ckeck if two cameras are connected
275  if (ncameras < 2) {
276  std::cout << "You have only " << ncameras << " camera connected on the bus." << std::endl;
277  std::cout << "It is not possible to active multi-camera acquisition." << std::endl;
278  std::cout << "Disable -m command line option, or connect an other " << std::endl;
279  std::cout << "cameras on the bus." << std::endl;
280  g->close();
281  delete g;
282  return EXIT_FAILURE;
283  }
284  }
285  if (camera >= ncameras) {
286  std::cout << "You have only " << ncameras;
287  std::cout << " camera connected on the bus." << std::endl;
288  std::cout << "It is not possible to select camera " << camera << std::endl;
289  std::cout << "Check your -c <camera> command line option." << std::endl;
290  g->close();
291  delete g;
292  return EXIT_FAILURE;
293  }
294  if (multi) {
295  camera = 0; // to over write a bad option usage
296  // reinitialize the grabbers with the right number of devices (one
297  // grabber per device)
298  delete[] g;
299  g = new vpDirectShowGrabber[ncameras];
300  for (unsigned int i = 0; i < ncameras; i++) {
301  g[i].open();
302  }
303 
304  }
305  else {
306  ncameras = 1; // acquisition from only one camera
307  delete[] g;
308  g = new vpDirectShowGrabber[1];
309  g[0].open();
310  g[0].setDevice(camera);
311  }
312 
313 // allocate an image and display for each camera to consider
314 #ifdef GRAB_COLOR
315  I = new vpImage<vpRGBa>[ncameras];
316 #else
317  I = new vpImage<unsigned char>[ncameras];
318 #endif
319  if (display)
320 
321 #ifdef VISP_HAVE_GDI
322  d = new vpDisplayGDI[ncameras];
323 #else
324  d = new vpDisplayGTK[ncameras];
325 #endif
326  // If required modify camera settings
327 
328  if (mediatype_is_set) {
329  g[0].setMediaType(mediatypeID);
330  }
331 
332  if (framerate_is_set) {
333  for (unsigned int i = 0; i < ncameras; i++) {
334  unsigned int c;
335  if (multi)
336  c = i;
337  else
338  c = camera;
339  std::cout << "camera " << c << std::endl;
340  if (!g[i].setFramerate(framerate))
341  std::cout << "Set Framerate failed !!" << std::endl << std::endl;
342  }
343  }
344 
345  // Display information for each camera
346  if (verbose_info || verbose_settings) {
347 
348  std::cout << "----------------------------------------------------------" << std::endl;
349  std::cout << "---- Device List : " << std::endl;
350  std::cout << "----------------------------------------------------------" << std::endl;
351  g[0].displayDevices();
352  for (unsigned i = 0; i < ncameras; i++) {
353  unsigned int c;
354  if (multi)
355  c = i;
356  else
357  c = camera;
358 
359  if (verbose_info) {
360  unsigned int width, height;
361  g[i].getFormat(width, height, framerate);
362  std::cout << "----------------------------------------------------------" << std::endl
363  << "---- MediaType and framerate currently used by device " << std::endl
364  << "---- (or camera) " << c << std::endl
365  << "---- Current MediaType : " << g[i].getMediaType() << std::endl
366  << "---- Current format : " << width << " x " << height << " at " << framerate << " fps"
367  << std::endl
368  << "----------------------------------------------------------" << std::endl;
369  }
370  if (verbose_settings) {
371  std::cout << "----------------------------------------------------------" << std::endl
372  << "---- MediaTypes supported by device (or camera) " << c << std::endl
373  << "---- One of the MediaType below can be set using " << std::endl
374  << "---- option -t <mediatype>." << std::endl
375  << "----------------------------------------------------------" << std::endl;
376  g[i].getStreamCapabilities();
377  }
378  }
379  delete[] g;
380  delete[] I;
381  if (display)
382  delete[] d;
383 
384  return EXIT_SUCCESS;
385  }
386 
387  // Do a first acquisition to initialise the display
388  for (unsigned int i = 0; i < ncameras; i++) {
389  // Acquire the first image
390  g[i].acquire(I[i]);
391  unsigned int c;
392  if (multi)
393  c = i;
394  else
395  c = camera;
396 
397  std::cout << "Image size for camera " << c << " : width: " << I[i].getWidth() << " height: " << I[i].getHeight()
398  << std::endl;
399 
400  if (display) {
401  // Initialise the display
402  std::stringstream title;
403  title << "Images captured by camera ";
404  title << c;
405  d[i].init(I[i], 100 + i * 50, 100 + i * 50, title.c_str());
406  }
407  }
408 
409  // Main loop for single or multi-camera acquisition and display
410  std::cout << "Capture in process..." << std::endl;
411 
412  double tbegin = 0, ttotal = 0;
413 
414  ttotal = 0;
415  tbegin = vpTime::measureTimeMs();
416  for (unsigned i = 0; i < nframes; i++) {
417  for (unsigned c = 0; c < ncameras; c++) {
418  // Acquire an image
419  g[c].acquire(I[c]);
420  if (display) {
421  // Display the last image acquired
422  vpDisplay::display(I[c]);
423  vpDisplay::flush(I[c]);
424  }
425  if (save) {
426  char buf[FILENAME_MAX];
427  snprintf(buf, FILENAME_MAX, opath.c_str(), c, i);
428  std::string filename(buf);
429  std::cout << "Write: " << filename << std::endl;
430  vpImageIo::write(I[c], filename);
431  }
432  }
433  double tend = vpTime::measureTimeMs();
434  double tloop = tend - tbegin;
435  tbegin = tend;
436  std::cout << "loop time: " << tloop << " ms" << std::endl;
437  ttotal += tloop;
438  }
439 
440  std::cout << "Mean loop time: " << ttotal / nframes << " ms" << std::endl;
441  std::cout << "Mean frequency: " << 1000. / (ttotal / nframes) << " fps" << std::endl;
442 
443  // Release the framegrabber
444  delete[] g;
445 
446  // Free memory
447  delete[] I;
448  if (display)
449  delete[] d;
450 
451  return EXIT_SUCCESS;
452  }
453  catch (const vpException &e) {
454  std::cout << "Catch an exception: " << e << std::endl;
455  return EXIT_FAILURE;
456  }
457 }
458 #else // (defined (VISP_HAVE_GTK) || defined(VISP_HAVE_GDI))
459 int main()
460 {
461  std::cout << "You do not have GDI (Graphical Device Interface), or GTK functionalities to display images..."
462  << std::endl;
463  std::cout << "Tip if you are on a windows-like system:" << std::endl;
464  std::cout << "- Install GDI, configure again ViSP using cmake and build again this example" << std::endl;
465  return EXIT_SUCCESS;
466 }
467 #endif // (defined (VISP_HAVE_GTK) || defined(VISP_HAVE_GDI))
468 #else // defined (VISP_HAVE_DIRECTSHOW)
469 int main()
470 {
471  std::cout << "This example requires Direct Show SDK. " << std::endl;
472  std::cout << "Tip if you are on a windows-like system:" << std::endl;
473  std::cout << "- Install Direct Show, configure again ViSP using cmake and build again this example" << std::endl;
474  return EXIT_SUCCESS;
475 }
476 #endif // defined (VISP_HAVE_DIRECTSHOW)
class for windows direct show devices
void acquire(vpImage< unsigned char > &I)
void getFormat(unsigned int &width, unsigned int &height, double &framerate)
bool setDevice(unsigned int id)
unsigned int getDeviceNumber()
bool setMediaType(int mediaTypeID)
Display for windows using GDI (available on any windows 32 platform).
Definition: vpDisplayGDI.h:130
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:133
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="") VP_OVERRIDE
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
VISP_EXPORT double measureTimeMs()