zoukankan      html  css  js  c++  java
  • 视频的采集和动态显示

    (原创)基于ZedBoard的Webcam设计(一):USB摄像头(V4L2接口)的图片采集(原创)基于ZedBoard的Webcam设计(二):USB摄像头图片采集+QT显示两篇博客中,我们完成了ZedBoard上USB摄像头的图片采集,以及将图片显示到Qt界面上。可是毕竟采集和显示到只是一帧图像,并非动态的视频数据。本小节将在介绍V4L2更新视频缓冲的方式、Qt paintEvent更新控件的基础上,实现如何实现视频的动态显示。

    更多更新请关注我的博客:@超群天晴 http://www.cnblogs.com/surpassal/

    一、V4l2更新缓冲Buffer的方法

     回顾上一节中,我们使用v4l2控制usb 摄像头,对摄像头的静态图片采集流程操作过程可以归纳为:

    静态图片采集流程图

    所用到的函数和参数都在旁边标注出。可以看到使用命令VIDIOC_DQBUF将缓存中的图像帧取出,然后摄像头设备是一直在采集图像,如果没有更新缓存区命令,采集到的新数据是不会被更新到缓存中的。v4l2提供了与VIDIOC_DQBUF命令相对的命令VIDIOC_QBUF,我对这个命令的理解就是允许摄像头设备将采集图像更新到缓存区。所以为了实现缓存区图像数据的动态更新,需要在每一次处理完数据后更新缓存区,以便下一次DQBUF获取到的是新的一帧数据。

     

    动态视频采集流程

     为此,需要重新定义两个函数,一个我们定义为get_frame,意为获取视频帧:

    复制代码
     1 int VideoDevice::get_frame(void **frame_buf, size_t* len)
     2 {
     3     v4l2_buffer queue_buf;
     4 
     5     queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     6     queue_buf.memory = V4L2_MEMORY_MMAP;
     7 
     8     if(ioctl(fd, VIDIOC_DQBUF, &queue_buf) == -1)
     9     {
    10         return FALSE;
    11     }
    12 
    13     *frame_buf = buffers[queue_buf.index].start;
    14     *len = buffers[queue_buf.index].length;
    15     index = queue_buf.index;
    16 
    17     return TRUE;
    18 }
    复制代码

    一个为free_frame,意为释放视频帧,让出缓存空间准备新的视频帧数据:

    复制代码
     1 int VideoDevice::free_frame()
     2 {
     3     if(index != -1)
     4     {
     5         v4l2_buffer queue_buf;
     6         queue_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
     7         queue_buf.memory = V4L2_MEMORY_MMAP;
     8         queue_buf.index = index;
     9 
    10         if(ioctl(fd, VIDIOC_QBUF, &queue_buf) == -1)
    11         {
    12             return FALSE;
    13         }
    14         return TRUE;
    15     }
    16     return FALSE;
    17 }
    复制代码

     二、Qt的paintEvent事件

    在上篇博客里面,我们对采集的的视频帧数据的显示,采用的方法是使用了一个QLabel和QPixmap,并使用loadfromdata函数将采集的数据转为QPixmap中的数据,并显示到QLabel上。这样的做法导致的结果是QLabel和QPixmap数据只能被更新一次,所以只能显示静态图片。

    在完成了视频缓存数据更新后,我们所面临的问题就是怎么样才能把这个数据动态显示出来。好在Qt提供了窗口刷新事件paintEvent,在这里,我们可以使用两种方式触发paintEvent事件:

    1、使用定时器QTimer,定时为33ms(因为摄像头的帧频为30pfs);

    2、不使用定时器,由QLabel自身内容改变产生。这里采用这种方式。paintEvent函数内容:

    复制代码
     1 void Widget::paintEvent(QPaintEvent *)
     2 {
     3     rs = vd->get_frame((void **)&yuv_buffer,&len);
     4     convert_yuv_to_rgb_buffer(yuv_buffer,rgb_buffer,640,480);
     5 
     6     frame->loadFromData((uchar *)rgb_buffer,640 * 480 * 3);
     7 
     8     ui->label->setPixmap(QPixmap::fromImage(*frame,Qt::AutoColor));
     9 
    10     rs = vd->unget_frame();
    11 }
    复制代码

    三、测试效果

    在ubuntu上测试通过后,移植到Zedboard上进行测试,测试视频:

    ==================================

    可执行代码下载:zed_webcam_lab3.rar

     
     
    分类: LinuxQtXilinxZedBoardZynq嵌入式
  • 相关阅读:
    学习流程
    Linux计划任务 定时任务 Crond 配置详解 crond计划任务调试 sh x 详解 JAVA脚本环境变量定义
    asp.net 将Excel中某个工作簿的数据导入到DataTable方法
    在浏览器输入url,发生了什么?BSC结构图(百度搜索关键字发生了什么?)
    在C#中使用属性控件添加属性窗口
    转载:面向对象在数据库应用程序中的应用(dotNet)
    中国软件:10个人20年坎坷路
    客户端回调
    鼠标放在图片连接上面,预览图片
    一个合格的程序员该做的事情
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2857922.html
Copyright © 2011-2022 走看看