如何使用C++提取视频帧并将其保存为图像

3

我现在正在尝试将视频文件的帧保存为图像在我的电脑上。我正在使用Visual Studio 2010和OpenCV 2.3.1。在下面的代码中,它可以保存图像序列的帧,但对于视频文件,我无法保存帧。 问题似乎特别出现在videoProcessing()函数中:

   string imageToSave =("output_MOG_" +  frameNumberString + ".png");
  bool saved = imwrite( imageToSave,fgMaskMOG);
  if(!saved) {
   cerr << "Unable to save " << imageToSave << endl;
      } 

有人能帮忙解决这个问题吗?
提前感谢。

我的代码是这样的:

    //opencv
 #include < opencv2/opencv.hpp>
 #include < opencv2/core/core.hpp>
 #include < opencv2/highgui/highgui.hpp>
 #include < opencv2/video/background_segm.hpp>
 //#include <opencv2/imgcodecs.hpp>
 #include <opencv2/imgproc/imgproc.hpp>
 //#include "opencv2/videoio.hpp"
  #include <opencv2/video/video.hpp>
 //C
 #include <stdio.h>
//C++
#include <iostream>
#include <sstream>

using namespace cv;
using namespace std;

      // Global variables
  Mat frame; //current frame
 Mat fgMaskMOG; //fg mask fg mask generated by MOG method
 Ptr<BackgroundSubtractor> pMOG; //MOG Background subtractor
 int keyboard; //input from keyboard

 /** Function Headers */
void help();
void processVideo(char* videoFilename);
void processImages(char* firstFrameFilename);

void help()
{
 cout
   << "---------------------------------------------------------------------   -----" << endl
 << "This program shows how to use background subtraction methods provided by "  << endl
<< " OpenCV. You can process both videos (-vid) and images (-img)."             << endl
                                                                                << endl
<< "Usage:"                                                                     << endl
<< "./bs {-vid <video filename>|-img <image filename>}"                         << endl
<< "for example: ./bs -vid video.avi"                                           << endl
<< "or: ./bs -img /data/images/1.png"                                           << endl
<< "--------------------------------------------------------------------------" << endl
<< endl;
 }

/**
 * @function main
 */
int main(int argc, char* argv[])
{


  //print help information
  help();

    //check for the input parameter correctness
    if(argc != 3) {
    cerr <<"Incorret input list" << endl;
    cerr <<"exiting..." << endl;
    return EXIT_FAILURE;
}


//create GUI windows
namedWindow("Frame");
namedWindow("FG Mask MOG ");

//create Background Subtractor objects
pMOG = new BackgroundSubtractorMOG();
if(strcmp(argv[1], "-vid") == 0) {
    //input data coming from a video
    processVideo(argv[2]);
}
else if(strcmp(argv[1], "-img") == 0) {
    //input data coming from a sequence of images
    processImages(argv[2]);
}
else {
    //error in reading input parameters
    cerr <<"Please, check the input parameters." << endl;
    cerr <<"Exiting..." << endl;
    return EXIT_FAILURE;
}
//destroy GUI windows
destroyAllWindows();
return EXIT_SUCCESS;
}

 //function processVideo

 void processVideo(char* videoFilename) {
  //create the capture object
    VideoCapture capture(videoFilename);
  if(!capture.isOpened()){
    //error in opening the video input
    cerr << "Unable to open video file: " << videoFilename << endl;
    exit(EXIT_FAILURE);
 }
 //read input data. ESC or 'q' for quitting
  while( (char)keyboard != 'q' && (char)keyboard != 27 ){
    //read the current frame
    if(!capture.read(frame)) {
        cerr << "Unable to read next frame." << endl;
        cerr << "Exiting..." << endl;
        exit(EXIT_FAILURE);
    }

    //update the background model
    pMOG->operator()(frame, fgMaskMOG,0.9);
    //get the frame number and write it on the current frame

    stringstream ss;
    rectangle(frame, cv::Point(10, 2), cv::Point(100,20),
              cv::Scalar(255,255,255), -1);
    ss << capture.get(CV_CAP_PROP_POS_FRAMES);
    string frameNumberString = ss.str();

    putText(frame, frameNumberString.c_str(), cv::Point(15, 15),
            FONT_HERSHEY_SIMPLEX, 0.5 , cv::Scalar(0,0,0));
    //show the current frame and the fg masks
    imshow("Frame", frame);
    imshow("FG Mask MOG  ", fgMaskMOG);
    //get the input from the keyboard
    keyboard = waitKey( 30 );
}

/*
string imageToSave =("output_MOG_" +  frameNumberString + ".bmp");
    bool saved = imwrite( imageToSave,fgMaskMOG);
    if(!saved) {
    cerr << "Unable to save " << imageToSave << endl;
       } 
      */


//delete capture object
 capture.release();
 }

/**
 * @function processImages
 */
