刚才随便写了下关于OpenCV中的关于对视频进行操作的几个小程序,其实**对视频的操作也是OpenCV的一个重要方面,视频可以看作是图像序列,每一帧都是一个单一的图片,采用循环处理每一帧的方式,也就可以对视频进行处理。**OpenCV中对视频的典型操作就是视频的读入、播放控制和写入。下面先介绍几个结构和函数。
(1)CvCapture结构
CvCapture结构就类似于IplImage结构,这个结构包含从摄像机或视频文件中读取帧所需的信息。
CvCapture* cvCreateFileCapture(const char* filename)
CvCapture* cvCreateCameraCapture(int index)
当使用cvCreateFileCapture()时,我们只需要将MPG或者是AVI视频文件名称传入参数,OpenCV就会打开视频并准备读取视频,打开成功的话将返回一个指向已经初始化的CvCapture结构的指针。而cvCreateCameraCapture()是用来处理OpenCV和摄像机的,在这个博文里不做介绍。
(2)读取视频cvQueryFrame()
int cvGrabFrame(CvCapture* capture);
IplImage* cvRetrieveFrame(CvCapture* capture);
IplImage* cvQueryFrame(CvCapture* capture);
创建一个有效的CvCapture结构之后,便可以开始开始读取视频。第一种方法就是使用cvGrabFrame()和 cvRetrieveFrame()函数进行组合,但是这种方法略微复杂点,在这里不做主要介绍。主要介绍第二种方法,比较简单,使用cvQueryFrame()函数。
(3)视频捕捉属性设置
我们在读取视频后,还可以对CvCapture结构执行很多其他的操作,尤其是属性的获取和设置。
double cvGetCaptureProperty(
CvCapture* capture,
int property_id
)
int cvSetCaptureProperty(
CvCapture* capture,
int property_id,
double value
)
关于视频捕捉属性(property_id)设置见如下表:
视频捕捉属性 数值
CV_CAP_PROP_POS_MSEC 0//指向视频当前位置,以毫秒为单位
CV_CAP_PROP_POS_FRAME 1//以帧为单位的当前位置
CV_CAP_PROP_POS_AVI_RATIO 2//介于0与1之间的数,表示位置
CV_CAP_PROP_FRAME_WIDTH 3//当前读取帧的宽度
CV_CAP_PROP_FRAME_HEIGHT 4//当前读取帧的高度
CV_CAP_PROP_FPS 5//对视频文件来说,它记录了视频录入时每秒钟的帧数
CV_CAP_PROP_FOURCC 6//四个字节组成,表示视频文件的压缩方法
CV_CAP_PROP_FRAME_COUNT 7//表示视频文件的总帧数
(4)写视频CvVideoWriter结构
CvVideoWriter结构类似于CvCapture结构,这个结构一般与cvWriteFrame()和cvReleaseVideoWriter()函数一起组合使用。
CvVideoWriter* cvCreateVideoWriter(
const char* filename,
int fourcc,
double fps,
CvSize frame_size,
int is_color=1
)
int cvWriteFrame(
CvVideoWriter* writer,
const IplImage* image
)
void cvReleaseVideoWriter(
CvVideoWriter** writer
)
示例程序如下:
//读入视频
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
int main( )
{
cvNamedWindow("Video", CV_WINDOW_AUTOSIZE);
CvCapture *capture = cvCreateFileCapture("1.mp4");
IplImage *frame = NULL;
while (1)
{
frame = cvQueryFrame(capture);
if (!frame) break;
cvShowImage("Video", frame);
char c = cvWaitKey(33);
if (c == 27)break;//27对应的是ESC
}
cvReleaseImage(&frame);
cvDestroyWindow("Video");
return 0;
}
//用进度条控制视频的播放
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
int g_slider_position = 0;
CvCapture *g_capture = NULL;
void onTrackbarSlider(int pos)
{
cvSetCaptureProperty(
g_capture,
CV_CAP_PROP_POS_FRAMES,
pos
);
}
int main()
{
cvNamedWindow("Video", CV_WINDOW_AUTOSIZE);
g_capture = cvCreateFileCapture("1.mp4");
int frames = (int)cvGetCaptureProperty(
g_capture,
CV_CAP_PROP_FRAME_COUNT
);
if (frames != 0)
{
cvCreateTrackbar(
"Position",
"Video",
&g_slider_position,
frames,
onTrackbarSlider
);
}
IplImage *frame = NULL;
while (1)
{
frame = cvQueryFrame(g_capture);
if (!frame)
break;
g_slider_position++;
cvShowImage("Video", frame);
char c = cvWaitKey(33);
if (c == 27)
break;
}
cvReleaseCapture(&g_capture);
cvDestroyWindow("Video");
return 0;
}
//写入视频
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace std;
int main()
{
cvNamedWindow("video", CV_WINDOW_AUTOSIZE);
CvCapture *capture = cvCreateFileCapture("1.mp4");
IplImage *frame = cvQueryFrame(capture);
double fps = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
int fourcc = cvGetCaptureProperty(capture, CV_CAP_PROP_FOURCC);
CvSize frame_size = cvSize(
(int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH),
(int)cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT)
);
CvVideoWriter *writer = cvCreateVideoWriter("2.avi", fourcc, fps, frame_size, 1);
IplImage *logPolar_frame = cvCreateImage(frame_size, IPL_DEPTH_8U, 3);
while ((frame = cvQueryFrame(capture)) != NULL)
{
cvLogPolar(frame, logPolar_frame, cvPoint2D32f(frame->width / 2, frame->height / 2), 40, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS);
cvWriteFrame(writer, logPolar_frame);
}
cvReleaseVideoWriter(&writer);
cvReleaseImage(&logPolar_frame);
cvReleaseCapture(&capture);
return 0;
}