Visual Servoing Platform  version 3.0.1
grabDirectShowMulti.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ViSP software.
4  * Copyright (C) 2005 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
9  * See the file LICENSE.txt at the root directory of this source
10  * distribution for additional information about the GNU GPL.
11  *
12  * For using ViSP with software that can not be combined with the GNU
13  * GPL, please contact Inria about acquiring a ViSP Professional
14  * Edition License.
15  *
16  * See http://visp.inria.fr for more information.
17  *
18  * This software was developed at:
19  * Inria Rennes - Bretagne Atlantique
20  * Campus Universitaire de Beaulieu
21  * 35042 Rennes Cedex
22  * France
23  *
24  * If you have questions regarding the use of this file, please contact
25  * Inria at visp@inria.fr
26  *
27  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29  *
30  * Description:
31  * Acquire images using DirectShow (under Windows only) and display it
32  * using GTK or GDI.
33  *
34  * Authors:
35  * Bruno Renier
36  * Fabien Spindler
37  * Anthony Saunier
38  *
39  *****************************************************************************/
40 
41 #include <visp3/core/vpConfig.h>
42 #include <visp3/core/vpDebug.h>
43 
51 #include <vector>
52 
53 #include <iostream>
54 #include <sstream>
55 
56 
57 #if defined (VISP_HAVE_DIRECTSHOW)
58 #if (defined (VISP_HAVE_GTK) || defined(VISP_HAVE_GDI))
59 
60 #include <visp3/sensor/vpDirectShowGrabber.h>
61 #include <visp3/core/vpImage.h>
62 #include <visp3/io/vpImageIo.h>
63 #include <visp3/gui/vpDisplayGTK.h>
64 #include <visp3/gui/vpDisplayGDI.h>
65 #include <visp3/io/vpParseArgv.h>
66 #include <visp3/core/vpTime.h>
67 
68 
69 // List of allowed command line options
70 //#define GETOPTARGS "dhn:o:"
71 #define GETOPTARGS "c:df:hmn:io:st:?"
72 
73 #define GRAB_COLOR
74 
86 void usage(const char *name, const char *badparam, unsigned int camera, unsigned int &nframes,
87  std::string &opath)
88 {
89  if (badparam)
90  fprintf(stderr, "\nERREUR: Bad parameter [%s]\n", badparam);
91 
92  fprintf(stdout, "\n\
93 Acquire images using DirectShow (under Windows only) and display\n\
94 it using GTK or the windows GDI if GTK is not available.\n\
95 For a given camera, mediatype (or video mode) as well as framerate\n\
96 can be set.\n\
97 If more than one camera is connected, this example allows also to \n\
98 acquire images from all the cameras.\n\
99 \n\
100 SYNOPSIS\n\
101 %s [-t <mediatype>] [-f <framerate>] \n\
102  [-c <camera id>] [-m] [-n <frames>] [-i] [-s] [-d] \n\
103  [-o <filename>] [-h]\n\
104  \n\
105 OPTIONS Default\n\
106  -t [%%u] \n\
107  MediaType (or video mode) to set for the active \n\
108  camera. Use -s option so see which are the supported \n\
109  Mediatypes. You can select the active camera \n\
110  using -c option.\n\
111 \n\
112  -f [%%d] \n\
113  Framerate to set for the active camera.\n\
114  You can select the active camera using -c option.\n",
115  name);
116 
117  fprintf(stdout, "\n\
118  -c [%%u] %u\n\
119  Active camera identifier.\n\
120  Zero is for the first camera found on the bus.\n\
121 \n\
122  -m \n\
123  Flag to active multi camera acquisition. \n\
124  You need at least two cameras connected on the bus.\n\
125 \n\
126  -n [%%u] %u\n\
127  Number of frames to acquire.\n\
128 \n\
129  -i \n\
130  Flag to print camera information.\n\
131 \n\
132  -s \n\
133  Print camera settings capabilities such as MediaType \n\
134  and sizes available and exit.\n\
135 \n\
136  -d \n\
137  Flag to turn off image display.\n\
138 \n\
139  -o [%%s] \n\
140  Filename for image saving. \n\
141  Example: -o %s\n\
142  The first %%d is for the camera id, %%04d\n\
143  is for the image numbering.\n\
144 \n\
145  -h \n\
146  Print the help.\n\
147 \n",
148  camera, nframes, opath.c_str());
149 
150  exit(0);
151 }
152 
178 void read_options(int argc, const char **argv, bool &multi, unsigned int &camera,
179  unsigned int &nframes, bool &verbose_info,
180  bool &verbose_settings,
181  bool &mediatype_is_set,
182  unsigned int &mediatypeID,
183  bool &framerate_is_set,
184  double &framerate,
185  bool &display, bool &save, std::string &opath)
186 {
187  const char *optarg;
188  int c;
189  /*
190  * Lecture des options.
191  */
192 
193  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS,&optarg)) > 1) {
194  switch (c) {
195  case 'c':
196  camera = atoi(optarg); break;
197  case 'd':
198  display = false; break;
199  case 'f':
200  framerate_is_set = true;
201  framerate = atoi(optarg); break;
202  case 'i':
203  verbose_info = true; break;
204  case 'm':
205  multi = true; break;
206  case 'n':
207  nframes = atoi(optarg); break;
208  case 'o':
209  save = true;
210  opath = optarg; break;
211  case 's':
212  verbose_settings = true; break;
213  case 't':
214  mediatype_is_set = true;
215  mediatypeID = atoi(optarg); 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 
230 
239 int
240 main(int argc, const char ** argv)
241 {
242  try {
243  unsigned int camera = 0;
244  bool multi = false;
245  bool verbose_info = false;
246  bool verbose_settings = false;
247  bool display = true;
248  unsigned int nframes = 50;
249  bool mediatype_is_set = false;
250  unsigned int mediatypeID;
251  bool framerate_is_set = false;
252  double framerate;
253  bool save = false;
254 
255 #ifdef GRAB_COLOR
256  vpImage<vpRGBa> *I;
257  std::string opath = "C:/temp/I%d-%04d.ppm";
258 #else
260  std::string opath = "C:/temp/I%d-%04d.pgm";
261 #endif
262 #if defined VISP_HAVE_GDI
263  vpDisplayGDI *d;
264 #elif defined VISP_HAVE_GTK
265  vpDisplayGTK *d;
266 #endif
267  read_options(argc, argv, multi, camera, nframes,
268  verbose_info, verbose_settings,
269  mediatype_is_set, mediatypeID,
270  framerate_is_set, framerate,
271  display, save, opath);
272 
273  // Number of cameras connected on the bus
275  g = new vpDirectShowGrabber();
276  unsigned int ncameras = g->getDeviceNumber();
277  // Check the consistancy of the options
278  if (multi) {
279  // ckeck if two cameras are connected
280  if (ncameras < 2) {
281  std::cout << "You have only " << ncameras << " camera connected on the bus." << std::endl;
282  std::cout << "It is not possible to active multi-camera acquisition." << std::endl;
283  std::cout << "Disable -m command line option, or connect an other " << std::endl;
284  std::cout << "cameras on the bus." << std::endl;
285  g->close();
286  delete g;
287  return(0);
288  }
289  }
290  if (camera >= ncameras) {
291  std::cout << "You have only " << ncameras;
292  std::cout << " camera connected on the bus." << std::endl;
293  std::cout << "It is not possible to select camera " << camera << std::endl;
294  std::cout << "Check your -c <camera> command line option." << std::endl;
295  g->close();
296  delete g;
297  return(0);
298  }
299  if (multi) {
300  camera = 0; // to over write a bad option usage
301  //reinitialize the grabbers with the right number of devices (one grabber per device)
302  delete [] g;
303  g = new vpDirectShowGrabber[ncameras];
304  for(unsigned int i=0; i<ncameras ; i++)
305  {
306  g[i].open();
307  }
308 
309  }
310  else {
311  ncameras = 1; // acquisition from only one camera
312  delete [] g;
313  g = new vpDirectShowGrabber[1];
314  g[0].open();
315  g[0].setDevice(camera);
316 
317  }
318 
319  // allocate an image and display for each camera to consider
320 #ifdef GRAB_COLOR
321  I = new vpImage<vpRGBa> [ncameras];
322 #else
323  I = new vpImage<unsigned char> [ncameras];
324 #endif
325  if (display)
326 
327 #ifdef VISP_HAVE_GDI
328  d = new vpDisplayGDI [ncameras];
329 #else
330  d = new vpDisplayGTK [ncameras];
331 #endif
332  // If required modify camera settings
333 
334  if (mediatype_is_set) {
335  g[0].setMediaType(mediatypeID);
336  }
337 
338  if (framerate_is_set) {
339  for(unsigned int i=0; i<ncameras ; i++)
340  {
341  unsigned int c;
342  if (multi) c = i;
343  else c = camera;
344  std::cout<<"camera " << c <<std::endl;
345  if (!g[i].setFramerate(framerate))
346  std::cout << "Set Framerate failed !!" <<std::endl<< std::endl;
347  }
348  }
349 
350  // Display information for each camera
351  if (verbose_info || verbose_settings) {
352 
353  std::cout << "----------------------------------------------------------" << std::endl;
354  std::cout << "---- Device List : " << std::endl;
355  std::cout << "----------------------------------------------------------" << std::endl;
356  g[0].displayDevices();
357  for (unsigned i=0; i < ncameras; i ++) {
358  unsigned int c;
359  if (multi) c = i;
360  else c = camera;
361 
362  if (verbose_info){
363  unsigned int width, height;
364  g[i].getFormat(width, height, framerate);
365  std::cout << "----------------------------------------------------------"
366  << std::endl
367  << "---- MediaType and framerate currently used by device " << std::endl
368  << "---- (or camera) " << c << std::endl
369  << "---- Current MediaType : " << g[i].getMediaType() << std::endl
370  << "---- Current format : " << width <<" x "<< height <<" at "<< framerate << " fps" << std::endl
371  << "----------------------------------------------------------" << std::endl;
372  }
373  if (verbose_settings) {
374  std::cout << "----------------------------------------------------------"
375  << std::endl
376  << "---- MediaTypes supported by device (or camera) "
377  << c << std::endl
378  << "---- One of the MediaType below can be set using " << std::endl
379  << "---- option -t <mediatype>."
380  << std::endl
381  << "----------------------------------------------------------"
382  << std::endl;
383  g[i].getStreamCapabilities();
384  }
385 
386  }
387  delete [] g;
388  delete [] I;
389  if (display)
390  delete [] d;
391 
392  return 0;
393  }
394 
395 
396  // Do a first acquisition to initialise the display
397  for (unsigned int i=0; i < ncameras; i ++) {
398  // Acquire the first image
399  g[i].acquire(I[i]);
400  unsigned int c;
401  if (multi) c = i;
402  else c = camera;
403 
404  std::cout << "Image size for camera " << c << " : width: "
405  << I[i].getWidth() << " height: " << I[i].getHeight() << std::endl;
406 
407  if (display) {
408  // Initialise the display
409  char title[100];
410  sprintf(title, "Images captured by camera %u", c );
411  d[i].init(I[i], 100+i*50, 100+i*50, title) ;
412  }
413  }
414 
415  // Main loop for single or multi-camera acquisition and display
416  std::cout << "Capture in process..." << std::endl;
417 
418  double tbegin=0, ttotal=0;
419 
420  ttotal = 0;
421  tbegin = vpTime::measureTimeMs();
422  for (unsigned i = 0; i < nframes; i++) {
423  for (unsigned c = 0; c < ncameras; c++) {
424  // Acquire an image
425  g[c].acquire(I[c]);
426  if (display) {
427  // Display the last image acquired
428  vpDisplay::display(I[c]);
429  vpDisplay::flush(I[c]);
430  }
431  if (save) {
432  char buf[FILENAME_MAX];
433  sprintf(buf, opath.c_str(), c, i);
434  std::string filename(buf);
435  std::cout << "Write: " << filename << std::endl;
436  vpImageIo::write(I[c], filename);
437  }
438  }
439  double tend = vpTime::measureTimeMs();
440  double tloop = tend - tbegin;
441  tbegin = tend;
442  std::cout << "loop time: " << tloop << " ms" << std::endl;
443  ttotal += tloop;
444  }
445 
446  std::cout << "Mean loop time: " << ttotal / nframes << " ms" << std::endl;
447  std::cout << "Mean frequency: " << 1000./(ttotal / nframes) << " fps" << std::endl;
448 
449  // Release the framegrabber
450  delete [] g;
451 
452  // Free memory
453  delete [] I;
454  if (display)
455  delete [] d;
456 
457  return 0;
458  }
459  catch(vpException &e) {
460  std::cout << "Catch an exception: " << e << std::endl;
461  return 1;
462  }
463 }
464 #else // (defined (VISP_HAVE_GTK) || defined(VISP_HAVE_GDI))
465 
466 int
467 main()
468 {
469  vpTRACE("GDI or GTK is not available...") ;
470 }
471 #endif // (defined (VISP_HAVE_GTK) || defined(VISP_HAVE_GDI))
472 #else // defined (VISP_HAVE_DIRECTSHOW)
473 int
474 main()
475 {
476  vpTRACE("DirectShow is not available...") ;
477 }
478 #endif // defined (VISP_HAVE_DIRECTSHOW)
479 
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:73
class for windows direct show devices
static void flush(const vpImage< unsigned char > &I)
VISP_EXPORT double measureTimeMs()
Definition: vpTime.cpp:93
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:76
bool setDevice(unsigned int id)
static void write(const vpImage< unsigned char > &I, const std::string &filename)
Definition: vpImageIo.cpp:368
#define vpTRACE
Definition: vpDebug.h:414
static void display(const vpImage< unsigned char > &I)
void acquire(vpImage< unsigned char > &I)
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:138
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &title="")
unsigned int getHeight() const
Definition: vpImage.h:175
unsigned int getDeviceNumber()
unsigned int getWidth() const
Definition: vpImage.h:226