void processImages(char* fistFrameFilename) {
  //read the first file of the sequence
  frame = imread(fistFrameFilename);
  if(frame.empty()){
    //error in opening the first image
    cerr << "Unable to open first image frame: " << fistFrameFilename <<     endl;
    exit(EXIT_FAILURE);
}
//current image filename
string fn(fistFrameFilename);
//read input data. ESC or 'q' for quitting
while( (char)keyboard != 'q' && (char)keyboard != 27 ){
    //update the background model
    pMOG->operator()(frame, fgMaskMOG,0.9);
    //get the frame number and write it on the current frame
    size_t index = fn.find_last_of("/");
    if(index == string::npos) {
        index = fn.find_last_of("\\");
    }
    size_t index2 = fn.find_last_of(".");
    string prefix = fn.substr(0,index+1);
    string suffix = fn.substr(index2);
    string frameNumberString = fn.substr(index+1, index2-index-1);
    istringstream iss(frameNumberString);
    int frameNumber = 0;
    iss >> frameNumber;
    rectangle(frame, cv::Point(10, 2), cv::Point(100,20),
              cv::Scalar(255,255,255), -1);
    putText(frame, frameNumberString.c_str(), cv::Point(15, 15),
            FONT_HERSHEY_SIMPLEX, 0.5 , cv::Scalar(0,0,0));
    //show the current frame and the fg masks
    imshow("Frame", frame);
    imshow("FG Mask MOG ", fgMaskMOG);
    //get the input from the keyboard
    keyboard = waitKey( 30 );
    //search for the next image in the sequence
    ostringstream oss;
    oss << (frameNumber + 1);
    string nextFrameNumberString = oss.str();
    string nextFrameFilename = prefix + nextFrameNumberString + suffix;
    //read the next frame
    frame = imread(nextFrameFilename);
    if(frame.empty()){
        //error in opening the next image in the sequence
        cerr << "Unable to open image frame: " << nextFrameFilename << endl;
        exit(EXIT_FAILURE);
    }
    //update the path of the current frame
    fn.assign(nextFrameFilename);

    // save subtracted images
    string imageToSave =("output_MOG_" +  frameNumberString + ".png");
    bool saved = imwrite( imageToSave,fgMaskMOG);
    if(!saved) {
    cerr << "Unable to save " << imageToSave << endl;
       }
}
}

你应该添加完整的代码!这段代码是不完整的。 - undefined
一旦你有了一个帧,只需使用VideoWriter来保存视频。 - undefined
我已经添加了代码。 - undefined
请提供一个 mcve,强调最小化。2) 你尝试过使用VideoWriter吗,就像之前建议的那样? - undefined
我已经尝试过了,但仍然找不到任何存储的图像或视频。 ` VideoWriter oVideoWriter ("fgMaskMOG", capture.get(CV_CAP_PROP_FOURCC), capture.get(CV_CAP_PROP_FPS), cv::Size(capture.get(CV_CAP_PROP_FRAME_WIDTH), capture.get(CV_CAP_PROP_FRAME_HEIGHT))); while (true) {
if (!capture.read(frame))
break;oVideoWriter.write(fgMaskMOG);} capture.release(); `
- undefined
显示剩余2条评论
1个回答

5
这是一个使用您的网络摄像头的小样本。您可以轻松地将其调整为使用视频:
#include "opencv2/opencv.hpp"
using namespace cv;

int main(int, char**)
{
    VideoCapture cap(0); // open the default camera
    if (!cap.isOpened())  // check if we succeeded
        return -1;

    Ptr<BackgroundSubtractor> pMOG = new BackgroundSubtractorMOG2();

    Mat fg_mask;
    Mat frame;
    int count = -1;

    for (;;)
    {
        // Get frame
        cap >> frame; // get a new frame from camera

        // Update counter
        ++count;

        // Background subtraction
        pMOG->operator()(frame, fg_mask);

        imshow("frame", frame);
        imshow("fg_mask", fg_mask);

        // Save foreground mask
        string name = "mask_" + std::to_string(count) + ".png";
        imwrite("D:\\SO\\temp\\" + name, fg_mask);

        if (waitKey(1) >= 0) break;
    }
    // the camera will be deinitialized automatically in VideoCapture destructor
    return 0;
}

在这一行代码中 string name = "mask_" + std::to_string(count) + ".png"; 看起来我需要排除std 因为我已经在开头声明了我正在使用命名空间std; 但是如何修复它呢? - undefined
如果这个方法不起作用,你可能在使用一个旧的编译器。像例子中一样使用stringstream。 - undefined
谢谢,到目前为止这个对我在使用网络摄像头的情况下有所帮助 但是我的相机仍然有问题,不仅仅是在这段代码中 它有时显示场景,有时显示灰色窗口。 - undefined
对于此行中的问题:string name = "mask_" + std::to_string(count) + ".png"; 我通过添加 string name = "mask_" + std::to_string(static_cast<long long>(count) + ".png"; 解决了它。 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接