zoukankan      html  css  js  c++  java
  • 【OpenCV归纳】2 读写视频

    

    除了读入图片之外,读写视频也足够简单易学,下面来看看如何读写视频吧。


    播放硬盘中的视频:


    #include "highgui.h"
    
    int main(int argc,char** argv)
    {
        cvNamedWindow("Test2",CV_WINDOW_AUTOSIZE);
       CvCapture* capture=cvCreateFileCapture(argv[1]);
        IplImage* frame;
        while(1)
        {
            frame=cvQueryFrame(capture);
            if(!frame)
                break;
            cvShowImage("Test2",frame);
            char c= cvWaitKey(33);
            if(c==27)
                break;
        }
        cvReleaseCapture(&capture);
        cvDestoryWindow("Test2");
    }

    CvCapture结构包含了从摄像机或视频文件中读取帧所需的信息。根据视频来源,我们可以使用下面两个函数之一来初始化CvCapture结构。

    CvCapture* cvCreateFileCapture(const char* filename);

    CvCapture* cvCreateCameraCapture(int index);

    当时用cvCreateFileCapture()时,我们只需要将MPG或AVI视频文件名告诉该函数,OpenCV会打开并准备读取视频。如果打开成功,将返回一个指向已经初始化了的CvCapture结构的指针,随后便可以读入视频的帧。注意:在一些情况下(比如文件不存在)无法打开文件,函数会返回NULL指针;当压缩视频的编码未知时cvCreateFileCapture()也会返回NULL指针。函数cvCreateCameraCapture()的用法与cvCreateFileCapture()非常类似,但是没有处理视频编码解码的麻烦。



    读视频


    int cvGrabFrame(cvCapture* capture);

    IplImage* cvRetrieveFrame(CvCapture* capture)

    IplImage* cvQueryFrame(CvCapture* capture)


    方法一:使用cvGrabFrame(),该函数以CvCapture*指针为参数,返回一个整数,当读取帧成功时返回1,否则返回0.cvGrabFrame()将视频帧复制到一个用户看不见的空间里,这是因为获取的视频帧数据是未经过处理的,cvGrabFrame()被设计为用于快速将视频帧读入内存。在cvGrabFrame()以后,可以调用cvRetrieveFrame()来处理cvGrabFrame()读入的视频数据。这个函数会对读入帧做所有必须的处理(包括图像解码操作),并且返回要给IplImage*指针,该指针指向另一块内存空间(不要过分依赖于这个指针所指向的图像,因为cvGrabFrame()下一次调用时,指针所指向的空间会被新的图像覆盖)。实现如下:

    #include<highgui.h>
    
    int main()
    {
    	CvCapture* capture;
    	IplImage* frame;
    	capture = cvCaptureFromFile("D:\1.avi");           // 你应该选择自己硬盘avi视频的位置
    	cvNamedWindow("Test2_0");
    
    	while (true)
    	{
    		if (cvGrabFrame(capture))
    		{
    			frame = cvRetrieveFrame(capture);
    			cvShowImage("Test2_0", frame);
    			char c = cvWaitKey(33);
    			if (c == 27)
    				break;
    		}				
    	}
    	cvReleaseCapture(&capture);
    	cvDestroyWindow("Test2_0");
    }

    方法二:代码即为本文第一个实例。

    对于CvCapture结构还可以执行很多其他的操作,比如可以查询与设置视频的各种属性:

    double cvGetCaptureProperty
    (
        CvCapture* capture,
        int property_id,
    );
    
    int cvSetCaptureProperty
    (
        CvCapture* capture,
        int property_id,
        double value
    };

    cvGetCaptureProperty()可以接受的参数见下表。

    视频捕捉属性 数值
    CV_CAP_PROP_POS_MSEC 0
    CV_CAP_PROP_POS_FRAME 1
    CV_CAP_PROP_POS_AVI_RATIO 2
    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


    获得视频编码格式

    double f=cvGetCaptureProperty
    (
        capture,
        CV_CAP_PROP_FOURCC
    );
    
    char* fourcs=(char*) (&f);

    double f=cvGetCaptureProperty
    (
        capture,
        CV_CAP_PROP_FOURCC
    );
    
    char* fourcs=(char*) (&f);

    写视频:


    写视频就得创建一个CvVideoWriter结构,这是一个类似于CvCapture的视频写入结构。此结构与下面的函数一起使用。


    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
    );

    除了视频文件名称,还需要告诉视频写入结构视频编码结构,帧率以及每一帧的大小。还可以告诉OpenCV图像是否彩色(默认为彩色)。fourcc是将4个字符打包在一个整数,由于经常使用,OpenCV提供了一个宏CV_FOURCC(c0,c1,c2,c3)来实现这个打包操作。

    视频写入结构建好后,需要调用cvWriteFrame()函数,并且为cvWriteFrame()函数传入一个CvVideoWriter*指针和要给IplImage*指针来写入文件。

    写入完成后,为了关闭写入结构,必须调用CvReleaseVideoWriter()函数,如果平时不习惯释放不再使用的空间和结构,对这个结构千万别偷懒,因为不显示释放结构,视频文件可能会被损毁。


    HighGUI工具包还包括了一个经常使用的滚动条,滚动条可以使我们方便的从视频的一帧跳到另外一帧。我们通过调用cvCreateTrackbar()来创建一个滚动条,并且通过设置参数来确定滚动条所属的窗口。为了获得所需的功能,只需要提供了一个回掉函数。

    #include<cv.h>
    #include<highgui.h>
    
    int g_slider_position=0;
    CvCapture* g_capture =NULL;
    
    void onTrackbarSlide(int pos)
    {
        cvSetCaptureProperty
        (  g_capture,
           CV_CAP_PROP_POS_FRAME,
           pos
        );
    }
    
    int main(int argc,char** argv)
    {
        cvNamedWindow("Test2_1",CV_WINDOW_AUTOSIZE);;
        g_capture=cvCreateFileCapture(argv[1]);
        int frames=(int)cvGetCaptureProperty(g_capture,CV_CAP_PROP_FRAME_COUNT);
        if(frames!=0)
        {
             cvCreateTrackbar
             (
                  "Position",
                  "Test2_1",
                  &g_slider_position,
                   frames,
                   onTrackbarSlide
               );
         }
         IplImage* frame;
         // While loop (as in Test1) capture & show video
         // ... 
         // Release memory and destroy window
         ...
         Return (0);
    }
    

    除了这些之外还有一个很重要的函数,cvConvertImage(),其用于在常用的不同图像格式之间转换。文件格式在src与dst的图像文件中指出(该函数还允许使用比IplImage更通用的CvArr类型)。源图像必须是单个、3个或者4个通道,也可以是8位或浮点型类型像素格式。目标图像必须是8位的单通道或者3个通道。函数也可以将彩色图像转换为灰度图或者将单通道的灰度图转换为3个通道的灰度图(彩色)。最后,flags参数可以垂直旋转图像。因为偶尔摄像机图像格式与图像显示格式会反转,因此这是很有用的。设置这个参数可以在内存中彻底旋转图像。




  • 相关阅读:
    Springmvc全局异常处理
    SpringMVC异常处理一
    [GDB7] gdb 的学习
    《Python 第七章》更加抽象
    python问题:IndentationError:expected an indented block错误解决
    [C/C++] C++ 类的学习
    [GCC6] gcc 的学习
    [Python] 列表 list
    [python] 循环与轻量级 pass, del, eval
    《Python 第八章》异常
  • 原文地址:https://www.cnblogs.com/NoMasp/p/4357161.html
Copyright © 2011-2022 走看看