homework1

来源:互联网 发布:理光mpc3300端口设置 编辑:程序博客网 时间:2024/06/05 01:16
  • 作业要求

    对输入的一个彩色视频与五张以上照片,用OpenCV实现以下功能或要求:

    1. 命令行格式: " xxx.exe 放视频与照片的文件夹路径" ,(例如MyMakeVideo.exe C:\input )【 假设该文件夹下面只有一个avi视频文件与若干jpg文件】

    2. 将输入的视频与照片处理成同样长宽后,合在一起生成一个视频;

    3. 这个新视频中,编程生成一个片头,然后按幻灯片形式播放这些输入照片,最后按视频原来速度播放输入的视频;

    4. 新视频中要在底部打上含自己学号与姓名等信息的字幕;

    5. 有能力的同学,可以编程实现镜头切换效果;

  • 代码

#include <iostream>

#include <string>

#include <vector>

#include <sstream>

#include <opencv2\opencv.hpp>

#include <windows.h>

#include <math.h>

usingnamespace std;

usingnamespace cv;

#define WINDOWN_NAME "Video Output"

#define INTERVAL (fps * 2.5)

  

VideoCapture capture;

VideoWriter writer;

int width =1280, height =728, fps =25;

RNG rng;

vector<string> vec;

  

//放文字

void putTextOnImg(Mat img)

{

string strHint ="w*d : ", str1, str2, str ="*";

stringstream ss;

ss.clear();

ss << width;

ss >> str1;

ss.clear();

ss << height;

ss >> str2;

putText(img, strHint + str1 + str + str2, Point(50,50), CV_FONT_HERSHEY_TRIPLEX,0.5, Scalar(255,255,255),1,8,false);

strHint ="fps : ";

ss.clear();

ss << fps;

ss >> str1;

putText(img, strHint + str1, Point(50,70), CV_FONT_HERSHEY_TRIPLEX,0.5, Scalar(255,255,255),1,8,false);

putText(img,"Number of Effects : 10", Point(50,90), CV_FONT_HERSHEY_TRIPLEX,0.5, Scalar(255,255,255),1,8,false);

putText(img,"video_output.avi can be played in player.", Point(50,110), CV_FONT_HERSHEY_TRIPLEX,0.5, Scalar(255,255,255),1,8,false);

putText(img,"Press Esc to Exit.", Point(50,130), CV_FONT_HERSHEY_TRIPLEX,0.5, Scalar(255,255,255),1,8,false);

putText(img,"11521062 ZhaoLei.", Point(width /2-150, height -50), FONT_HERSHEY_SCRIPT_COMPLEX,1, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)),2,8,false);

}

  

//图像切换效果

void effects(int id, Mat img)

