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