现在的位置: 首页 > 综合 > 正文

《学习OpenCV》第二章(1)

2017年10月14日 ⁄ 综合 ⁄ 共 4770字 ⁄ 字号 评论关闭

初试牛刀——显示图像

这一节接触了以下内容:

头文件“highgui.h”,此模块主要服务于图像和视频的输入/输出(在第一章已经学习过);

IplImage,图像文件的数据结构体;

IplImage* cvLoadImage( const char* filename, int flags=CV_LOAD_IMAGE_COLOR ),将图像文件加载进内存,它可以读取大部分格式类型的图像文件;

int cvNamedWindow( const char* name, int flags=CV_WINDOW_AUTOSIZE ),创建图像窗口,第一个参数作为与其他函数交互的索引;

void cvShowImage( const char* name, const CvArr* image ),把img图像显示在name的窗口中;

cvWaitKey(0),参数为0或负数时,等待用户触发行为,参数为正整数时,则为所指的毫秒数,时间一到就继续执行下去,不等待用户行为;

                         返回值:被按键的值,如果超过指定时间则返回-1。

                          如果程序想响应某个按键可利用if(cvWaitKey(1)==Keyvalue);——(第二小节会接触到

cvReleaseImage(&img),释放img所占据的内存,显示图像的窗口图像不会消失;

cvDestroyWindow("name"),销毁name窗口,同时释放为副本图像所开辟的内存,图像窗口消失;

程序编写:

编程环境:windows xp系统; opencv 1.0; VC++6.0;

程序说明:

此程序实现了opencv图片的加载和现实;

加入头文件:

#include <highgui.h>

主要程序代码:

	IplImage* img = cvLoadImage("./image/3.jpg");	//将图像文件加载进内存
	if (!img)	//检测文件是否成功读入
	{
		AfxMessageBox("图像文件不存在!");
		return TRUE;
	}
	cvNamedWindow("lovely", CV_WINDOW_AUTOSIZE);	//创建图像窗口,第一个参数作为与其他函数交互的索引
	cvShowImage("lovely", img);	//把img图像显示在lovely的窗口中
	cvWaitKey(0);	//等待用户触发行为
	cvReleaseImage(&img);	//释放img所占据的内存,“lovely”窗口图像不会消失
	cvDestroyWindow("lovely");	//销毁lovely窗口,同时释放为img的一个副本图像所开辟的内存,图像消失

运行成功界面:

程序源代码下载

编程过程遇到的问题:

编译错误:缺少lib文件所导致的编译错误

注意opencv的VC++6.0的配置,安装配置参照官网文档:VC6下安装与配置OpenCV1.0

第二个程序——播放AVI视频


这一节接触了以下内容:

CvCapture:可以理解为抽象视频接口结构体,它包括了所有关于读入AVI文件的信息;

CvCapture* cvCreateFileCapture( const char* filename ):给指定文件中的视频流分配和初始化CvCapture结构。当分配的结构不再使用的时候,它应该使用           cvReleaseCapture函数释放掉;

IplImage* cvQueryFrame( CvCapture* capture ):从摄像头或者文件中抓取一帧,然后解压并返回这一帧。这个函数仅仅是函数cvGrabFrame和函数cvRetrieveFrame在一起调用的组合。返回的图像不可以被用户释放或者修改。抓取后,capture被指向下一帧,可用cvSetCaptureProperty调整capture到合适的帧;

void cvReleaseCapture( CvCapture** capture ):释放由函数cvCreateFileCapture或者cvCreateCameraCapture分配的CvCapture结构,注:若从capture中使用cvQueryFrame获取图像指针,在releaseCapture的时候同时函数释放图像指针,用户不用再自己释放;

程序编写:

编程环境:windows xp系统; opencv 1.0; VC++6.0;

程序说明:

此程序实现了AVI视频文件的加载和播放功能;

加入头文件:

#include <highgui.h>

主要程序代码:

	cvNamedWindow("lovely", CV_WINDOW_AUTOSIZE);
	CvCapture* capture = cvCreateFileCapture("./avi/Lucky.avi");
	if (!capture)
	{
		AfxMessageBox("无法读入视频文件!");
		return TRUE;
	}
	IplImage* frame;
	while(1)
	{
		frame = cvQueryFrame(capture);
		if (!frame) break;
		cvShowImage("lovely", frame);
		char c = cvWaitKey(33);
		if (c == 27) break;  //等待ESC键
	}
	cvReleaseCapture(&capture);
	cvDestroyWindow("lovely");

运行成功界面:

程序源代码下载

编程过程遇到的问题:

加载AVI视频失败:

原因很简单,肯定是视频格式有问题,AVI文件它有不同的编码方式,有些编码方式opencv是不支持的。

OpenCV支持的AVI如下:(我也看不懂下面说的什么意思,还是用暴风直接转吧!)

Container

FourCC

Name

Description

AVI

'DIB '

RGB(A)

Uncompressed RGB, 24 or 32 bit

AVI

'I420'

RAW I420

Uncompressed YUV, 4:2:0 chroma subsampled

AVI

'IYUV'

RAW I420

identical to I420

本程序使用的是暴风影音转码软件,对于AVI,它共有两种编码方式:opencv不支持MPEG4格式,请选用XVID编码格式;


视频播放控制

这一节接触了以下内容:
double cvGetCaptureProperty( CvCapture* capture, int property_id ):获得摄像头或者视频文件的指定属性。

译者注:有时候这个函数在cvQueryFrame被调用一次后,再调用cvGetCaptureProperty才会返回正确的数值。这是一个bug,建议在调用此函数前先调用cvQueryFrame。

int cvSetCaptureProperty( CvCapture* capture, int property_id, double value ):设置指定视频获取的属性。目前这个函数对视频文件只支持: CV_CAP_PROP_POS_MSEC, CV_CAP_PROP_POS_FRAMES, CV_CAP_PROP_POS_AVI_RATIO

int cvCreateTrackbar( const char* trackbar_name, const char* window_name,
                      int* value, int count, CvTrackbarCallback on_change ):函数cvCreateTrackbar用指定的名字和范围来创建trackbar(滑块或者范围控制),指定与trackbar位置同步的变量,并且指定当trackbar位置被改变的时候调用的回调函数。被创建的trackbar显示在指定窗口的顶端。

void cvSetTrackbarPos( const char* trackbar_name, const char* window_name, int pos ):设置指定trackbar的位置。


程序编写:

编程环境:windows xp系统; opencv 1.0; VC++6.0;

程序说明:

此程序实现了avi视频的播放和控制,书上的代码和说明只实现了手动移动滚动条来调节视频播放位置,本文程序代码已经实现了滚动条随着视频播放自动移动的功能。

滚动条自动移动的原理是,在循环体里面,每循环一次就添加一个帧,每添加一个帧,全局变量slider_position就自加一,它代表的是滚动条的位置向前移动一步,然后利用滚动条位置设置函数cvSetTrackbarPos设置滚动滑块的位置。当然,当人为手动时,要记得同时改写slider_position的值,以使它处于最新值状态。

本程序的opencv参考函数列表如下:

加入头文件:

<span style="font-size:16px;">#include <cv.h>
#include <highgui.h></span>

主要程序代码:

<span style="font-size:16px;">//回调函数
void OnTrackbarSlide(int pos)
{
	cvSetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES, pos);	//设置视频获取属性 
	slider_position = pos;	//设置滚动条位置状态值,为实时滚动服务
}</span>

	cvNamedWindow("lovely", CV_WINDOW_AUTOSIZE);	//创建窗口
	capture = cvCreateFileCapture("./avi/Lucky.avi");	//获取视频
	if (!capture)
	{
		AfxMessageBox("无法读入视频文件!");
		return TRUE;
	}

	//获得视频获取结构的属性,CV_CAP_PROP_FRAME_COUNT - 视频文件中帧的总数
	int frames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
	if (frames != 0)
	{
		//创建滚动条并将它添加到指定的窗口
		cvCreateTrackbar("Position", "lovely", &slider_position, frames, OnTrackbarSlide);
	}
	IplImage* frame;
	while(1)
	{		
		frame = cvQueryFrame(capture);	//获取视频帧
		if (!frame) break;
		cvShowImage("lovely", frame);	//显示视频帧
		char c = cvWaitKey(33);
		if (c == 27) break;	//等待ESC推出按键

		slider_position++;
		cvSetTrackbarPos("Position", "lovely", slider_position);	//设置滚动条位置
	}
	cvReleaseCapture(&capture);	//释放资源
	cvDestroyWindow("lovely");	//销毁窗口

运行成功界面:

程序源代码下载

编程过程遇到的问题:

当把回调函数void OnTrackbarSlide(int pos)作为类成员定义时,会出现调用错误cvCreateTrackbar("Position", "lovely", &slider_position, frames, OnTrackbarSlide),错误信息如下:cannot convert parameter 5 from 'void (int)' to 'void (__cdecl *)(int)';

解决方式,把OnTrackbarSlide(int pos)声明为全局变量,这个不知是否跟回调函数的性质有关(待调研)。

抱歉!评论已关闭.