Visual Servoing Platform  version 3.6.1 under development (2024-11-15)
grab1394Two.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  * Firewire cameras video capture.
33  *
34 *****************************************************************************/
35 
49 #include <iostream>
50 #include <list>
51 #include <sstream>
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <visp3/core/vpConfig.h>
55 #include <visp3/core/vpDebug.h>
56 #if defined(VISP_HAVE_DC1394)
57 
58 #include <visp3/core/vpDisplay.h>
59 #include <visp3/core/vpImage.h>
60 #include <visp3/core/vpRGBa.h>
61 #include <visp3/core/vpTime.h>
62 #include <visp3/gui/vpDisplayX.h>
63 #include <visp3/io/vpImageIo.h>
64 #include <visp3/io/vpParseArgv.h>
65 #include <visp3/sensor/vp1394TwoGrabber.h>
66 
67 #define GRAB_CxOLOR
68 
69 // List of allowed command line options
70 #define GETOPTARGS "b:c:df:g:hH:L:mn:io:p:rsT:v:W:"
71 #define DUAL_ACQ
72 
73 #ifdef ENABLE_VISP_NAMESPACE
74 using namespace VISP_NAMESPACE_NAME;
75 #endif
76 
92 void usage(const char *name, const char *badparam, unsigned int camera, const unsigned int &nframes,
93  const std::string &opath, const unsigned int &roi_left, const unsigned int &roi_top,
94  const unsigned int &roi_width, const unsigned int &roi_height, const unsigned int &ringbuffersize,
95  const unsigned int &panControl)
96 {
97  if (badparam)
98  fprintf(stderr, "\nERROR: Bad parameter [%s]\n", badparam);
99 
100  fprintf(stderr, "\n\
101 SYNOPSIS\n\
102  %s [-v <video mode>] [-f <framerate>] \n\
103  [-g <color coding>] [-c <camera id>] [-m] [-n <frames>] \n\
104  [-i] [-s] [-d] [-o <filename>] [-L <format 7 roi left position>] \n\
105  [-T <format 7 roi top position>] [-W <format 7 roi width>] \n\
106  [-H <format 7 roi height>] [-b <ring buffer size>] \n\
107  [-p <pan control value>] [-R] [-h]\n\
108  \n\
109 DESCRIPTION\n\
110  Test for firewire camera image acquisition.\n\
111  \n\
112 EXAMPLES\n\
113  \n\
114  %s -s\n\
115  Indicates the current settings for the first camera found on the bus.\n\n\
116  %s -i\n\
117  Gives information on the first camera found on the bus.\n\n\
118  %s -s -m\n\
119  Indicates the current settings for all the cameras found on the bus.\n\n\
120  %s -i -m\n\
121  Gives information on all the cameras found on the bus.\n\
122  %s -c 1\n\
123  Grab images from camera 1.\n\n\
124  %s -m\n\
125  Grab images from all the cameras.\n\n\
126  \n\
127  If a stereo camera is connected to the bus like the PointGrey Bumblebee,\n\
128  you may set the pan control to select the camera view:\n\
129  %s -p 0\n\
130  Transmit right imge.\n\
131  %s -p 1\n\
132  Transmit left imge.\n\
133  \n\
134 OPTIONS Default\n\
135  -v [%%u] : Video mode to set for the active camera.\n\
136  Use -s option so see which are the supported \n\
137  video modes. You can select the active \n\
138  camera using -c option.\n\
139  \n\
140  -f [%%u] : Framerate to set for the active camera.\n\
141  Use -s option so see which are the supported \n\
142  framerates. You can select the active \n\
143  camera using -c option.\n\
144  \n\
145  -g [%%u] : Color coding to set for the active camera\n\
146  in format 7 video mode. Use -s option so see if \n\
147  format 7 is supported by the camera and if so, \n\
148  which are the supported color codings. You can \n\
149  select the active camera using -c option.\n\
150  See -t <top>, -l <left>, -w <width>, \n\
151  -h <height> option to set format 7 roi.\n\
152  \n\
153  -L [%%u] : Format 7 region of interest (roi) left %u\n\
154  position. This option is only used if video\n\
155  mode is format 7.\n\
156  \n\
157  -T [%%u] : Format 7 region of interest (roi) top %u\n\
158  position. This option is only used if video\n\
159  mode is format 7.\n\
160  \n\
161  -W [%%u] : Format 7 region of interest (roi) width. %u\n\
162  Is set to zero, use the maximum width. This\n\
163  option is only used if video mode is format 7.\n\
164  \n\
165  -H [%%u] : Format 7 region of interest (roi) height. %u\n\
166  Is set to zero, use the maximum height. This\n\
167  option is only used if video mode is format 7.\n\
168  \n\
169  -c [%%u] : Active camera identifier. %u\n\
170  Zero is for the first camera found on the bus.\n\
171  \n\
172  -m : Flag to active multi camera acquisition. \n\
173  You need at least two cameras connected on \n\
174  the bus.\n\
175  \n\
176  -n [%%u] : Number of frames to acquire. %u\n\
177  \n\
178  -i : Flag to print camera information.\n\
179  \n\
180  -s : Print camera settings capabilities such as \n\
181  video mode and framerates available and exit.\n\
182  \n\
183  -d : Flag to turn off image display.\n\
184  \n\
185  -b [%%u] : Ring buffer size used during capture %u\n\
186  \n\
187  -p [%%u] : Pan control value used to control single or %u\n\
188  multiple image transmission from stereo vision \n\
189  cameras by setting the PAN register 0x884.\n\
190  \n\
191  -o [%%s] : Filename for image saving. \n\
192  Example: -o %s\n\
193  The first %%d is for the camera id. The second\n\
194  %%04d is for the image numbering. The format is set \n\
195  by the extension of the file (ex .png, .pgm, ...) \n\
196  \n\
197  -r : Reset the bus attached to the first camera found.\n\
198  Bus reset may help to make firewire working if the\n\
199  program was not properly stopped by a CTRL-C.\n\
200  \n\
201  -h : Print this help.\n\
202  \n",
203  name, name, name, name, name, name, name, name, name, roi_left, roi_top, roi_width, roi_height, camera,
204  nframes, ringbuffersize, panControl, opath.c_str());
205 }
206 
249 bool read_options(int argc, const char **argv, bool &multi, unsigned int &camera, unsigned int &nframes,
250  bool &verbose_info, bool &verbose_settings, bool &videomode_is_set,
251  vp1394TwoGrabber::vp1394TwoVideoModeType &videomode, bool &framerate_is_set,
252  vp1394TwoGrabber::vp1394TwoFramerateType &framerate, bool &colorcoding_is_set,
253  vp1394TwoGrabber::vp1394TwoColorCodingType &colorcoding, bool &ringbuffersize_is_set,
254  unsigned int &ringbuffersize, bool &display, bool &save, std::string &opath, unsigned int &roi_left,
255  unsigned int &roi_top, unsigned int &roi_width, unsigned int &roi_height, bool &reset,
256  unsigned int &panControl, bool &panControl_is_set)
257 {
258  /*
259  * Lecture des options.
260  */
261  const char *optarg_;
262  int c;
263 
264  while ((c = vpParseArgv::parse(argc, argv, GETOPTARGS, &optarg_)) > 1) {
265  switch (c) {
266  case 'c':
267  camera = (unsigned int)atoi(optarg_);
268  break;
269  case 'd':
270  display = false;
271  break;
272  case 'f':
273  framerate_is_set = true;
274  framerate = (vp1394TwoGrabber::vp1394TwoFramerateType)atoi(optarg_);
275  break;
276  case 'g':
277  colorcoding_is_set = true;
278  colorcoding = (vp1394TwoGrabber::vp1394TwoColorCodingType)atoi(optarg_);
279  break;
280  case 'H':
281  roi_height = (unsigned int)atoi(optarg_);
282  break;
283  case 'i':
284  verbose_info = true;
285  break;
286  case 'L':
287  roi_left = (unsigned int)atoi(optarg_);
288  break;
289  case 'm':
290  multi = true;
291  break;
292  case 'n':
293  nframes = (unsigned int)atoi(optarg_);
294  break;
295  case 'o':
296  save = true;
297  opath = optarg_;
298  break;
299  case 'b':
300  ringbuffersize_is_set = true;
301  ringbuffersize = (unsigned int)atoi(optarg_);
302  break;
303  case 'p':
304  panControl = (unsigned int)atoi(optarg_);
305  panControl_is_set = true;
306  break;
307  case 'r':
308  reset = true;
309  break;
310  case 's':
311  verbose_settings = true;
312  break;
313  case 'T':
314  roi_top = (unsigned int)atoi(optarg_);
315  break;
316  case 'v':
317  videomode_is_set = true;
318  videomode = (vp1394TwoGrabber::vp1394TwoVideoModeType)atoi(optarg_);
319  break;
320  case 'W':
321  roi_width = (unsigned int)atoi(optarg_);
322  break;
323  case 'h':
324  case '?':
325  usage(argv[0], nullptr, camera, nframes, opath, roi_left, roi_top, roi_width, roi_height, ringbuffersize,
326  panControl);
327  return false;
328  break;
329  }
330  }
331 
332  if ((c == 1) || (c == -1)) {
333  // standalone param or error
334  usage(argv[0], nullptr, camera, nframes, opath, roi_left, roi_top, roi_width, roi_height, ringbuffersize, panControl);
335  std::cerr << "ERROR: " << std::endl;
336  std::cerr << " Bad argument " << optarg_ << std::endl << std::endl;
337  return false;
338  }
339  return true;
340 }
341 
351 int main(int argc, const char **argv)
352 {
353  try {
354  unsigned int camera = 0;
355  bool multi = false;
356  bool verbose_info = false;
357  bool verbose_settings = false;
358  bool display = true;
359  unsigned int nframes = 50;
360  unsigned int offset;
361  bool videomode_is_set = false;
363  bool framerate_is_set = false;
365  bool colorcoding_is_set = false;
367  bool ringbuffersize_is_set = false;
368  unsigned int ringbuffersize = 4;
369  bool save = false;
370  bool reset = false;
371  unsigned int panControl = 0;
372  bool panControl_is_set = false;
373 
374  // Format 7 roi
375  unsigned int roi_left = 0, roi_top = 0, roi_width = 0, roi_height = 0;
376 
377  // Default output path for image saving
378  std::string opath = "/tmp/I%d-%04d.ppm";
379 
380  if (read_options(argc, argv, multi, camera, nframes, verbose_info, verbose_settings, videomode_is_set, videomode,
381  framerate_is_set, framerate, colorcoding_is_set, colorcoding, ringbuffersize_is_set,
382  ringbuffersize, display, save, opath, roi_left, roi_top, roi_width, roi_height, reset, panControl,
383  panControl_is_set) == false) {
384  return EXIT_FAILURE;
385  }
386  // Create a grabber
387  vp1394TwoGrabber g(reset);
388 
389  if (reset) {
390  // The experience shows that for some Marlin cameras (F131B and
391  // F033C) a tempo of 1s is requested after a bus reset.
392  vpTime::wait(1000); // Wait 1000 ms
393  }
394 
395  // Number of cameras connected on the bus
396  unsigned int ncameras = 0;
397  g.getNumCameras(ncameras);
398 
399  std::cout << "Number of cameras on the bus: " << ncameras << std::endl;
400 
401  // Check the consistancy of the options
402  if (multi) {
403  // ckeck if two cameras are connected
404  if (ncameras < 2) {
405  std::cout << "You have only " << ncameras << " camera connected on the bus." << std::endl;
406  std::cout << "It is not possible to active multi-camera acquisition." << std::endl;
407  std::cout << "Disable -m command line option, or connect an other " << std::endl;
408  std::cout << "cameras on the bus." << std::endl;
409  g.close();
410  return EXIT_FAILURE;
411  }
412  }
413  if (camera >= ncameras) {
414  std::cout << "You have only " << ncameras;
415  std::cout << " camera connected on the bus." << std::endl;
416  std::cout << "It is not possible to select camera " << camera << std::endl;
417  std::cout << "Check your -c <camera> command line option." << std::endl;
418  g.close();
419  return EXIT_FAILURE;
420  }
421 
422  if (multi) {
423  camera = 0; // to over write a bad option usage
424  }
425  else {
426  ncameras = 1; // acquisition from only one camera
427  }
428  // Offset is used to set the correspondancy between and image and the
429  // camera. For example, images coming from camera (i+offset) are
430  // available in I[i]
431  offset = camera;
432 
433  // Display information for each camera
434  if (verbose_info || verbose_settings) {
435  for (unsigned int i = 0; i < ncameras; i++) {
436 
437  g.setCamera(i + offset);
438 
439  if (verbose_info)
440  g.printCameraInfo();
441 
442  if (verbose_settings) {
446  std::list<vp1394TwoGrabber::vp1394TwoVideoModeType> lmode;
447  std::list<vp1394TwoGrabber::vp1394TwoFramerateType> lfps;
448  std::list<vp1394TwoGrabber::vp1394TwoColorCodingType> lcoding;
449  std::list<vp1394TwoGrabber::vp1394TwoVideoModeType>::const_iterator it_lmode;
450  std::list<vp1394TwoGrabber::vp1394TwoFramerateType>::const_iterator it_lfps;
451  std::list<vp1394TwoGrabber::vp1394TwoColorCodingType>::const_iterator it_lcoding;
452  uint64_t guid;
453 
454  g.getVideoMode(curmode);
455  g.getFramerate(curfps);
456  g.getColorCoding(curcoding);
457  g.getVideoModeSupported(lmode);
458  g.getGuid(guid);
459 
460  std::cout << "----------------------------------------------------------" << std::endl
461  << "---- Video modes and framerates supported by camera " << i + offset << " ----" << std::endl
462  << "---- with guid 0x" << std::hex << guid << " ----" << std::endl
463  << "---- * is for the current settings ----" << std::endl
464  << "---- between ( ) you have the corresponding option ----" << std::endl
465  << "---- to use. ----" << std::endl
466  << "----------------------------------------------------------" << std::endl;
467 
468  for (it_lmode = lmode.begin(); it_lmode != lmode.end(); ++it_lmode) {
469  // Parse the list of supported modes
470  vp1394TwoGrabber::vp1394TwoVideoModeType supmode = *it_lmode;
471  std::stringstream ss;
472  ss << (int)supmode;
473  if (curmode == supmode)
474  std::cout << " * " << vp1394TwoGrabber::videoMode2string(supmode) << " (-v " << ss.str() << ")"
475  << std::endl;
476  else
477  std::cout << " " << vp1394TwoGrabber::videoMode2string(supmode) << " (-v " << ss.str() << ")"
478  << std::endl;
479 
480  if (g.isVideoModeFormat7(supmode)) {
481  // Format 7 video mode; no framerate setting, but color
482  // coding setting
483  g.getColorCodingSupported(supmode, lcoding);
484  for (it_lcoding = lcoding.begin(); it_lcoding != lcoding.end(); ++it_lcoding) {
486  supcoding = *it_lcoding;
487  std::stringstream ss;
488  ss << (int)supcoding;
489  if ((curmode == supmode) && (supcoding == curcoding))
490  std::cout << " * " << vp1394TwoGrabber::colorCoding2string(supcoding) << " (-g " << ss.str()
491  << ")" << std::endl;
492  else
493  std::cout << " " << vp1394TwoGrabber::colorCoding2string(supcoding) << " (-g " << ss.str()
494  << ")" << std::endl;
495  }
496  }
497  else {
498 
499  // Parse the list of supported framerates for a supported mode
500  g.getFramerateSupported(supmode, lfps);
501  for (it_lfps = lfps.begin(); it_lfps != lfps.end(); ++it_lfps) {
503  std::stringstream ss;
504  ss << (int)supfps;
505  if ((curmode == supmode) && (supfps == curfps))
506  std::cout << " * " << vp1394TwoGrabber::framerate2string(supfps) << " (-f " << ss.str() << ")"
507  << std::endl;
508  else
509  std::cout << " " << vp1394TwoGrabber::framerate2string(supfps) << " (-f " << ss.str() << ")"
510  << std::endl;
511  }
512  }
513  }
514  std::cout << "----------------------------------------------------------" << std::endl;
515  }
516  }
517  return EXIT_SUCCESS;
518  }
519 
520  // If requested set the PAN register 0x884 to control single or
521  // multiple image transmission from stereo vision cameras.
522  if (panControl_is_set) {
523  g.setPanControl(panControl);
524  }
525 
526  // If required modify camera settings
527  if (videomode_is_set) {
528  g.setCamera(camera);
529  g.setVideoMode(videomode);
530  }
531  else {
532  // get The actual video mode
533  g.setCamera(camera);
534  g.getVideoMode(videomode);
535  }
536  if (framerate_is_set) {
537  g.setCamera(camera);
538  g.setFramerate(framerate);
539  }
540  if (colorcoding_is_set) {
541  g.setCamera(camera);
542  g.setColorCoding(colorcoding);
543  }
544  if (ringbuffersize_is_set) {
545  g.setRingBufferSize(ringbuffersize);
546  }
547 
548  // In format 7 set roi to the hole image
549  if (g.isVideoModeFormat7(videomode))
550  g.setFormat7ROI(roi_left, roi_top, roi_width, roi_height);
551 
552  // Array to know if color images or grey level images are acquired
553  bool *grab_color = new bool[ncameras];
554 
555 #ifdef VISP_HAVE_X11
556  // allocate a display for each camera to consider
557  vpDisplayX *d = nullptr;
558  if (display)
559  d = new vpDisplayX[ncameras];
560 #endif
561 
562  // allocate an Grey and color image for each camera to consider
563  vpImage<vpRGBa> *Ic = new vpImage<vpRGBa>[ncameras];
565 
566  // Do a first acquisition to initialise the display
567  for (unsigned int i = 0; i < ncameras; i++) {
568  // Set the active camera on the bus
569  g.setCamera(i + offset);
570  // Ask each camera to know if color images or grey level images are
571  // acquired
572  grab_color[i] = g.isColor();
573  // Acquire the first image
574  if (grab_color[i]) {
575  g.acquire(Ic[i]);
576  std::cout << "Image size for camera " << i + offset << " : width: " << Ic[i].getWidth()
577  << " height: " << Ic[i].getHeight() << std::endl;
578 
579 #ifdef VISP_HAVE_X11
580  if (display) {
581  // Initialise the display
582  std::stringstream title;
583  title << "Images captured by camera ";
584  title << i + offset;
585  d[i].init(Ic[i], (int)(100 + i * 50), (int)(100 + i * 50), title.str());
586  vpDisplay::display(Ic[i]);
587  vpDisplay::flush(Ic[i]);
588  }
589 #endif
590  }
591  else {
592  g.acquire(Ig[i]);
593  std::cout << "Image size for camera " << i + offset << " : width: " << Ig[i].getWidth()
594  << " height: " << Ig[i].getHeight() << std::endl;
595 
596 #ifdef VISP_HAVE_X11
597  if (display) {
598  // Initialise the display
599  std::stringstream title;
600  title << "Images captured by camera ";
601  title << i + offset;
602  d[i].init(Ig[i], (int)(100 + i * 50), (int)(100 + i * 50), title.str());
603  vpDisplay::display(Ig[i]);
604  vpDisplay::flush(Ig[i]);
605  }
606 #endif
607  }
608  }
609 
610  // Main loop for single or multi-camera acquisition and display
611  std::cout << "Capture in process..." << std::endl;
612 
613  double tbegin = 0, ttotal = 0;
614 
615  ttotal = 0;
616  tbegin = vpTime::measureTimeMs();
617  for (unsigned int i = 0; i < nframes; i++) {
618  for (unsigned int c = 0; c < ncameras; c++) {
619  // Set the active camera on the bus
620  g.setCamera(c + offset);
621  // Acquire an image
622  if (grab_color[c]) {
623  g.acquire(Ic[c]);
624 #ifdef VISP_HAVE_X11
625  if (display) {
626  // Display the last image acquired
627  vpDisplay::display(Ic[c]);
628  vpDisplay::flush(Ic[c]);
629  }
630 #endif
631  }
632  else {
633  g.acquire(Ig[c]);
634 #ifdef VISP_HAVE_X11
635  if (display) {
636  // Display the last image acquired
637  vpDisplay::display(Ig[c]);
638  vpDisplay::flush(Ig[c]);
639  }
640 #endif
641  }
642  if (save) {
643  char buf[FILENAME_MAX];
644  snprintf(buf, FILENAME_MAX, opath.c_str(), c + offset, i);
645  std::string filename(buf);
646  std::cout << "Write: " << filename << std::endl;
647  if (grab_color[c]) {
648  vpImageIo::write(Ic[c], filename);
649  }
650  else {
651  vpImageIo::write(Ig[c], filename);
652  }
653  }
654  }
655  double tend = vpTime::measureTimeMs();
656  double tloop = tend - tbegin;
657  tbegin = tend;
658  std::cout << "loop time: " << tloop << " ms" << std::endl;
659  ttotal += tloop;
660  }
661 
662  std::cout << "Mean loop time: " << ttotal / nframes << " ms" << std::endl;
663  std::cout << "Mean frequency: " << 1000. / (ttotal / nframes) << " fps" << std::endl;
664 
665  // Release the framegrabber
666  g.close();
667 
668  // Free memory
669 
670  delete[] Ic;
671  delete[] Ig;
672  delete[] grab_color;
673 
674 #ifdef VISP_HAVE_X11
675  if (display)
676  delete[] d;
677 #endif
678  return EXIT_SUCCESS;
679  }
680  catch (const vpException &e) {
681  std::cout << "Catch an exception: " << e << std::endl;
682  return EXIT_FAILURE;
683  }
684 }
685 #else
686 int main()
687 {
688  std::cout << "This example requires dc1394 SDK. " << std::endl;
689  std::cout << "Tip if you are on a unix-like system:" << std::endl;
690  std::cout << "- Install libdc1394-2, configure again ViSP using cmake and build again this example" << std::endl;
691  return EXIT_SUCCESS;
692  }
693 
694 #endif
Class for firewire ieee1394 video devices using libdc1394-2.x api.
static std::string colorCoding2string(vp1394TwoColorCodingType colorcoding)
static std::string framerate2string(vp1394TwoFramerateType fps)
static std::string videoMode2string(vp1394TwoVideoModeType videomode)
void init(vpImage< unsigned char > &I, int winx=-1, int winy=-1, const std::string &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:60
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
Definition: vpImageIo.cpp:291
unsigned int getWidth() const
Definition: vpImage.h:242
unsigned int getHeight() const
Definition: vpImage.h:181
static bool parse(int *argcPtr, const char **argv, vpArgvInfo *argTable, int flags)
Definition: vpParseArgv.cpp:70
VISP_EXPORT int wait(double t0, double t)
VISP_EXPORT double measureTimeMs()