opencv视频学习第五课(视频播放控制)笔记整理

来源:互联网 发布:cent 7 在线音乐软件 编辑:程序博客网 时间:2024/06/09 14:33
这次是学习怎么创建一个控制台的滚动条,并且使用它控制视频的播放。为了测试一些东西,改编了视频教程中的代码。
#include "stdafx.h"#include "highgui.h"#include "cv.h"CvCapture* g_capture = NULL;//记录滚动条的当前位置int g_slider_pos = 0;//对视频帧进行计数的变量int frame_count = 0;void onTrackbarSlider(int pos)//回调函数{//设置g_capture的属性,从位置pos开始播放视频cvSetCaptureProperty(g_capture,CV_CAP_PROP_POS_FRAMES,//单位为帧数的位置pos//当前滚动条的位置);frame_count =pos;//printf("frame_count is %dpos is %d\n-------\n",frame_count,pos);}int main(int argc, char* argv[]){IplImage* frame;cvNamedWindow("show");CvCapture* tmp = cvCreateFileCapture("E:\\狸窝转换结果\\oldfriends.avi");printf("使用代码1.2,屏蔽代码1.1和代码2.1\n");/*-----------------1、获取总帧数---------*/frame = cvQueryFrame(tmp);//获取视频的总帧数int frames = 0;/*-----------------代码1.1---------*//*frames =(int)cvGetCaptureProperty(            tmp,CV_CAP_PROP_FRAME_COUNT);*//*-----------------代码1.1end---------*//*-----------------代码1.2---------*/while(frame != NULL ){frame = cvQueryFrame(tmp);frames++;}cvReleaseCapture(&tmp);/*-----------------代码1.2end---------*/printf("总帧数 is %3d\n",frames);/*-----------------获取总帧数-----------*/g_capture = cvCreateFileCapture("E:\\狸窝转换结果\\oldfriends.avi");if(frames>0){cvCreateTrackbar("Position",//创建的名字"show",//窗口名字&g_slider_pos,//整数指针,它的值将反应滑块位置frames,//滑块位置的最大值onTrackbarSlider//每次滑块位置被改变的时候,被调用的指针);}int count = 0;while(1){frame = cvQueryFrame(g_capture);//返回视频文件的下一帧if(!frame){printf("NULL\n");break;}cvShowImage("show",frame);char c = cvWaitKey(33);if(c==27)//Esc按键{cvWaitKey(0);//break; }/*-----------------2、设置滚动条位置---------*//*-----------------代码2.1---------*///cvSetTrackbarPos("Position","show",frame_count);//通过单步调试,发现执行这一步时会调用到onTrackbarSlider()函数/*-----------------代码2.1end---------*//*-----------------设置滚动条位置-----------*/frame_count++;count++;}printf("累加值:frame_count is %3d,count is %3d\n",frame_count,count);cvReleaseCapture(&g_capture);cvDestroyWindow("show");return 0;}

上述代码中有几个函数值得深入研究

1、double cvGetCaptureProperty(CvCapture* capture, int property_id)//获取摄像头属性的函数

capture:源文件指针
property_id: 控制返回的属性,其中
CV_CAP_PROP_POS_MSEC - 影片目前位置,为毫秒数或者视频获取时间戳
CV_CAP_PROP_POS_FRAMES - 将被下一步解压/获取的帧索引,以0为起点
CV_CAP_PROP_POS_AVI_RATIO - 视频文件的相对位置(0 - 影片的开始,1 - 影片的结尾)
CV_CAP_PROP_FRAME_WIDTH - 视频流中的帧宽度
CV_CAP_PROP_FRAME_HEIGHT - 视频流中的帧高度
CV_CAP_PROP_FPS - 帧率
CV_CAP_PROP_FOURCC - 表示codec的四个字符
CV_CAP_PROP_FRAME_COUNT视频文件中帧的总数(本课时需要使用的属性)

注:1.有时调用函数cvGetCaptureProperty需要调用cvQueruFrame一次后才返回正确的值。这是软件存在的一个bug.
2.cvGetCaptureProperty函数实际是通过读取视频文件头信息返回数据,不是真正读取视频文件。因此不同格式视频文件转换成opencv所支持的avi格式后,使用该函数去读取时,会造成信息的不准确。(主要参考http://blog.sina.com.cn/s/blog_4b0020f301012dbz.html)


2、cvCreateTrackbar()创建滚动条

定义:
CV_EXTERN_C_FUNCPTR(void(*CvTrackbarCallback)(int pos));//回调函数的格式,返回值是void,参数是int。不能随意定义
int cvCreateTrackbar(const char* trackbar_name,//创建的名字
                     const char* window_name,//窗口名字
                     int* value,//整数指针,它的值将反应滑块位置
                     int count,//滑块位置的最大值
                     CvTrackbarCallback on_change//每次滑块位置被改变的时候,被调用的指针,回调函数
                     );

回调函数就是一个通过函数指针调用的函数。
如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。


3、int cvSetCaptureProperty( CvCapture* capture, int property_id, double value );//设置视频获取属性


4、cvSetTrackbarPos设置滚动条的值



根据cvGetCaptureProperty函数中提到的获取值不正确问题,我做了一个实验。

使用狸窝工具,将一个rmvb视频转成avi然后进行测试。测试数据如下:






对于这样的结果,我表示深深的疑惑。

首先图1图3和图2图4的对比可以看出,之前说到的cvGetCaptureProperty函数获取的值不正确这个问题是存在的。

其次,看到图3,为什么获取的总帧数是734,后来运行的时候帧数却可以达到879?对比了图1图2和图3图4之后,可以发现这个问题和cvSetTrackbarPos()、cvSetCaptureProperty()这两个函数有关。

是不是在使用函数的时候修改了什么东西,具体的还需要找到这两个函数的源代码看看才知道。

3 0