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