您的位置:首页 > 运维架构

opencv 保存视频VideoWrite

2015-12-06 18:43 323 查看
版权声明:本文为博主原创文章,未经博主允许不得转载。

尽早过来学习了一下opencv中如何写入视频,顿时发现Opencv太强大了 !!!!

你可能已经不满足于读取视频,还想要将你产生的一系列结果保存到一个新建的视频文件中。使用OpenCV中的
VideoWriter 类就可以简单的完成创建视频的工作。在接下来的教程中,我们将告诉你:

如何用OpenCV创建一个视频文件
用OpenCV能创建什么样的视频文件
如何释放视频文件当中的某个颜色通道

为了使例子简单,我就仅仅释放原始视频RGB通道中的一个,并把它放入新视频文件中。你可以使用命令行参数来控制程序的一些行为:

第一个参数指向你需要操作的视频文件。
第二个参数可以是如下的几个字母之一:R G B。用来指定你需要释放哪一个通道。
首先,你需要知道一个视频文件是什么样子的。每一个视频文件本质上都是一个容器,文件的扩展名只是表示容器格式(例如
avi ,
mov ,或者mkv )而不是视频和音频的压缩格式。容器里可能会有很多元素,例如视频流,音频流和一些字幕流等等。这些流的储存方式是由每一个流对应的编解码器(codec)决定的。通常来说,视频流很可能使用mp3
或 aac 格式来储存。而视频格式就更多些,通常是
XVID ,
DIVX ,
H264 或
LAGS (Lagarith Lossless Codec)等等。具体你能够使用的编码器种类可以在操作系统的编解码器列表里找到
如你所见,视频文件确实比图像文件要复杂很多。然而OpenCV只是个计算机视觉库而不是一个视频处理编码库。所以开发者们试图将这个部分尽可能地精简,结果就是OpenCV能够处理的视频只剩下avi 扩展名的了。另外一个限制就是你不能创建超过2GB的单个视频,还有就是每个文件里只能支持一个视频流,不能将音频流和字幕流等其他数据放在里面。尽管如此,任何系统支持的编解码器在这里应该都能工作。如果这些视频处理能力不够你使用的话,我想你应该去找一些专门处理视频的库例如FFMpeg
或者更多的编解码器例如 HuffYUV ,
CorePNG 和
LCL 。你可以先用OpenCV创建一个原始的视频流然后通过其他编解码器转换成其他格式并用VirtualDub 和
AviSynth 这样的软件去创建各种格式的视频文件

好了 上代码啦 :

[cpp]
view plaincopyprint?

int main()
{
const string source="e:\\kankan\\1.avi";
VideoCapture cap(source);

const bool askOutputType = true;
if(!cap.isOpened())
{
cout<<"could not open the video"<<endl; }

string ::size_type pAt=source.find_last_of('.');
const string NAME=source.substr(0,pAt)+'r'+".avi";
int ex=static_cast<int>(cap.get(CV_CAP_PROP_FOURCC));
char EXT[] = {ex & 0XFF , (ex & 0XFF00) >> 8,(ex & 0XFF0000) >> 16,(ex & 0XFF000000) >> 24, 0};

Size S=Size((int)cap.get(CV_CAP_PROP_FRAME_WIDTH),
(int)cap.get(CV_CAP_PROP_FRAME_HEIGHT) );
VideoWriter outputVideo; // Open the output
if (askOutputType)
outputVideo.open(NAME , ex=-1, cap.get(CV_CAP_PROP_FPS),S, true);
else
outputVideo.open(NAME , ex, cap.get(CV_CAP_PROP_FPS),S, true);

union { int v; char c[5];} uEx ;
uEx.v = ex; // From Int to char via union
uEx.c[4]='\0';

cout << "Input frame resolution: Width=" << S.width << " Height=" << S.height
<< " of nr#: " << cap.get(CV_CAP_PROP_FRAME_COUNT) << endl;
cout << "Input codec type: " << EXT << endl;

int channel=2;

Mat frame;
Mat res;
vector<Mat>spl;
while(true)
{
cap>>frame;
if(frame.empty())
{
cout<<"over"<<endl;
break;
}

split(frame,spl);
for(int i=0;i<3;++i)
{
if(i!=channel)
spl[i]=Mat::zeros(frame.size(),spl[0].type());
merge(spl,res);
imshow("r",res);
outputVideo << res;
}

}


waitKey(33);
return 0;
}

int main()
{
	const string source="e:\\kankan\\1.avi";
	VideoCapture  cap(source);
	
	const bool askOutputType = true;
	if(!cap.isOpened())
	{
		cout<<"could not open the video"<<endl;  }
		
	string ::size_type pAt=source.find_last_of('.');
	const string NAME=source.substr(0,pAt)+'r'+".avi";
	int ex=static_cast<int>(cap.get(CV_CAP_PROP_FOURCC));
	char EXT[] = {ex & 0XFF , (ex & 0XFF00) >> 8,(ex & 0XFF0000) >> 16,(ex & 0XFF000000) >> 24, 0};

	Size S=Size((int)cap.get(CV_CAP_PROP_FRAME_WIDTH), 
		(int)cap.get(CV_CAP_PROP_FRAME_HEIGHT) );
	 VideoWriter outputVideo;                                        // Open the output
    if (askOutputType)
            outputVideo.open(NAME  , ex=-1, cap.get(CV_CAP_PROP_FPS),S, true);  
    else
        outputVideo.open(NAME , ex, cap.get(CV_CAP_PROP_FPS),S, true);
	
	union { int v; char c[5];} uEx ;
    uEx.v = ex;                              // From Int to char via union
    uEx.c[4]='\0';

    cout << "Input frame resolution: Width=" << S.width << "  Height=" << S.height
        << " of nr#: " << cap.get(CV_CAP_PROP_FRAME_COUNT) << endl;
    cout << "Input codec type: " << EXT << endl;
	
	int channel=2;
	
	Mat frame;
		Mat res;
		vector<Mat>spl;
		while(true)
		{
			cap>>frame;
			if(frame.empty())
			{
				cout<<"over"<<endl;
				break;
			}
		
			split(frame,spl);
			for(int i=0;i<3;++i)
			{
				if(i!=channel)
					spl[i]=Mat::zeros(frame.size(),spl[0].type());
				  merge(spl,res);
				  imshow("r",res);
				  outputVideo << res;
			}
			
		}
		    
			
			waitKey(33);
		return 0;
}




我选择的是R通道。效果图如下:



部分代码:



[cpp]
view plaincopyprint?

split(src, spl); // 分离三个通道
for( int i =0; i < 3; ++i)
if (i != channel)
spl[i] = Mat::zeros(S, spl[0].type()); //创建相同大小的黑色图像
merge(spl, res); //重新合并

split(src, spl);                 // 分离三个通道
for( int i =0; i < 3; ++i)
   if (i != channel)
      spl[i] = Mat::zeros(S, spl[0].type());         //创建相同大小的黑色图像
merge(spl, res);             //重新合并
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: