//把两个视频合成一个视频,播放合成之后的视频,效果就是同一个窗口的左右两边同时播放两个视频
// successfully !!
#include"stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
// 获取视频 capture 的第 pos 帧的图片
IplImage* getFrameFromVideo(CvCapture* capture, int pos)
{
IplImage *frame = NULL;
cvSetCaptureProperty(capture, CV_CAP_PROP_POS_FRAMES, pos);
printf("pos: %d \t",pos);
//获取一帧图片
frame = cvQueryFrame(capture);
if (!frame) return NULL;
else return frame;
}
//把两个视频合成一个视频
void combine_two_videos_into_one()
{
IplImage *newFrame = NULL;
IplImage *frame1 = NULL;
IplImage *frame2 = NULL;
// 用cvCaptureFromAVI()跟cvCaptureFromFile()、cvCreateFileCapture()都是一样的作用
CvCapture * pCapture1 = cvCaptureFromAVI(".\\video1.avi"); //输入第一个视频地址
CvCapture * pCapture2 = cvCaptureFromAVI(".\\video2.avi"); //输入第二个视频地址
CvRect rect;
CvVideoWriter *pWriter = NULL;
// cvGetCaptureProperty(Capture* cap,int property_index)获取视频文件的一些属性
// 获取视频的帧总数目
int frameNo1 = (int)cvGetCaptureProperty(pCapture1, CV_CAP_PROP_FRAME_COUNT);
int frameNo2 = (int)cvGetCaptureProperty(pCapture2, CV_CAP_PROP_FRAME_COUNT);
if (frameNo1 != frameNo2)
printf("video length 1 != video length 2\n");
else
printf("Total frame numbers: %d\n", frameNo1);
// 获取帧宽
int frameWidth1 = (int)cvGetCaptureProperty(pCapture1, CV_CAP_PROP_FRAME_WIDTH);
int frameWidth2 = (int)cvGetCaptureProperty(pCapture2, CV_CAP_PROP_FRAME_WIDTH);
if (frameWidth1 != frameWidth2)
printf("video width 1 != video width 2\n");
else
printf("frame width: %d\n", frameWidth1);
// 获取帧高
int frameHeight1 = (int)cvGetCaptureProperty(pCapture1, CV_CAP_PROP_FRAME_HEIGHT);
int frameHeight2 = (int)cvGetCaptureProperty(pCapture2, CV_CAP_PROP_FRAME_HEIGHT);
if (frameHeight1 != frameHeight2)
printf("video height 1 != video height 2\n");
else
printf("frame height: %d\n", frameHeight1);
// 获取帧率
int fps1 = (int)cvGetCaptureProperty(pCapture1, CV_CAP_PROP_FPS);
int fps2 = (int)cvGetCaptureProperty(pCapture2, CV_CAP_PROP_FPS);
if (fps1 != fps2)
printf("video fps 1 != video fps 2\n");
else
printf("frame fps: %d\n", fps1);
int initFlag = 0;
int counter = 0;
/*
在VR系统中,双目立体视觉起了很大作用。用户的两只眼睛看到的不同图像是分别产生的,显示在不同的显示器上。
有的系统采用单个显示器,但用户带上特殊的眼镜后, 一只眼睛只能看到奇数帧图像,另一只眼睛只能看到偶数帧图像,
奇、偶帧之间的不同也就是视差就产生了立体感。
*/
// 可以通过控制 counter 的值,让视频差帧播放、快进播放
while ((frame1 = getFrameFromVideo(pCapture1,3*counter)) != NULL && (frame2 = getFrameFromVideo(pCapture2,3*counter+1)) != NULL)
{
printf("counter : %d\n", counter++);
if (initFlag == 0)
{
//IplImage* cvCreateImage(CvSize size, int depth, int channels)
newFrame = cvCreateImage(cvSize(frame1->width * 2, frame1->height), frame1->depth, frame1->nChannels);
// 输入存放合成后的视频的地址
pWriter = cvCreateVideoWriter(".\\videoCombine.avi", CV_FOURCC('X', 'V', 'I', 'D'), fps1, cvSize(frame1->width * 2, frame1->height), 1);
initFlag = 1;
}
rect.x = 0;
rect.y = 0;
rect.height = frameHeight1;
rect.width = frameWidth1;
//利用ROI实现视频拼接
cvSetImageROI(newFrame, rect);
cvCopy(frame1, newFrame);
cvResetImageROI(newFrame);
rect.x = frameWidth1;
rect.y = 0;
rect.height = frameHeight1;
rect.width = frameWidth1;
cvSetImageROI(newFrame, rect);
//cvCopyImage(frame2, newFrame);
/*
如果设定了ROI等参数的时候,cvCopy只是复制被设定的区域,复制到一个和所设定参数相吻合的新的IplImage中
cvCopy的原型是:
void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL );
在使用这个函数之前,你必须用cvCreateImage()一类的函数先开一段内存,然后传递给dst。cvCopy会把src中的数据复制到dst的内存中。
*/
cvCopy(frame2, newFrame);
cvResetImageROI(newFrame);
cvWriteFrame(pWriter, newFrame);
cvShowImage("合成的视频", newFrame);
char c = cvWaitKey(33);
if (c == 27) break;
}
cvReleaseImage(&frame1);
cvReleaseImage(&frame2);
cvReleaseImage(&newFrame);
cvReleaseVideoWriter(&pWriter);
}
int main(int argc, char *argv[])
{
combine_two_videos_into_one();
return 0;
}