{

Point2f center = Point2f(width /2, height /2);

Point2f point = Point2f(0,0);

Point2f srcTri[3]={ Point2f(0,0),Point2f(img.cols,0),Point2f(0, img.rows)}, dstTri[3];

Point tl, rb;

Mat tmpMat, dstImg, blackImg = Mat::zeros(Size(width, height), CV_8UC3);

int x, y;

cout <<"Writing Image";

for(int j =0; j <= INTERVAL; j++)

{

switch(id)

{

case0:

tmpMat = getRotationMatrix2D(center,0.0,1.2/ INTERVAL *(INTERVAL - j));//缩小

warpAffine(img, dstImg, tmpMat, img.size());

break;

case1:

//仿射变换

x = img.cols / INTERVAL *(INTERVAL - j);

y = img.rows / INTERVAL *(INTERVAL - j);

dstTri[0]= Point2f(width - x,0);

dstTri[1]= Point2f(x,0);

dstTri[2]= Point2f(width - x, img.rows - y);

tmpMat = getAffineTransform(srcTri, dstTri);

warpAffine(img, dstImg, tmpMat, img.size());

break;

case2:

x = img.cols / INTERVAL *(INTERVAL - j);

y =4* height * x *(width - x)/(width * width);

dstTri[0]= Point2f(width - x, y);

dstTri[1]= Point2f(x, y);

dstTri[2]= Point2f(x, img.rows - y);

tmpMat = getAffineTransform(srcTri, dstTri);

warpAffine(img, dstImg, tmpMat, img.size());

tmpMat = getRotationMatrix2D(point,0,1.2/ INTERVAL *(INTERVAL - j));

warpAffine(dstImg, dstImg, tmpMat, dstImg.size());

break;

case3:

tmpMat = getRotationMatrix2D(point,0,1.2/ INTERVAL * j);

warpAffine(img, dstImg, tmpMat, img.size());

break;

case4:

tmpMat = getRotationMatrix2D(center,360/ INTERVAL * j *2,1.2/ INTERVAL * j);//旋转加放大

warpAffine(img, dstImg, tmpMat, img.size());

break;

case5:

addWeighted(img,1.0/ INTERVAL *(INTERVAL - j), blackImg,1.0/ INTERVAL * j,0, dstImg);//图像混合

break;

case6:

tl = Point((width /2)/ INTERVAL *(INTERVAL - j),(height /2)/ INTERVAL *(INTERVAL - j));

rb = Point((width /2)/ INTERVAL * j +(width /2),(height /2)/ INTERVAL * j +(height /2));

tmpMat = img(Rect(tl.x, tl.y, rb.x - tl.x, rb.y - tl.y));//获取ROI区域

//ROI区域填充矩形

rectangle(tmpMat, Point(0,0), Point(tmpMat.cols, tmpMat.rows), Scalar(0,0,0), CV_FILLED);

dstImg = img;

break;

case7:

tl = Point((width /2)/ INTERVAL *(INTERVAL - j),(height /2)/ INTERVAL *(INTERVAL - j));

rb = Point((width /2)/ INTERVAL * j +(width /2),(height /2)/ INTERVAL * j +(height /2));

tmpMat = img(Rect(tl.x, tl.y, rb.x - tl.x, rb.y - tl.y));

circle(tmpMat, Point(tmpMat.cols /2, tmpMat.rows /2), tmpMat.cols /2, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), CV_FILLED);

dstImg = img;

break;

case8:

tmpMat = getRotationMatrix2D(point,0,1.2/ INTERVAL *(INTERVAL - j));

warpAffine(img, dstImg, tmpMat, img.size());

break;

case9:

tmpMat = getRotationMatrix2D(center,0.0,1.2/ INTERVAL * j);//放大

warpAffine(img, dstImg, tmpMat, img.size());

break;

}

putTextOnImg(dstImg);

writer.write(dstImg);

cout <<".";

}

cout <<"\n";

}

  

//绘制片头(八卦)

void drawStarter()

{

Mat dstImg = Mat::zeros(Size(width, height), CV_8UC3);

int r = height /2-80, a = width /2, b = height /2, x, y, ya, yb;

int b1 = height /2- r /2, b2 = height /2+ r /2;

cout <<"Writing Starter";

for(int j =0; j <= INTERVAL *4; j++)

{

//绘大圆

x =2* r /(INTERVAL *2)* j +80;

ya = sqrt(pow(r,2)- pow(x - a,2))+ b;

yb =-sqrt(pow(r,2)- pow(x - a,2))+ b;

circle(dstImg, Point(x, ya),2, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), CV_FILLED);

circle(dstImg, Point(x, yb),2, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), CV_FILLED);

//绘半圆上

y = height /2- r /(INTERVAL *3)* j;

x =-sqrt(pow(r /2,2)- pow(y - b1,2))+ a;

circle(dstImg, Point(x, y),2, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), CV_FILLED);

//绘半圆下

y = r /(INTERVAL *3)* j + height /2;

x = sqrt(pow(r /2,2)- pow(y - b2,2))+ a;

circle(dstImg, Point(x, y),2, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), CV_FILLED);

//绘小圆上

x = r /4/(INTERVAL *3)* j + width /2- r /8;

ya = sqrt(pow(r /8,2)- pow(x - a,2))+ b1;

yb =-sqrt(pow(r /8,2)- pow(x - a,2))+ b1;

