mtcbf325 2022-12-12 15:36 采纳率: 33.3%
浏览 64
已结题

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%

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

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

4条回答 默认 最新

  • yy64ll826 2022-12-12 15:40
    关注

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

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

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 12月19日
  • 创建了问题 12月12日