这个程序演示的是三个线程读取图像、处理图像、保存图像的例子,并把它们封装成一个类。第一个线程从视频读取图像放入队列imgs,第二个线程从imgs读取图像并处理后放入队列processedimgs,第三个线程保存processedimgs中的图像。为了限制内存占用,限制imgs的大小为15,processedimgs的大小为25。
project/lib.h
#ifndef _LIB_H_
#define _LIB_H_
#include <queue>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
class TriThread{
public:
TriThread(string vs, string os);
void Go();
private:
void mkdir();
void getImg();
void proImg();
void saveImg();
private:
string videoPath;
string outputPath;
queue<pair<Mat,bool>> imgs;
queue<pair<Mat,bool>> processedimgs;
double Fr=0;
int Fw=0;
int Fh=0;
int Fn=0;
};
#endif
project/lib.cc
#include <iostream>
#include <lib.h>
#include <thread>
#include <queue>
#include <opencv2/opencv.hpp>
#include <cmath>
#include <unistd.h>
using namespace std;
using namespace cv;
TriThread::TriThread(string vs, string os){
videoPath=vs;
outputPath=os;
mkdir();
}
//获取图像
void TriThread::getImg(){
int n=0;
bool flag=true;
VideoCapture inputVideo(videoPath);
//获取图像的帧率、宽高、帧数
Fw=inputVideo.get(CV_CAP_PROP_FRAME_WIDTH);
Fh=inputVideo.get(CV_CAP_PROP_FRAME_HEIGHT);
Fr=inputVideo.get(CV_CAP_PROP_FPS);
Fn=inputVideo.get(CV_CAP_PROP_FRAME_COUNT);
cout<<"This video contains "<<Fn<<" frames."<<endl;
Mat src;
while(flag){
if(imgs.size()<15){
inputVideo>>src;
if(src.empty())
flag=false;
n++;
imgs.push(make_pair(src, flag));
}
}
inputVideo.release();
cout<<"--Read frames: "<<n<<endl;
}
//处理图像
void TriThread::proImg(){
Mat src;
int x=0;
bool flag=true;
while(flag){
if(imgs.size()>0 && processedimgs.size()<25){
src=imgs.front().first;
if(imgs.front().second){
/*处理src*/flip(src,src,0);
imshow("1",src);
waitKey(1);/*处理src*/
}
else
flag=false;
x++;
imgs.pop();
processedimgs.push(make_pair(src, flag));
}
}
usleep(1000);
cout<<"--Processed frames: "<<x<<endl;
}
//保存图像
void TriThread::saveImg(){
Mat src;
stringstream ss;
string name;
int i=0;
while(true){
if(processedimgs.size()>0){
if(processedimgs.size()>0 && !processedimgs.front().second)//必须要有processedimgs.size()>0
break;
ss.str("");
ss.clear();
ss<<outputPath<<"/"<<setw(ceil(log10(Fn)))<<setfill('0')<<i++<<".jpg";
ss>>name;
src=processedimgs.front().first;
processedimgs.pop();
imwrite(name,src);
}
}
usleep(2000);
cout<<"--Saved frames: "<<i<<endl;
}
/*void TriThread::saveImg(){
int n=0;
while(Fn==0);
Mat src;
VideoWriter writer("video101.avi", CV_FOURCC('D','I','V','X'), Fr, Size(Fw, Fh), 1);
while(flag || processedimgs.size()>0){
if(processedimgs.size()>0){
src=processedimgs.front();
processedimgs.pop();
if(!src.empty()){
writer<<src;
n++;
}
}
}
writer.release();
cout<<"Saved "<<n<<" frames."<<endl;
}*/
//创建保存图像的文件夹
void TriThread::mkdir(){
if(access(outputPath.c_str(), F_OK)==-1){
char buffer[100];
sprintf(buffer,"mkdir %s",outputPath.data());
system(buffer);
}
}
void TriThread::Go(){
thread th1(&TriThread::getImg,this);
thread th2(&TriThread::proImg,this);
thread th3(&TriThread::saveImg,this);
th1.join();
th2.join();
th3.join();
}
project/main.cc
#include <iostream>
#include <lib.h>
using namespace std;
int main(int argc, char** argv){
TriThread tt("../m1.avi", "output");
tt.Go();
return 0;
}