circle(dstImg, Point(x, ya),2, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), CV_FILLED);

circle(dstImg, Point(x, yb),2, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), CV_FILLED);

//绘小圆下

x = r /4/(INTERVAL *3)* j + width /2- r /8;

ya = sqrt(pow(r /8,2)- pow(x - a,2))+ b2;

yb =-sqrt(pow(r /8,2)- pow(x - a,2))+ b2;

circle(dstImg, Point(x, ya),2, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), CV_FILLED);

circle(dstImg, Point(x, yb),2, Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255)), CV_FILLED);

putTextOnImg(dstImg);

writer.write(dstImg);

cout <<".";

}

cout <<"\n";

}

  

//wchar2str

string wchar2str(LPCWSTR wstr)

{

int len = WideCharToMultiByte(CP_ACP,0, wstr,-1,NULL,0,NULL,NULL);

if(len <=0)

return string("");

char* dst =newchar[len];

if(dst ==NULL)

return string("");

WideCharToMultiByte(CP_ACP,0, wstr,-1, dst, len,NULL,NULL);

dst[len -1]=0;

string str(dst);

delete[] dst;

return str;

}

  

//遍历文件夹下的文件

int listFiles(string str)

{

vec.clear();

WIN32_FIND_DATA findData;

HANDLE error;

//str2wstr

wstring widstr = wstring(str.begin(), str.end());

LPWSTR path =(LPWSTR)widstr.c_str();

  

error = FindFirstFile(path,&findData);

if(error == INVALID_HANDLE_VALUE)

{

cout <<"Failed to Find Files!"<<"\n";

return1;

}

do

{

string str = wchar2str(findData.cFileName);

vec.push_back(str);

//cout << str << "\n";

}while(FindNextFile(error,&findData));

return0;

}

  

int main(int argc,char*argv[])

{

if(argv[1]==NULL)

{

cout <<"Please run the program by command line.\ne.g.(Need to enter in the executable directory):\nhomework1.exe E:\\input"<<"\n\n";

system("pause");

return1;

}

  

bool selfExit =false;

Mat frame;

string strSplit ="\\", strType ="*.avi", fileName;

string path = argv[1]+ strSplit, fileOutput ="video_output.avi";

listFiles(path + strType);

for each (string file in vec)

{

if(file !="video_output.avi")

fileName = file;

}

capture.open(path + fileName);

if(!capture.isOpened())

{

cout <<"Failed to Open Video!";

return1;

}

width =(int)capture.get(CAP_PROP_FRAME_WIDTH);//1280

height =(int)capture.get(CAP_PROP_FRAME_HEIGHT);//720

cout <<"w*h:"<< width <<"*"<< height <<"\n";

fps =(int)capture.get(CV_CAP_PROP_FPS);//25fps

cout <<"fps:"<< fps <<"\n";

  

writer.open(path + fileOutput, CV_FOURCC('D','I','V','X'), fps, Size(width, height),true);

drawStarter();

int i =0;

strType ="*.jpg";

listFiles(path + strType);

for each (string fileName in vec)

{

cout << path + fileName <<"\n";

Mat img = imread(path + fileName);

Mat dst = Mat::zeros(Size(width, height), CV_8UC3);

resize(img, dst, dst.size());

effects(i++%10, dst);

}

cout <<"Writing Video Images";

while(1)

{

if(capture.read(frame))

{

putTextOnImg(frame);

writer.write(frame);

cout <<".";

}

else

break;

}

cout <<"\n";

  

namedWindow(WINDOWN_NAME);

capture.open(path + fileOutput);

while(1)

{

if(capture.read(frame))

imshow(WINDOWN_NAME, frame);

else

break;

//每帧间隔interval ms,且按esc退出

if(waitKey(1000/ fps)==27)

{

selfExit =true;

break;

}

}

cout <<"All are successful!\n";

if(!selfExit)

waitKey();

return0;

}

  • 效果

    media文件夹内的内容(其中video_output.avi为最后生成的视频文件):

    片头效果截图:

    切换效果截图(10种中的一个):

    原视频截图:

      

      

0 0