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