USB摄像头视频采集与QT界面显示分析.docx

上传人:b****3 文档编号:3816778 上传时间:2023-05-06 格式:DOCX 页数:23 大小:1.06MB
下载 相关 举报
USB摄像头视频采集与QT界面显示分析.docx_第1页
第1页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第2页
第2页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第3页
第3页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第4页
第4页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第5页
第5页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第6页
第6页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第7页
第7页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第8页
第8页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第9页
第9页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第10页
第10页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第11页
第11页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第12页
第12页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第13页
第13页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第14页
第14页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第15页
第15页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第16页
第16页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第17页
第17页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第18页
第18页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第19页
第19页 / 共23页
USB摄像头视频采集与QT界面显示分析.docx_第20页
第20页 / 共23页
亲,该文档总共23页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

USB摄像头视频采集与QT界面显示分析.docx

《USB摄像头视频采集与QT界面显示分析.docx》由会员分享,可在线阅读,更多相关《USB摄像头视频采集与QT界面显示分析.docx(23页珍藏版)》请在冰点文库上搜索。

USB摄像头视频采集与QT界面显示分析.docx

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

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

一.Qt界面制作

1.新建Qt工程

启动QtCreator,新建一个QtGui应用。

单击File选择NewFileorProject出现以下界面:

选择QtGuiApplication,之后选择好工程与路径名,其他默认,一直到设置Classinformation(类信息)时,Classname设为Widget,Basename选择QWidget,其他默认。

设置好这些后,其他默认,直到工程设置结束。

如下图所示:

2.修改ui界面

打开Widget.ui,进入可视化设计界面。

默认情况中间的主设计区下只有一个Widget的对象。

由于USB摄像头采集到的图像需要显示到一个QLabel的部件上,从右侧的部件列表的“DisplayWidget”中选择“Label”部件拖动到中间;此外,我们需要两个按钮,一个用于启动和终止视频数据的保存,一个用于以后的视频文件的压缩。

从右侧的”Buttons”中两次选择”PushButtion”部件并拖动到Widget中。

从上图可以看出,对象Widget下已经添加了一个label部件,两个pushbutton部件。

右上角Object与Class的关系是:

Object对应的物体是属于Class对应的类,反映了Qt的继承关系。

接下来设置上面四种部件的属性,Widget的属性按照下面图示设置,其中geometry设置为[(0,0),650*550]说明界面左上角的坐标位于原点,大小为650*550;在windowname这一项设置的是你的界面的名字,我设置为USB_YUV_Camera。

注:

图片未提及的采用默认就行,其他三个部件见图示。

这些部件的objectName要特别注意,因为会在后面编写的程序中用到。

(Widget设置图示)(label设置图示1)(label设置图示2)

(Pushbutton1设置图示)(Pushbutton1设置图示)

(Pushbutton2设置图示)Pushbutton2设置图示)

最后生成的界面:

点击Debug会得到Debug文档,里面有你设置的信息。

编译运行后,会在建立的工程文件夹下生成很多文件,重要的是widget.ui文件,其他的文件要根据你具体的应用作出相应的修改。

Qt界面最终的效果图为:

二.USB摄像头视频采集与Qt界面显示源代码分析

源码包含:

common.hVideoDevice.hwidget.hVideoDevice.cppwidget.cppmain.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

#ifndefCOMMON_H

#defineCOMMON_H

//……

#defineIMG_WIDTH640//定义视频的宽度为640

#defineIMG_HEIGTH480//定义视频的高度为480

#endif//COMMON_H

(2)Videodevice.h

#defineCLEAR(x)memset(&(x),0,sizeof(x))//定义CLEAR为内存清零

classVideoDevice:

publicQObject

{

Q_OBJECT//有了这条语句才能使用QT中的signal和slot机制

public:

VideoDevice(QStringdev_name);//构造函数定义,用于初始化

~VideoDevice();//析构函数用于释放内存

intget_frame(unsignedchar**yuv_buffer_pointer,size_t*len);//获取视频帧

intunget_frame();//释放视频帧,让出缓存空间准备新的视频帧数据

private:

intopen_device();//打开设备

intinit_device();//初始化设备

intstart_capturing();//启动视频采集

intinit_mmap();//内存映射初始化

intstop_capturing();//停止视频采集

intuninit_device();//注销设备

intclose_device();//关闭设备

structbuffer

{

void*start;//视频缓冲区的起始地址

size_tlength;//缓冲区的长度

};

QStringdev_name;

intfd;//video0file

buffer*buffers;

unsignedintn_buffers;

intindex;

signals:

//voiddisplay_error(QString);

};

#endif//VIDEODEVICE_H

(3)Videodevice.cpp

#defineFILE_VIDEO"/dev/video0"

VideoDevice:

:

