Visual Servoing Platform version 3.5.0
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
85void 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\
91Acquire images using DirectShow (under Windows only) and display\n\
92it using GTK or the windows GDI if GTK is not available.\n\
93For a given camera, mediatype (or video mode) as well as framerate\n\
94can be set.\n\
95If more than one camera is connected, this example allows also to \n\
96acquire images from all the cameras.\n\
97\n\
98SYNOPSIS\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\
103OPTIONS 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
174void 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
238int 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
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;
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))
456int 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)
465int 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)
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:129
The vpDisplayGTK allows to display image using the GTK 3rd party library. Thus to enable this class G...
Definition: vpDisplayGTK.h:135
void init(vpImage< unsigned char > &I, int win_x=-1, int win_y=-1, const std::string &win_title="")
static void display(const vpImage< unsigned char > &I)
static void flush(const vpImage< unsigned char > &I)
error that can be emited by ViSP classes.
Definition: vpException.h:72
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:293
unsigned int getWidth() const
Definition: vpImage.h:246
unsigned int getHeight() const
Definition: vpImage.h:188
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:69
VISP_EXPORT double measureTimeMs()