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种中的一个):
原视频截图:
- Homework1
- homework1
- homework1
- homework1
- homework1
- 密码学 homework1
- Homework1-15
- 补充homework1
- C homework1
- data science cs109 homework1
- CSIT571: Cryptography and Security Homework1
- CSIT 561 Computer Networks: An Internet Perspective Homework1
- Paradigms Homework1 一个超小型二元一次方程组计算器
- UC Berkeley CS 61B 2014 Spring Homework1
- tableView的一些细节
- 对称加密和分组加密中的四种模式(ECB、CBC、CFB、OFB)
- list_entry()
- tcpdump 两个通信进程在同一台机子
- CC2538之TinyOS例程实验:1-blink nesC语法
- homework1
- windows终止处理程序( __try __finally) 简单解析
- CSS2.1SPEC:视觉格式化模型之width属性详解(下)
- speex编解码在android上实现
- win7 64位下VS2010和opencv 2.4.11的配置
- Spring MVC 3中各个jar包的作用
- mysql-锁
- 关于有偿提供拼图响应式后台的通知
- UISegmentedControl详解