从firewire摄像头获取彩色图像
下面的示例演示如何在Unix下使用framegrabber从firewire摄像头获取彩色图像。
下面的示例假设libX11和libdc1394-2第三方可用。
#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
}
在这里,我们解释了引入的新行。
首先创建帧抓取器的实例。在创建过程中,发送总线重置。如果不想重置firewire总线,只需将reset设置为false。
vp1394TwoGrabber g(reset);
创建抓取器后,我们设置相机图像大小、颜色编码和帧速率。
g.setVideoMode(vp1394TwoGrabber::vpVIDEO_MODE_640x480_MONO8);
g.setFramerate(vp1394TwoGrabber::vpFRAMERATE_60);
请注意,这里可以指定一些其他设置,例如firewire传输速度。有关更完整的设置列表,请参阅vp1394TwoGrabber类。
g.setIsoTransmissionSpeed(vp1394TwoGrabber::vpISO_SPEED_800);
Then the grabber is initialized using:
g.open(I);
从现在起,彩色图像I也将初始化为与抓取器设置相对应的大小。
然后,我们进入一个while循环,其中图像采集只需通过以下方式完成:
g.acquire(I);
我们正在等待非阻塞鼠标事件在结束程序之前中断while循环。
if (vpDisplay::getClick(I, false)) break;
在上一个示例中,我们使用vp1394TwoGrabber类,该类在Unix下适用于firewire摄像头。如果您在Windows下,则可以使用vp1394CMUGrabber类。教程-grabber-CMU1394.cpp中提供了类似的示例。
从USB等摄像机采集图像
如果您想在Unix下从usb摄像头抓取图像,可以使用VPV4L2GRABER类。为此,应安装libv4l。教程-grabber-v4l2.cpp中提供了一个示例。
#include <visp/vpV4l2Grabber.h>
#include <visp/vpDisplayX.h>
#include <visp/vpImage.h>
int main()
{
#ifdef VISP_HAVE_V4L2
try{
vpImage<unsigned char> I;
vpV4l2Grabber g;
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
}
也可以使用OpenCV抓取图像。您可以在教程grabber opencv和教程opencv-bis.cpp中找到示例添加链接描述。
当然让还有其他很多方法
来自视频流的图像
使用ViSP还可以从输入视频流中获取图像。为此,我们利用ffmpeg第三方。下面的示例在教程grabber视频中提供。CPP显示了如何考虑MPEG视频流:
#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
}
我们现在解释一下导入的一些库。
#include <visp/vpTime.h>
#include <visp/vpVideoReader.h>
包括允许测量时间的vpTime类的标头,以及允许读取视频流的vpVideoReader类的标头。
vpVideoReader g;
创建视频读取器的实例。
g.setFileName("./video.mpg");
设置视频流的名称。这里是视频。mpg是指与可执行文件位于同一文件夹中的mpeg文件。
vpVideoReader类还可以处理一系列图像。例如,要读取以下图像:
% ls *.png
image0000.png
image0001.png
image0002.png
image0003.png
image0004.png
...
您可以使用以下命令
```cpp
g.setFileName("./image%04d.png");
其中指定每个图像编号用4位数字编码。在这里,ffmpeg还不是强制性的,而是应该可用于读取PNG图像的libpng。支持的图像格式有PPM、PGM、PNG和JPEG。在最后一种情况下,应该安装libjpeg。
然后,对于任何其他抓取器,必须使用以下命令初始化帧抓取器:
g.open(I);
然后,我们进入while循环,直到没有到达最后一个图像:
while (! g.end() ) {
要获取流中的下一个图像,我们只需使用:
g.acquire(I);
为了使视频解码与视频帧率同步,我们测量每个循环迭代的开始时间:
double t = vpTime::measureTimeMs();
通过使用以下命令,从迭代开始等待以毫秒为单位的相应时间来完成同步:
vpTime::wait(t, 1000. / g.getFramerate());