版权声明:学无止境,好好学习 https://blog.csdn.net/m0_38116269/article/details/88886338
一、基础信息
版本:OpenCV 4.0.1
系统:Ubuntu 18.04 LTS
编译:CMake
参考:samples/cpp/tutorial_code/videoio/video-write/video-write.cpp
二.merge 和split操作的理解
目前通道的合并和读取不太明白,准备今天下午搞得明明白白,清清楚楚,扎扎实实!
先从图片做起,处理单张图片试一试。
已经学习到的小tips:
(1)一定要注意先保存,再make, 不然编译的还是没有保存之前的。
(2)读取文件的路径,一定要写成绝对路径而不是相对路径
(3)多加一些if判断语句,例如读取不到文件就输出一条语句并且返回,别总是等到机器报错就不好了。
编写了个测试代码,有助于理解通道的融合和分离。
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main(){
//注意,这里要放绝对路径。。。不然会出错。
Mat img = imread("/home/wwh/Documents/myproject/video/data/lena.jpg"); //
if(img.empty()){
cout<<"There is no this image or wrong directory!"<<endl;
return -1;
}
cout<<"the size of the image is: "
<<img.size()<<endl;
vector<Mat> sptimg;
split(img, sptimg); //通道分离
if(sptimg.empty()){
cout<<"wrong split!"<<endl;
return -1;
}
Mat merimg;
Size S = Size(512, 512);
sptimg[0] = Mat::zeros(S, sptimg[0].type());
//sptimg[2] = Mat::zeros(S, sptimg[2].type());
merge(sptimg, merimg);
//图片打印到屏幕上
namedWindow("lena", WINDOW_NORMAL);
imshow("lena", merimg);
waitKey(5000);
return 0;
}
通过打印分离后的通道size,可以发现分成了三个512512。而原始图像也是512512,这说明并不是矩阵的重组,而是融合!意会!
三.读取视频,截取一段写成新的视频
编写了个简单的程序,可以实现对原始视频的截取然后保存,比如,截取原始视频的第100帧到第200帧保存为一个新的视频。
下面是代码,
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
static void help(){
cout<<"wrong input number"<<endl;
cout<<"eg: ./video ../data/xx.avi"<<endl;
}
int main(int argc, char* argv[]){
if(argc != 2){
help();
return -1;
}
const string sourceVideo = argv[1];
VideoCapture capVideo(sourceVideo);
if(!capVideo.isOpened()){
cout<<"No this video os directory!"<<endl;
return -1;
}
int ex = static_cast<int>(capVideo.get(CAP_PROP_FOURCC));
Size S = Size((int)capVideo.get(CAP_PROP_FRAME_WIDTH),
(int)capVideo.get(CAP_PROP_FRAME_HEIGHT));
//打印输入视频的相关信息,高度,宽度,帧数
cout<<"the source vidio has width:"<<S.width
<<"height:"<<S.height;
cout<<" total frame is:"<<capVideo.get(CAP_PROP_FRAME_COUNT)<<endl;
//命名
string::size_type ptn = sourceVideo.find_last_of('.');
const string Name = sourceVideo.substr(0, ptn) + "_new.avi";
VideoWriter wriVideo;
wriVideo.open(Name, ex, capVideo.get(CAP_PROP_FPS), S, true);
if(!wriVideo.isOpened()){
cout<<"Can't create a new vidio!"<<endl;
return -1;
}
Mat src, wri;
int framNum = -1;
while(1){
capVideo >> src;
//准备写入原始视频的第100帧到第200帧到新视频中
if(framNum > 100 && framNum < 200){
wriVideo << src;
}
//要是读到底了,那就退出
if(src.empty()){
break;
}
++framNum;
}
cout<<"Finished"<<endl;
return 0;
}
下面准备稍微改一下,
(1)能够读取前后10帧,共20帧组成一个视频。
(2)修改路径,能够保存在自己想要的目录下面,成功。
(3)能够读取多个片段并保存,这个得想一想。
准备开干!
感觉自己功力不够深厚,目前还不能写多个视频,分段保存,准备继续深造,来日再战。
四、读取摄像头写入视频文件
又成功实现了一个读取摄像头,并将视频写入的文件,附上代码。这里注意,原来的demo是有错误,循环当中应该写视频流,我给加上了。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(){
VideoCapture cap;
cap.open(0);
if(!cap.isOpened()){
cout<< "Can't open camera!"<<endl;
return -1;
}
Mat src;
cap >> src;
int codec = VideoWriter::fourcc('M', 'J', 'P', 'G');
double fps = 25.0;
string filename = "../outvid/camvid.avi";
VideoWriter wriVideo;
wriVideo.open(filename, codec, fps, src.size(), true);
if(!wriVideo.isOpened()){
cout<<"Can't open the new avi"<<endl;
return -1;
}
while(1){
cap >> src;
if(src.empty()){
cout<<"Can't open the camera!"<<endl;
break;
}
wriVideo << src;
imshow("window", src);
if(waitKey(5)>0){
break;
}
if(src.empty()){
break;
}
}
cap.release();
destroyAllWindows();
return 0;
}