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

这次是学习怎么创建一个控制台的滚动条,并且使用它控制视频的播放。为了测试一些东西,改编了视频教程中的代码。
#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然后进行测试。测试数据如下:

opencv视频学习第五课(视频播放控制)笔记整理_第1张图片opencv视频学习第五课(视频播放控制)笔记整理_第2张图片


opencv视频学习第五课(视频播放控制)笔记整理_第3张图片opencv视频学习第五课(视频播放控制)笔记整理_第4张图片


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

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

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

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

你可能感兴趣的:(opencv,MFC学习,c语言,程序)