opencv write webcam output to avi file

2019-03-25 12:55发布

问题:

I am trying to create an avi video from my webcam output using opencv. No exceptions are thrown, however the avi file it creates is 414 bytes in size and does not grow.

Also it will not play with any media player. I suspect there is something wrong with the writing to file part.

Here is the code:

  CvCapture *capture = cvCaptureFromCAM( 0 );

  int width = ( int )cvGetCaptureProperty( capture, 
  CV_CAP_PROP_FRAME_WIDTH );

  int height = ( int )cvGetCaptureProperty( capture,
  CV_CAP_PROP_FRAME_HEIGHT );
  CvVideoWriter *writer = cvCreateVideoWriter("CamCapture.avi",                                                     
  -1,30, cvSize(  width, height ) );

  cvNamedWindow("capWindow", CV_WINDOW_AUTOSIZE);
  IplImage *frame = 0;

  // this returns 0 not sure why ??
  //double fps = cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
  double fps = 30;

  while( 1 )
  {
      frame = cvQueryFrame( capture );
      cvShowImage("capWindow",frame);
      cvWriteFrame( writer, frame );
      char c = cvWaitKey(1000/fps);

      if( c == 27 ) break;
  }

   cvReleaseCapture( &capture );
   cvReleaseVideoWriter( &writer );
   cvDestroyWindow( "capWindow" );

I have referenced and tried the following samples with no luck:

  • http://gipetrou.com/scc/2010/12/12/save-video-from-webcam-with-opencv-2-1/
  • http://answers.oreilly.com/topic/1366-how-to-write-to-an-avi-file-with-opencv/
  • https://www.cs.utexas.edu/~teammco/misc/udp_video/

回答1:

Dont use outdated C, use C++ api, it is easy to use and simple, for example the above code can be rewritten in C++ like,

#include "opencv2/opencv.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main(){

    VideoCapture vcap(0); 
      if(!vcap.isOpened()){
             cout << "Error opening video stream or file" << endl;
             return -1;
      }

   int frame_width=   vcap.get(CV_CAP_PROP_FRAME_WIDTH);
   int frame_height=   vcap.get(CV_CAP_PROP_FRAME_HEIGHT);
   VideoWriter video("out.avi",CV_FOURCC('M','J','P','G'),10, Size(frame_width,frame_height),true);

   for(;;){

       Mat frame;
       vcap >> frame;
       video.write(frame);
       imshow( "Frame", frame );
       char c = (char)waitKey(33);
       if( c == 27 ) break;
    }
  return 0;
}


回答2:

Use below code to write AVI format from capturing camera input.

#include "opencv2/highgui/highgui.hpp"
#include <iostream>

using namespace cv;
using namespace std;

int main(int argc, char* argv[])
{
    VideoCapture cap(0); // open the video camera no. 0

    if (!cap.isOpened())  // if not success, exit program
    {
        cout << "ERROR: Cannot open the video file" << endl;
        return -1;
    }

 namedWindow("MyVideo",CV_WINDOW_AUTOSIZE); //create a window called "MyVideo"

   double dWidth = cap.get(CV_CAP_PROP_FRAME_WIDTH); //get the width of frames of the video
   double dHeight = cap.get(CV_CAP_PROP_FRAME_HEIGHT); //get the height of frames of the video

   cout << "Frame Size = " << dWidth << "x" << dHeight << endl;

   Size frameSize(static_cast<int>(dWidth), static_cast<int>(dHeight));

 VideoWriter oVideoWriter ("D:/MyVideo.avi", CV_FOURCC('P','I','M','1'), 20, frameSize, true); //initialize the VideoWriter object 

   if ( !oVideoWriter.isOpened() ) //if not initialize the VideoWriter successfully, exit the program
   {
        cout << "ERROR: Failed to write the video" << endl;
        return -1;
   }

    while (1)
    {

        Mat frame;

        bool bSuccess = cap.read(frame); // read a new frame from video

        if (!bSuccess) //if not success, break loop
       {
             cout << "ERROR: Cannot read a frame from video file" << endl;
             break;
        }

         oVideoWriter.write(frame); //writer the frame into the file

        imshow("MyVideo", frame); //show the frame in "MyVideo" window

        if (waitKey(10) == 27) //wait for 'esc' key press for 30ms. If 'esc' key is pressed, break loop
       {
            cout << "esc key is pressed by user" << endl;
            break; 
       }
    }

    return 0;

}