Visual servo control tool visual servo platform --- VISP --- get image from camera

Posted by Chimera on Thu, 06 Jan 2022 14:06:12 +0100

The following example demonstrates how to use framegrabber to obtain color images from a firewire camera under Unix.
The following example assumes that libX11 and libdc1394-2 are available to third parties.

#include <visp/vp1394TwoGrabber.h>
#include <visp/vpDisplayX.h>
#include <visp/vpImage.h>
int main()
{
#ifdef VISP_HAVE_DC1394_2
  try {
    vpImage<unsigned char> I; // Create a gray level image container
    bool reset = true; // Enable bus reset during construction (default)
    vp1394TwoGrabber g(reset); // Create a grabber based on libdc1394-2.x third party lib
    g.setVideoMode(vp1394TwoGrabber::vpVIDEO_MODE_640x480_MONO8);
    g.setFramerate(vp1394TwoGrabber::vpFRAMERATE_60);
    g.open(I);
    std::cout << "Image size: " << I.getWidth() << " " << I.getHeight() << std::endl;
#ifdef VISP_HAVE_X11
    vpDisplayX d(I);
#else
    std::cout << "No image viewer is available..." << std::endl;
#endif
    while(1) {
      g.acquire(I);
      vpDisplay::display(I);
      vpDisplay::flush(I);
      if (vpDisplay::getClick(I, false))
        break;
    }
  }
  catch(vpException e) {
    std::cout << "Catch an exception: " << e << std::endl;
  }
#endif
}

Here, we explain the new line introduced.

First, create an instance of the frame grabber. During creation, a bus reset is sent. If you don't want to reset the firewall bus, just set reset to false.

vp1394TwoGrabber g(reset);

After creating the grabber, we set the camera image size, color coding and frame rate.

g.setVideoMode(vp1394TwoGrabber::vpVIDEO_MODE_640x480_MONO8);
g.setFramerate(vp1394TwoGrabber::vpFRAMERATE_60);

Note that some other settings can be specified here, such as firewall transmission speed. For a more complete list of settings, see the vp1394TwoGrabber class.

g.setIsoTransmissionSpeed(vp1394TwoGrabber::vpISO_SPEED_800);

Then the grabber is initialized using:

g.open(I);

From now on, the color image I will also be initialized to a size corresponding to the gripper setting.
Then, we enter a while loop, in which the image acquisition only needs to be completed in the following ways:

g.acquire(I);

We are waiting for a non blocking mouse event to break the while loop before ending the program.

if (vpDisplay::getClick(I, false)) break;

In the previous example, we used the vp1394TwoGrabber class, which is suitable for firewire cameras under Unix. If you are under Windows, you can use the vp1394CMUGrabber class. Tutorial - grabber-cmu1394 A similar example is provided in CPP.

Images from other cameras

If you want to capture images from a usb camera under Unix, you can use the VPV4L2GRABER class. To do this, install libv4l. Tutorial - grabber-v4l2 An example is provided in CPP.

You can also use OpenCV to capture images. You can find examples in the tutorial grabber OpenCV. CPP and tutorial grabber opencv BIS cpp.
Of course, there are many other ways

Image from video stream

ViSP can also be used to obtain images from the input video stream. To this end, we use ffmpeg third party. The following example is provided in the tutorial grabber video. CPP shows how to consider MPEG video streams:

#include <visp/vpDisplayX.h>
#include <visp/vpVideoReader.h>
int main()
{
#ifdef VISP_HAVE_FFMPEG
  try {
    vpImage<unsigned char> I;
    vpVideoReader g;
    g.setFileName("./video.mpg");
    g.open(I);
    std::cout << "video framerate: " << g.getFramerate() << "Hz" << std::endl;
    std::cout << "video dimension: " << I.getWidth() << " " << I.getHeight() << std::endl;
#ifdef VISP_HAVE_X11
    vpDisplayX d(I);
#else
    std::cout << "No image viewer is available..." << std::endl;
#endif
    vpDisplay::setTitle(I, "Video grabber");
    while (! g.end() ) {
      double t = vpTime::measureTimeMs();
      g.acquire(I);
      vpDisplay::display(I);
      vpDisplay::flush(I);
      if (vpDisplay::getClick(I, false)) break;
      vpTime::wait(t, 1000. / g.getFramerate());
    }
  }
  catch(vpException e) {
    std::cout << "Catch an exception: " << e << std::endl;
  }
#endif
}

Let's now explain some of the imported libraries.

#include <visp/vpTime.h>
#include <visp/vpVideoReader.h>

This includes the header of the vpTime class that allows the measurement of time and the header of the vpVideoReader class that allows the reading of video streams.

vpVideoReader g;

Create an instance of the video reader.

g.setFileName("./video.mpg");

Sets the name of the video stream. Here is the video. mpg refers to an mpeg file located in the same folder as the executable file.
The vpVideoReader class can also process a series of images. For example, to read the following image:

% ls *.png
image0000.png
image0001.png
image0002.png
image0003.png
image0004.png
...
You can use the following commands
```cpp
g.setFileName("./image%04d.png");

It specifies that each image number is encoded with 4 digits. Here, ffmpeg is not mandatory, but libpng that should be used to read PNG images. Supported image formats are PPM, PGM, PNG and JPEG. In the last case, libjpeg should be installed.
Then, for any other grabber, the frame grabber must be initialized with the following command:

g.open(I);

Then, we enter the while loop until we don't reach the last image:

while (! g.end() ) {

To get the next image in the stream, we just use:

g.acquire(I);

In order to synchronize video decoding with video frame rate, we measure the start time of each loop iteration:

double t = vpTime::measureTimeMs();

Complete the synchronization by waiting for the corresponding time in milliseconds from the beginning of the iteration using the following command:

vpTime::wait(t, 1000. / g.getFramerate());

Topics: C++ Visual Studio