VideoDevice(QStringdev_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)

{}

}

intVideoDevice:

:

init_device()//设备初始化

{

v4l2_capabilitycap;//设备能力结构体

v4l2_formatfmt;//设置视频像素

v4l2_streamparmsetfps;//设置采样率

v4l2_fmtdescfmtdesc;//查询摄像头支持像素格式

if(ioctl(fd,VIDIOC_QUERYCAP,&cap)==-1)

{

printf("Erroropeningdevice%s:

unabletoquerydevice.\n",FILE_VIDEO);

returnFALSE;

}

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("capabilities:

\t%x\n",cap.capabilities);

//以上打印信息详见设备能力结构体(structv4l2_capability)

if((cap.capabilities&V4L2_CAP_VIDEO_CAPTURE))

{

printf("Device%s:

supportscapture.\n",FILE_VIDEO);

}

if((cap.capabilities&V4L2_CAP_STREAMING))

{

printf("Device%s:

supportsstreaming.\n",FILE_VIDEO);

}

}

//列举摄像头所支持像素格式

fmtdesc.index=0;

fmtdesc.type=V4L2_BUF_TYPE_VIDEO_CAPTURE;

printf("Supportformat:

\n");

while(ioctl(fd,VIDIOC_ENUM_FMT,&fmtdesc)!

=-1)

{

printf("\t%d.%s\n",fmtdesc.index+1,fmtdesc.description);

fmtdesc.index++;

}

//setfmt

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("Unabletosetformat\n");

returnFALSE;

}

if(ioctl(fd,VIDIOC_G_FMT,&fmt)==-1)

{

printf("Unabletogetformat\n");

returnFALSE;

}

//setfps具体参考结构体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("Unabletosetframerate\n");

returnFALSE;

}

else

{

printf("setfpsOK!

\n");

}

if(ioctl(fd,VIDIOC_G_PARM,&setfps)==-1)

{

printf("Unabletogetframerate\n");

returnFALSE;

}

else

{

printf("getfpsOK!

\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("cannotmmap!

\n");

returnFALSE;

}

returnTRUE;

}

(4)widget.h

namespaceUi{

classWidget;

}

classWidget:

publicQWidget

{

Q_OBJECT//上面内容为固定格式

public:

explicitWidget(QWidget*parent=0);//explicit可以避免发生隐式类型转换

~Widget();

private:

Ui:

:

Widget*ui;

QImage*frame;

intrs;

unsignedintlen;

intconvert_yuv_to_rgb_buffer();

voidprint_quartet(unsignedinti);

VideoDevice*vd;

FILE*yuvfile;

unsignedcharrgb_buffer[640*480*3];

unsignedchar*yuv_buffer_pointer;

charY_frame[640*480];//存储亮度Y分量

charCr_frame[240*320];//存储蓝色浓度偏移量即U分量

charCb_frame[240*320];//存储红色浓度偏移量即V分量

intwrite420();//视频图像保存为YUV420,也可存储为YUV422

privateslots:

//定义槽

voidon_pushButton_start_clicked();//按钮按下对应的处理,不定义成槽,按钮将失效

voidpaintEvent(QPaintEvent*);//窗口刷新函数

};

#endif//WIDGET_H

(5)widget.cpp

charyuvfilename[11]={'s','a','v','e','0','0','.','y','u','v','\0'};//视频保存文件的名称

Widget:

:

Widget(QWidget*parent):

QWidget(parent),

ui(newUi:

:

Widget)

{

ui->setupUi(this);

vd=newVideoDevice(tr("/dev/video0"));

frame=newQImage(rgb_buffer,640,480,QImage:

:

Format_RGB888);

}

voidWidget:

:

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);

}

intWidget:

:

write420()

{

intx,y;

longintindex1=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("writedframe%ld\n",framecnt);

}

intWidget:

:

convert_yuv_to_rgb_buffer()

{

unsignedlongin,out=0;

inty0,u,y1,v;

intr,g,b;

for(in=0;in

{

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;

}

return0;

}

voidWidget:

:

on_pushButton_start_clicked()

{

switch(state)

{

case0:

{

ui->pushButton_start->setText("stopsave");

state=1;

break;

}

case1:

{

ui->pushButton_start->setText("saveagain");

state=2;

break;

}

case2:

{

ui->pushButton_start->setText("startsave");

framecnt=0;

state=0;

break;

}

default:

break;

}

(6)main.cpp

#include

#include"widget.h"

intmain(intargc,char*argv[])

{

QApplicationa(argc,argv);

Widgetw;

w.show();

returna.exec();

}

三.运行效果

点击保存按钮后存放视频的文件,当关闭时自动生成下一个save01.yuv文件已接受下次视频数据,以此类推。

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 党团工作 > 入党转正申请

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2