首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用v4l2非常慢地捕获相机图像

用v4l2非常慢地捕获相机图像
EN

Stack Overflow用户
提问于 2015-03-26 08:00:40
回答 1查看 5.4K关注 0票数 7

我一直在使用v4l2直接获取OpenCV中的相机图像。这是非常好的工作方式;这样我就可以以YUYV格式并以高分辨率获取图像(理解框架将下降)。我无法用OpenCV实现完成这一任务。从功能上看,它运行得很好,但性能可能会好得多。由于这是我第一次直接使用v4l2,所以对我来说还有点模糊。我已经对所有相关部分进行了计时,并看到v4l2选择方法花费的时间超过了一秒钟。当我降低时间间隔时,select方法所需的时间较少,但要比去排队所需的时间长得多(也就是第二次)。在其他功能中,相机是初始化的,所以设置正确的格式等等。我理解框架将是低的,没有压缩和高分辨率,但这是极端低。

下面是捕获图像函数。我跳过了将缓冲区转换为Mat (YUYV -> RGB)的代码,因为我认为它目前并不相关。

有人知道如何让v4l2更快地捕获图像吗?也许有些地方我不应该执行每一个帧抓取?

谢谢!

代码语言:javascript
复制
Mat Camera::capture_image() {
Mat returnframe(10, 10, CV_8UC3);
struct v4l2_buffer buf = {0};
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
buf.index = 0;
if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) {
    perror("Query Buffer");
    return returnframe;
}

if (-1 == xioctl(fd, VIDIOC_STREAMON, &buf.type)) {
    perror("Start Capture");
    return returnframe;
}

fd_set fds;
FD_ZERO(&fds);
FD_SET(fd, &fds);
struct timeval tv = {0};
tv.tv_sec = 2;
int r = select(fd + 1, &fds, NULL, NULL, &tv);
if (-1 == r) {
    perror("Waiting for Frame");
    return returnframe;
}

if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) {
    perror("Retrieving Frame");
    return returnframe;
}

//转换为Mat的代码

代码语言:javascript
复制
if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &buf.type)) {
    perror("Stop Capture");
    return returnframe;
}

//copy Mat and free bigbuffer, to avoid memory leak
Mat returnImg = dispimg.clone();
free(bigbuffer);
return returnImg;
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-03-26 20:35:45

对于您正在调用的VIDIOC_STREAMONVIDIOC_STREAMOFF的每一个帧,似乎都会增加大量开销(几乎就像重新启动每个帧的应用程序一样)。

适当的办法是:

  • 打开设备(只调用一次):在捕获会话开始时(例如,程序启动),通过调用VIDIOC_STREAMON设置视频设备以启动流。
  • 捕获帧(被多次调用):对于要捕获的每个帧,只调用DQBUF/QBUF请求帧(这非常快,因为设备将不断地将数据流到缓冲区队列中);您仍然需要调用select才能知道何时有新的帧可用。
  • 关闭设备(只调用一次):一旦完成,通过调用VIDIOC_STREAMOFF停止流
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29273508

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档