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然后进行测试。测试数据如下:

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

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

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

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

时间: 2024-10-25 10:09:56

opencv视频学习第五课(视频播放控制)笔记整理的相关文章

OpenGL教程翻译 第十五课 相机控制(二)

OpenGL教程翻译 第十五课 相机控制(二) 原文地址:http://ogldev.atspace.co.uk/(源码请从原文主页下载) Background 在这一节中我们将使用鼠标来控制相机的方向,从而得我们的相机控制更加完善.相机有不同的自由程度,这与其设计有关.在本教程中我们将要实现的是与第一人称游戏中相似的相机控制(如枪战类游戏).这意味着我们将可以使相机完成360度的旋转(绕着Y轴),这与我们的头部向左转向右转.身体转一整圈类似.除此之外我们也能使相机向上或者向下倾斜以获得更好的向

Web前端学习-第五课JavaScript篇

Q9:什么是跨域?什么是JSON?什么是JSONP?解决跨域问题有哪些方法?请结合代码和文字说明. 跨域:因为JavaScript同源策略(一段脚本只能读取来自同一来源的窗口和文档的属性,同一来源指主机名,协议和端口号的组合)的限制,a.com域名下的js无法操作b.com域名下的对象,只要是协议,域名,端口有任何一个不同都被当做是不同的域: Json(JavaScript Object Notation):一种轻量级的数据交换格式.基于ECMAScript的一个子集.采用完全独立于语言的文本格

性能测试学习 第五课

1.根据接口文档写脚本,函数(web_custom_request),完成get,post请求(注册,登录) Action(){    lr_save_string("192.168.42.131:8080","IP");            web_reg_save_param_ex(        "ParamName=register_code",        "LB=\"code\":",   

英语学习第五课总结

1.logic 逻辑,logical 逻辑的(音译词) 2.urban 城市的 urba+n = 谐音“欧巴+嗯~” = 城里人 3.suburban 郊区的,suburb 郊区 subway 地下铁,前缀sub- = 下 4.rural  = 谐音“卤肉” = 乡下的 5.Engine 引擎(音译词) Motor 马达(音译词) 6.camel 骆驼 camel = 谐音“楷模” = 骆驼 7.System 系统(音译词);身体 8.shock 休克(音译词):使震惊 9.scan 细看(谐音

javascript学习第五课this、call、apply

this 对象是在运行中基于函数的执行环境绑定的,在全局函数中,this等于window,而当函数被 作为某个对象的方法调用时,this等于那个对象 也就是说this关键字就是指代调用者. call.apply示例: 1.简单用法:绑定一些函数,用于传递参数.调用 2.用于扩展用于函数运行的作用域: js没有块级作用域的概念: 模拟高级语言实现块级作用域的功能示例: 通过运用匿名函数自执行实现: 闭包: 闭包示例:

Web前端学习-第五课HTML篇

Q12:HTML5有哪些新颖? 1.用于绘画的canvas元素: 2.用于媒介回放的video和audio元素: 3.对本地离线存储的更好的支持: 4.新的特殊内容元素,比如article,footer,header,nav,section: 5.新的表单控件,比如calender,date,time,Email,URL,search: 6.新特性基于HTML,css,DOM,以及JavaScript: 7.减少对外部插件的需求: 8.更优秀的错误处理: 9.更多取代脚本的标记: 10.HTML

【ios开发学习 - 第五课】UITableView使用

在开发iphone的应用时基本上都要用到UITableView,这里讲解一下UITableView的使用方法及代理的调用情况 - (void)viewDidLoad { [super viewDidLoad]; //初始化数据 NSArray *array1_=@[@"张铁林",@"张国立",@"张国荣",@"张艺谋",@"张惠妹"]; NSArray *array2_=@[@"李小龙"

Asp.net MVC4高级编程学习笔记-模型学习第五课MVC表单和HTML辅助方法20171101

MVC表单和HTML辅助方法 一.表单的使用. 表单中的action与method特性.Action表示表单要提交往那里,因此这里就有一个URL.这个URL可以是相对或绝对地址.表单默认的method属性值是get,如果看到表单没有写method属性那就是表示method是get方式提交.另外一种就是post方式. 当使用HTTP Get请求时,浏览器会提取表单中元素的name特性值及相应的value特性值放到查询字符串中.如:http://localhost?search?id=1 如果不想把

python学习第五天流程控制分支if和循环while

所有的逻辑结构围绕分支和循环进行,比如登陆注册,支付成功与否等等,下面讲述分支if用法和while用法 if age>30: print("www.96net.com.cn") else print("www.dc3688.com") if score>90: print("good") elif score>70 and score<90: print("g") else print("fa