C++ 将视频帧循环输出为视频流

问题遇到的现象和发生背景

加完水印后,生成了一个新的frame,没有替换。把每30帧输出为一个视频流

遇到的现象和发生背景,请写出第一个错误信息

原本是利用opencv 把原视频的帧和新的帧合并写成一个视频mp4

用代码块功能插入代码,请勿粘贴截图。 不用代码块回答率下降 50%
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);
            }
    }
}

运行结果及详细报错内容
我的解答思路和尝试过的方法,不写自己思路的,回答率下降 60%

现在想要的结果是每读取到固定多少帧输出为一个视频流,就不用全部扫描整个视频文件

我想要达到的结果,如果你需要快速回答,请尝试 “付费悬赏”

视频流读取与视频帧处理
如有帮助,望采纳

为了处理视频序列,需要读取每一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 ();


参考下实例:Python OpenCV 保存mp4视频,链接:https://xercis.blog.csdn.net/article/details/113358019?spm=1001.2101.3001.6650.17&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EESLANDING%7Edefault-17-113358019-blog-117959910.pc_relevant_landingrelevant&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EESLANDING%7Edefault-17-113358019-blog-117959910.pc_relevant_landingrelevant&utm_relevant_index=23

不知道能不能帮到你?

/**************************************************************************************************/

    //视频播放及保存
    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);
    }
}