How to write a video file with OpenCV?

CCS picture CCS · Feb 2, 2011 · Viewed 25.3k times · Source

I am trying to write a program to analyze emotional expressions like tears. As part of my tracker I am using OpenCV to record sample videos. Particularly, I am not certain about how to correctly choose FPS (10FPS seems like it ought to work). I am also not sure which Codec I should use on OS X, I have tried all possible CV_FOURCC from here as well but returned the following error:

Stream #0.0: Video: rawvideo, yuv420p, 640x480, q=2-31, 19660 kb/s, 90k tbn, 10 tbc
Assertion failed: (image->imageSize == avpicture_get_size( (PixelFormat)input_pix_fmt, image->width, image->height )), function writeFrame, file /opt/local/var/macports/build/_opt_local_var_macports_sources_rsync.macports.org_release_ports_graphics_opencv/work/OpenCV-2.2.0/modules/highgui/src/cap_ffmpeg.cpp, line 1085.

Do you all have some working code with cvWriteFrame? Thanks for taking time to look at my problem!

For those interested the entire program is:

#include <cv.h>
#include <cxcore.h>
#include <highgui.h>

int main (int argc, const char * argv[]) 
{
    CvCapture *capture;
    IplImage  *img;
    int       key = 0;
    CvVideoWriter *writer;

    // initialize camera
    capture = cvCaptureFromCAM( 0 );
    // capture = cvCaptureFromAVI("AVIFile");

    // always check
    assert( capture );

    // create a window
    cvNamedWindow( "video", 1 );

    int color = 1; // 0 for black and white

    // get the frame size
    CvSize size = cvSize((int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH),(int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT));

    writer = cvCreateVideoWriter(argv[1], -1 , 10 , size, color);

    while( key != 'q' ) {
        // get a frame
        img = cvQueryFrame( capture );

        // always check
        if( !img ) break;

        cvWriteFrame( writer, img );        
        cvShowImage("video", img );

        // quit if user press 'q'
        key = cvWaitKey( 5 );
    }

    // free memory
    cvReleaseVideoWriter( &writer );
    cvReleaseCapture( &capture );
    cvDestroyWindow( "video" );

    return 0;   
}

Answer

mpenkov picture mpenkov · Feb 3, 2011

Have a look here for the recommended codecs to use.

Basically:

  • You can use -1 instead of CV_FOURCC(...) only if you're on Windows (see the manual). Since you're on OSX, you can't use it.
  • Use CV_FOURCC('I', 'Y', 'U', 'V') to encode using yuv420p into an uncompressed AVI container -- this is the recommended approach
  • If you want compressed video, then you can use tools like ffmpeg to compress the AVI output by OpenCV

The reason OpenCV doesn't recommend using compressor codecs is probably because each codec has a large number of codec-specific options, and dealing with all of them through the simple OpenCV video writer interface would be impossible.

EDIT

I have some bad news:

Unfortunately, we still have no working (i.e. native) video writer for Mac OS X. If you need video writing, you should currently configure for ffmpeg or xine and disable QuickTime.

Sounds like you may need to reconfigure and recompile your library.

EDIT 2

Alternatively, you could just write each frame to a JPEG file, and then stitch those JPEG files into a movie using ffmpeg (that should work on OS/X). This is essentially what MJPEG is, anyway. You'll probably get better compression rates with codecs that exploit temporal redundancy (e.g. MPEG4, H.264, etc), though.