加完水印后,生成了一个新的frame,没有替换。把每30帧输出为一个视频流
原本是利用opencv 把原视频的帧和新的帧合并写成一个视频mp4
void WatermarkAdder::proceedVideo(string outputFileName,string text) {
Mat pictw = setTextpic(300,300,text);
VideoWriter videoWriter(outputFileName,
VideoWriter::fourcc('m','p','4','v'),
fps/insertInterval*(insertInterval+1),
Size(width, height)
);
// cap.read(frame);
for (int i = 0; i < frameCount; i++) {
Mat frame;
cap.read(frame);
videoWriter.write(frame);
if (i == insertInterval)
{
cout << "proceeding frame" << i << endl;
Mat newFrame = proceedFrame(frame, pictw);
videoWriter.write(newFrame);
}
}
}
现在想要的结果是每读取到固定多少帧输出为一个视频流,就不用全部扫描整个视频文件
视频流读取与视频帧处理
如有帮助,望采纳
为了处理视频序列,需要读取每一Frame.用c++类封装VideoProcessor类视频读取处理的代码
class VideoProcessor{
private:
VideoCapture caputure; //The OpenCV Video capture object
void (*process)(Mat &,Mat &); // the callback function to be called for the
// processing of each frame
bool callIt;
string WindowNameInput; //Input display windnow name
string WindowNameOutput; //Output display window name
int delay;
long fnumber; // number of processed frames
long frameToStop; // stop at this frame number
bool stop;
public:
VideoProcessor() : callIt(true),delay(0),fnumber(0),stop(false),frameToStop(-1){}
void setFrameProcess(void (*process)(Mat &,Mat &)){
this->process = process;
}
bool setInput(string filename){
fnumber = 0;
caputure.release ();
return caputure.open (filename);
}
void displayInput(string wn){
WindowNameInput = wn;
namedWindow (WindowNameInput);
}
void displayOutput(string wn){
WindowNameOutput = wn;
namedWindow (WindowNameOutput);
}
void dontDisplay(){
destroyWindow (WindowNameInput);
destroyWindow (WindowNameOutput);
WindowNameInput.clear ();
WindowNameOutput.clear ();
}
void run(){
Mat frame;
Mat output;
if(!isOpened()) return;
stop = false;
while(!isStopped()){
if(!readNextFrame(frame)) break;
if(WindowNameInput.length ()!=0) imshow (WindowNameInput,frame);
if(callIt) process(frame,output);
else output = frame;
if(WindowNameOutput.length ()!=0) imshow (WindowNameOutput,output);
if(delay>=0&&waitKey (delay)>=0) waitKey(0);
if(frameToStop>=0&&getFrameNumber()==frameToStop) stopIt();
}
}
void stopIt(){
stop = true;
}
bool isStopped(){
return stop;
}
bool isOpened(){
return caputure.isOpened ();
}
void setDelay(int d){
delay = d;
}
bool readNextFrame(Mat &frame){
return caputure.read (frame);
}
void CallProcess(){
callIt = true;
}
void dontCallProcess(){
callIt = false;
}
void stopAtFrameNo(long frame){
frameToStop = frame;
}
long getFrameNumber(){
long fnumber = static_cast<long>(caputure.get ((CV_CAP_PROP_POS_FRAMES)));
return fnumber;
}
double getFrameRate(){
return caputure.get(CV_CAP_PROP_FPS);
}
};
处理视频帧主要是对于每个视频帧都应用一些处理函数。将自己的类中封装OpenCV的视频获取框架,同时可以指定每帧调用函数。作为一个视频帧处理函数,如:canny函数计算输入图像的Canny边缘。代码如下所示:
void canny(cv::Mat& img, cv::Mat& out) {
if (img.channels()==3)
cvtColor(img,out,CV_BGR2GRAY);
Canny(out,out,100,200);
threshold(out,out,128,255,cv::THRESH_BINARY_INV);
}
接着,定义一个video处理类,将与一个回调函数相关联。使用此类,将创建一个实例并指定输入的video文件,绑定回调函数,然后开始处理过程。代码如下所示:
VideoProcessor processor;
processor.setInput ("test.avi");
processor.displayInput ("Input Video");
processor.displayOutput ("Output Video");
processor.setDelay (2000./processor.getFrameRate ());
processor.setFrameProcess (canny );
processor.run ();
不知道能不能帮到你?
/**************************************************************************************************/
//视频播放及保存
void quick_show::video_demo(Mat &image) {
VideoCapture capture("E:\\ChenXY\\Opencv\\test\\Test\\testl.mp4");
int frame_width = capture.get(CAP_PROP_FRAME_WIDTH); //获取视频宽度;
int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT); //获取视频高度;
int count = capture.get(CAP_PROP_FRAME_COUNT); //获取视频总帧率;
double fps = capture.get(CAP_PROP_FPS); //获取视频帧率;
std::cout << frame_width << std::endl;
std::cout << frame_height << std::endl;
std::cout << count << std::endl;
std::cout << fps << std::endl;
VideoWriter writer("E:/ChenXY/testc.mp4", CV_FOURCC('M','J','P','G'), //参数:路径、格式、视频帧、大小
fps, Size(frame_width, frame_height), true); //保存视频capture.get(CAP_PROP_FOURCC)
Mat frame;
while (true) {
capture.read(frame); //视频帧读取到图片
//flip(frame, frame, 1);
if (frame.empty()) { //判断是否读取成功
break;
}
namedWindow("frame.put", WINDOW_FREERATIO); //视频展示
imshow("frame.put", frame);
//ColorSpace_Demo(frame);
writer.write(frame); //保存图片流为视频
int c = waitKey(8);
if (c == 27) { //按esc退出
break;
}
}
capture.release();
writer.release();
}
/**************************************************************************************************/
您可以通过改变循环的终止条件以及对每个循环迭代的处理方式来优化该代码。例如,您可以将循环更改为以下形式:
for (int i = 0; i < frameCount; i += insertInterval + 1) {
Mat frame;
cap.read(frame);
videoWriter.write(frame);
// 在每个固定的帧间隔内添加水印
if (i + insertInterval < frameCount) {
cout << "proceeding frame" << i << endl;
Mat newFrame = proceedFrame(frame, pictw);
videoWriter.write(newFrame);
}
}