首页 USB摄像头视频采集与QT界面显示

USB摄像头视频采集与QT界面显示

举报
开通vip

USB摄像头视频采集与QT界面显示USB摄像头视频采集与QT界面显示 USB摄像头视频采集与Qt界面显示 一( Qt界面制作 1( 新建Qt工程 启动Qt Creator,新建一个Qt Gui应用。 单击File选择New File or Project出现以下界面: 选择Qt Gui Application,之后选择好工程与路径名,其他默认,一直到设置Class information(类信息)时,Class name设为Widget, Base name选择QWidget,其他默认。设置好这些后,其他默认,直到工程设置结束。如下...

USB摄像头视频采集与QT界面显示
USB摄像头视频采集与QT界面显示 USB摄像头视频采集与Qt界面显示 一( Qt界面制作 1( 新建Qt工程 启动Qt Creator,新建一个Qt Gui应用。 单击File选择New File or Project出现以下界面: 选择Qt Gui Application,之后选择好工程与路径名,其他默认,一直到设置Class information(类信息)时,Class name设为Widget, Base name选择QWidget,其他默认。设置好这些后,其他默认,直到工程设置结束。如下图所示: 2. 修改ui界面 打开Widget.ui,进入可视化设计界面。默认情况中间的主设计区下只有一个Widget的对象。由于USB摄像头采集到的图像需要显示到一个QLabel的部件上,从右侧的部件列表的“DisplayWidget”中选择“Label”部件拖动到中间;此外,我们需要两个按钮,一个用于启动和终止视频数据的保存,一个用于以后的视频文件的压缩。从右侧的”Buttons”中两次选择”Push Buttion”部件并拖动到Widget中。 从上图可以看出,对象Widget下已经添加了一个label部件,两个push button部件。右上角Object与Class的关系是:Object对应的物体是属于Class对应的类,反映了Qt的继承关系。 接下来设置上面四种部件的属性,Widget的属性按照下面图示设置,其中geometry设置为[(0,0),650*550]说明界面左上角的坐标位于原点,大小为650*550;在window name这一项设置的是你的界面的名字,我设置为USB_YUV_Camera。 注:图片未提及的采用默认就行,其他三个部件见图示。这些部件的objectName要特别注意,因为会在后面编写的程序中用到。 (Widget设置图示) (label设置图示1) (label设置图示2) (Push button 1设置图示) (Push button 1设置图示) (Push button 2设置图示) Push button 2设置图示) 最后生成的界面: 点击Debug会得到Debug文档,里面有你设置的信息。 编译运行后,会在建立的工程文件夹下生成很多文件,重要的是widget.ui文件,其他 的文件要根据你具体的应用作出相应的修改。 Qt界面最终的效果图为: 二( USB摄像头视频采集与Qt界面显示源代码分析 源码包含:common.h VideoDevice.h widget.h VideoDevice.cpp widget.cpp main.cpp common.h主要定义了USB采集到的图像的宽度,高度等信息; Videodevice.h定义了VideoDevice类,使它继承于Qt的基类QObject,定义了VideoDevice的构造函数与析构函数,重要的是定义了实现V4L2视频架构的函数; Videodevice.cpp具体实现了Videodevice.h定义的函数,完成了基于V4L2架构的视频采集; widget.h定义了Widget窗口类,使它继承于Qt窗口类QWidget,并定义了YUV到RGB颜色转变的函数;QT界面按钮操作的实现函数,以及视频窗口的刷新时间painEvent函数; widget.cpp实现了widget.h定义的函数。 下面介绍各文件的主要代码段: (1)common.h #ifndef COMMON_H #define COMMON_H //… … #define IMG_WIDTH 640//定义视频的宽度为640 #define IMG_HEIGTH 480//定义视频的高度为480 #endif // COMMON_H (2) Videodevice.h #define CLEAR(x) memset(&(x), 0, sizeof(x))//定义CLEAR为内存清零 class VideoDevice : public QObject { Q_OBJECT //有了这条语句才能使用QT中的signal和slot机制 public: VideoDevice(QString dev_name);//构造函数定义,用于初始化 ~VideoDevice();//析构函数用于释放内存 int get_frame(unsigned char ** yuv_buffer_pointer, size_t* len);//获取视频帧 int unget_frame();//释放视频帧,让出缓存空间准备新的视频帧数据 private: int open_device();//打开设备 int init_device();//初始化设备 int start_capturing();//启动视频采集 int init_mmap();//内存映射初始化 int stop_capturing();//停止视频采集 int uninit_device();//注销设备 int close_device();//关闭设备 struct buffer { void * start;//视频缓冲区的起始地址 size_t length;//缓冲区的长度 }; QString dev_name; int fd;//video0 file buffer* buffers; unsigned int n_buffers; int index; signals: //void display_error(QString); }; #endif // VIDEODEVICE_H (3)Videodevice.cpp #define FILE_VIDEO "/dev/video0" VideoDevice::VideoDevice(QString dev_name)//VideoDevice的构造函数进行初始化 { this->dev_name = dev_name; this->fd = -1; this->buffers = NULL; this->n_buffers = 0; this->index = -1; if(open_device() == FALSE) { close_device(); } if(init_device() == FALSE) { close_device(); } if(start_capturing() == FALSE) { stop_capturing(); close_device(); } } VideoDevice::~VideoDevice()//VideoDevice的析构函数 { if(stop_capturing() == FALSE) {} if(uninit_device() == FALSE) { } if(close_device() == FALSE) {} } int VideoDevice::init_device()//设备初始化 { v4l2_capability cap;//设备能力结构体 v4l2_format fmt;//设置视频像素 v4l2_streamparm setfps;//设置采样率 v4l2_fmtdesc fmtdesc;//查询摄像头支持像素格式 if(ioctl(fd, VIDIOC_QUERYCAP, &cap) == -1) { printf("Error opening device %s: unable to query device.\n",FILE_VIDEO); return FALSE; } else { printf("driver:\t\t%s\n",cap.driver);//驱动名 printf("card:\t\t%s\n",cap.card);//摄像头信息 printf("bus_info:\t%s\n",cap.bus_info);//PCI总线信息 printf("version:\t%d\n",cap.version);//内核版本 printf("capabili ties:\t%x\n",cap.capabilities); //以上打印信息详见设备能力结构体(struct v4l2_capability) if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { printf("Device %s: supports capture.\n",FILE_VIDEO); } if ((cap.capabilities & V4L2_CAP_STREAMING)) { printf("Device %s: supports streaming.\n",FILE_VIDEO); } } //列举摄像头所支持像素格式 fmtdesc.index=0; fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE; printf("Support format:\n"); while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!=-1) { printf("\t%d.%s\n",fmtdesc.index+1,fmtdesc.description); fmtdesc.index++; } //set fmt fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;//恒为此项 fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV;//视频数据存储类型 fmt.fmt.pix.height = 480; fmt.fmt.pix.width = 640; fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;//隔行扫描 if(ioctl(fd, VIDIOC_S_FMT, &fmt) == -1) { printf("Unable to set format\n"); return FALSE; } if(ioctl(fd, VIDIOC_G_FMT, &fmt) == -1) { printf("Unable to get format\n"); return FALSE; } //set fps 具体参考结构体v4l2_captureparm setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; /*timeperframe字段用于指定想要使用的帧频率,它是一个结构体: numerator 和denominator所描述的系数给出的是成功的帧之间的时间间隔。 numerator分子,denominator分母。主要表达每次帧之间时间间隔。numerator/denominator秒一帧。*/ setfps.parm.capture.timeperframe.numerator = 1; setfps.parm.capture.timeperframe.denominator = 30;//本摄像头帧频范围[5,30]帧/秒 if(ioctl(fd, VIDIOC_S_PARM, &setfps) == -1) { printf("Unable to set frame rate\n"); return FALSE; } else { printf("set fps OK!\n"); } if(ioctl(fd, VIDIOC_G_PARM, &setfps) == -1) { printf("Unable to get frame rate\n"); return FALSE; } else { printf("get fps OK!\n"); printf("timeperframe.numerator:\t%d\n",setfps.parm.capture.timeperframe.numerator); printf("timeperframe.denominator:\t%d\n",setfps.parm.capture.timeperframe.denominator); } //mmap if(init_mmap() == FALSE ) { printf("cannot mmap!\n"); return FALSE; } return TRUE; } (4)widget.h namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT //上面内容为固定格式 public: explicit Widget(QWidget *parent = 0);//explicit可以避免发生隐式类型转换 ~Widget(); private: Ui::Widget *ui; QImage *frame; int rs; unsigned int len; int convert_yuv_to_rgb_buffer(); void print_quartet(unsigned int i); VideoDevice *vd; FILE * yuvfile; unsigned char rgb_buffer[640*480*3]; unsigned char * yuv_buffer_pointer; char Y_frame[640*480];//存储亮度Y分量 char Cr_frame[240*320]; //存储蓝色浓度偏移量即U分量 char Cb_frame[240*320]; //存储红色浓度偏移量即V分量 int write420();//视频图像保存为YUV420,也可存储为YUV422 private slots://定义槽 void on_pushButton_start_clicked();//按钮按下对应的处理,不定义成槽,按钮将失效 void paintEvent(QPaintEvent *);//窗口刷新函数 }; #endif // WIDGET_H (5) widget.cpp char yuvfilename[11] = {'s','a','v','e','0','0','.','y','u','v','\0'};//视频保存文件的名称 Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); vd = new VideoDevice(tr("/dev/video0")); frame = new QImage(rgb_buffer,640,480,QImage::Format_RGB888); } void Widget::paintEvent(QPaintEvent *) { rs = vd->get_frame(&yuv_buffer_pointer,&len); if(last_state==2 && state == 0) { yuvfile = fopen(yuvfilename,"wb+"); yuvfilename[5]++; } if(state == 1) { rs = write420(); } if(last_state==1 && state==2) { fclose(yuvfile); } int Widget::write420() { int x,y; long int index1 =0; if (yuv_buffer_pointer[0] == '\0') { return -1; } for(x=0;x<640;x++) { for(y=0;y<480;y++) { Y_frame[index1]=yuv_buffer_pointer[2*index1]; index1++; } } index1=0; for(x=0;x<480;x++,x++) { for(y=0;y<640;y++,y++) { Cb_frame[index1]=yuv_buffer_pointer[(x*640+y)*2+1]; Cr_frame[index1]=yuv_buffer_pointer[(x*640+y)*2+3]; index1++; } } //YUV422的程序 /* for(x=0;x<480;x++) { for(y=0;y<320;y++) { Y_frame[index]= yuv_buffer_pointer[(x*320+y)*4]; Cb_frame[index]= yuv_buffer_pointer[(x*320+y)*4 + 1]; Y_frame[index+1]= yuv_buffer_pointer[(x*320+y)*4 + 2]; Cr_frame[index]= yuv_buffer_pointer [(x*320+y)*4 + 3]; index++; } }*/ fwrite(Y_frame, 307200, 1, yuvfile); fwrite(Cb_frame,76800, 1, yuvfile); fwrite(Cr_frame,76800, 1, yuvfile); framecnt++; printf("writed frame %ld\n",framecnt); } int Widget::convert_yuv_to_rgb_buffer() { unsigned long in, out = 0; int y0, u, y1, v; int r, g, b; for(in = 0; in < IMG_WIDTH * IMG_HEIGTH * 2; in += 4) { y0 = yuv_buffer_pointer[in + 0]; u = yuv_buffer_pointer[in + 1]; y1 = yuv_buffer_pointer[in + 2]; v = yuv_buffer_pointer[in + 3]; r = y0 + (1.370705 * (v-128)); g = y0 - (0.698001 * (v-128)) - (0.337633 * (u-128)); b = y0 + (1.732446 * (u-128)); /* r = y0 + 1.042*(v-128); g = y0 - 0.34414*(u-128) - 0.71414*(v-128); b = y0 + 1.772*(u-128);*/ // YUV422程序 if(r > 255) r = 255; if(g > 255) g = 255; if(b > 255) b = 255; if(r < 0) r = 0; if(g < 0) g = 0; if(b < 0) b = 0; rgb_buffer[out++] = r; rgb_buffer[out++] = g; rgb_buffer[out++] = b; r = y1 + (1.370705 * (v-128)); g = y1 - (0.698001 * (v-128)) - (0.337633 * (u-128)); b = y1 + (1.732446 * (u-128)); /* r = y0 + 1.042*(v-128); g = y0 - 0.34414*(u-128) - 0.71414*(v-128); b = y0 + 1.772*(u-128);*/ // YUV422程序 if(r > 255) r = 255; if(g > 255) g = 255; if(b > 255) b = 255; if(r < 0) r = 0; if(g < 0) g = 0; if(b < 0) b = 0; rgb_buffer[out++] = r; rgb_buffer[out++] = g; rgb_buffer[out++] = b; } return 0; } void Widget::on_pushButton_start_clicked() { switch(state) { case 0: { ui->pushButton_start->setText("stop save"); state = 1; break; } case 1: { ui->pushButton_start->setText("save again"); state = 2; break; } case 2: { ui->pushButton_start->setText("start save"); framecnt=0; state = 0; break; } default :break; } (6) main.cpp #include #include "widget.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); } 三( 运行效果 点击保存按钮后存放视频的文件,当关闭时自动生成下一个 save01.yuv文件已接受下次视频数据,以此类推。
本文档为【USB摄像头视频采集与QT界面显示】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。
下载需要: 免费 已有0 人下载
最新资料
资料动态
专题动态
is_511210
暂无简介~
格式:doc
大小:313KB
软件:Word
页数:24
分类:其他高等教育
上传时间:2017-09-02
浏览量:221