• OPENCV读取AVI视频失败 视频帧提取以及图片合成视频


    前一阵子,实验室老师个了个小命题,就是如何提取一段AVI视频中的图片,或者说视频帧的提取。虽然是第一次接触OPENCV,可是做起来也是不难的,自己的代码就不拿出来了,写的很乱,网上的这个代码比较不错,为了说明我们的主题,姑且拿这段代码做个试验。

    #include <stdlib.h>
    #include <stdio.h>
    #include <math.h>
    #include <cv.h>
    #include <highgui.h>
    #define NUM_FRAME 5591 //只处理前300帧,根据视频帧数可修改
    
    
    int frameH;
    int frameW; 
    int fps;
    int numFrames;
    
    void Video_to_image(char* filename)
    {
    	printf("------------- video to image ... ----------------\n");
    	//初始化一个视频文件捕捉器
    	CvCapture* capture = cvCaptureFromAVI(filename);
    	//获取视频信息
    	cvQueryFrame(capture);
    	frameH    = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT);
    	frameW    = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH);
    	fps       = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
    	numFrames = (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FRAME_COUNT);
    	printf("\tvideo height : %d\n\tvideo width : %d\n\tfps : %d\n\tframe numbers : %d\n", frameH, frameW, fps, numFrames);
    	//定义和初始化变量
    	int i = 0;
    	IplImage* img = 0;
    	char image_name[13];
    	
    	cvNamedWindow( "mainWin", CV_WINDOW_AUTOSIZE );
    	//读取和显示
    	while(1) 
    	{
    		
    		img = cvQueryFrame(capture); //获取一帧图片
    		cvShowImage( "mainWin", img ); //将其显示
    		char key = cvWaitKey(20);
    		
    		sprintf(image_name, "%s%d%s", "image", ++i, ".bmp");//保存的图片名
    		
    		cvSaveImage( image_name, img);   //保存一帧图片
    		
    		if(i >=numFrames || i >= NUM_FRAME ) break;
    
    	}
    	cvReleaseCapture(&capture);
    	cvDestroyWindow("mainWin");
    }
    void Image_to_video()
    {
    	int i = 0;
    	IplImage* img = 0;
    	char image_name[13];
    	printf("------------- image to video ... ----------------\n");
    	//初始化视频编写器,参数根据实际视频文件修改
    	CvVideoWriter *writer = 0;
    	int isColor = 1;
    
    	writer=cvCreateVideoWriter("out.avi",CV_FOURCC('X','V','I','D'),fps,cvSize(frameW,frameH),isColor);
    	printf("\tvideo height : %d\n\tvideo width : %d\n\tfps : %d\n", frameH, frameW, fps);
    	//创建窗口
    	cvNamedWindow( "mainWin", CV_WINDOW_AUTOSIZE );
    	while(i<NUM_FRAME)
    	{
    		sprintf(image_name, "%s%d%s", "image", ++i, ".bmp");
    		img = cvLoadImage(image_name);
    		if(!img)
    		{
    			printf("Could not load image file...\n");
    			exit(0);
    		}
    		cvShowImage("mainWin", img);
    		char key = cvWaitKey(20);
    		cvWriteFrame(writer, img);
    	}
    	cvReleaseVideoWriter(&writer);
    	cvDestroyWindow("mainWin");
    }
    
    int main(int argc, char *argv[])
    {
    	char filename[23] = "F:\\1_Xvid.avi";
    	Video_to_image(filename); //视频转图片
    	Image_to_video();    //图片转视频
    	return 0;
    }
    

      配置好OPENCV环境(WIN7 + VS2010)之后,这段代码是可以运行的,可是,实验室师兄师姐们的主流实用VC6开发的,所以老师让我把代码在VC6下调试出来。

    结果配置好VC6之后,一运行出现这个错误:Null pointer in function cvGetMat

    首先找资料是怎么回事,有的人说是内存不足之类的原因,建议在循环体里面释放窗体资源,我照做了,可是还是不行。

    郁闷了老半天,还是没有结果。。。。。

    后来我发现一个细节,就是说,视频的信息压根就没有读进来,可以看看控制台。

    找到原因之后,后来就相对好办了,其实也花了很长时间去做。

    网上很多人说是解码器的问题,建议安装K-Lite_Codec_Pack_3.9.5Full,我也试了,在实验室蛋疼的网速之下,苦苦等待,安装,结果不知道为什么还是不行,。

    最后阶段,一个偶然的机会,我看到这篇文章http://hqs2892805.blog.163.com/blog/static/379968312010722915630/

    结果按照这篇文章这么做,就实现了。。。

    如果AVI文件打不开,请下载VIRTUALDUB图像处理软件,然后把AVI文件用XVID编码,编码后的文件不会太大。我自己用摄像头拍摄的AVI有5兆,编码后只有不到2兆,而且能够用VC打开。

    http://www.xvidmovies.com/codec/    可以从这个网站下载xvid解编码器

    方法:file——open video file 

               video——compression——选择XVIDMPEG CODEC

    哈哈,庆祝一下

  • 相关阅读:
    计算机最小单位
    api接口调用
    STM32SystemInit函数
    关于 Verilog 的 TimeScale
    破获ARM64位CPU下linux crash要案之神技能:手动恢复函数调用栈
    芯片后仿
    破获ARM64位CPU下linux crash要案之神技能:手动恢复函数调用栈
    HardFault定位方法和步骤
    BSP和SDK的区别
    armCPSR寄存器
  • 原文地址:https://www.cnblogs.com/xubenben/p/2797689.html
Copyright © 2020-2023  润新知