Writing to an AVI File

In many applications we will want to record streaming input or even disparate captured images to an output video stream, and OpenCV provides a straightforward method for doing this. Just as we are able to create a capture device that allows us to grab frames one at a time from a video stream, we are able to create a writer device that allows us to place frames one by one into a video file. The routine that allows us to do this is cvCreateVideoWriter().

Once this call has been made, we may successively call cvWriteFrame(), once for each frame, and finally cvReleaseVideoWriter() when we are done. Example 2-10 describes a simple program that opens a video file, reads the contents, converts them to a log-polar format (something like what your eye actually sees, as described in Chapter 6), and writes out the log-polar image to a new video file.

Example 2-10. A complete program to read in a color video and write out the log-polar transformed video

// Convert a video to grayscale
 // argv[1]: input video file
 // argv[2]: name of new output file
 //
#include "cv.h"
#include "highgui.h"
main( int argc, char* argv[] ) {
    CvCapture* capture = 0;
    capture = cvCreateFileCapture( argv[1] );
    if(!capture){
         return -1;
    }
    IplImage *bgr_frame=cvQueryFrame(capture);//Init the video read
    double fps = cvGetCaptureProperty (
        capture,
        CV_CAP_PROP_FPS
    );
    CvSize size = cvSize(
       (int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH),
       (int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT)
    );
    CvVideoWriter *writer = cvCreateVideoWriter(
        argv[2],
        CV_FOURCC('M','J','P','G'),
        fps,
        size
    );
    IplImage* logpolar_frame = cvCreateImage(
        size,
        IPL_DEPTH_8U,
        3
    );
    while( (bgr_frame=cvQueryFrame(capture)) != NULL ) {
        cvLogPolar( bgr_frame, logpolar_frame,
                    cvPoint2D32f(bgr_frame->width/2,
                    bgr_frame->height/2),
                    40,
                    CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS );
        cvWriteFrame( writer, logpolar_frame );
    }
    cvReleaseVideoWriter( &writer );
    cvReleaseImage( &logpolar_frame );
    cvReleaseCapture( &capture );
    return(0);
}

Looking over this program reveals mostly familiar elements. We open one video; start reading with cvQueryFrame(), which is necessary to read the video properties on some systems; and then use cvGetCaptureProperty() to ascertain various important properties of the video stream. We then open a video file for writing, convert the frame to log-polar format, and write the frames to this new file one at a time until there are none left. Then we close up.

The call to cvCreateVideoWriter() contains several parameters that we should understand. The first is just the filename for the new file. The second is the video codec with which the video stream will be compressed. There are countless such codecs in circulation, but whichever codec you choose must be available on your machine (codecs are installed separately from OpenCV). In our case we choose the relatively popular MJPG codec; this is indicated to OpenCV by using the macro CV_FOURCC(), which takes four characters as arguments. These characters constitute the "four-character code" of the codec, and every codec has such a code. The four-character code for motion jpeg is MJPG, so we specify that as CV_FOURCC('M','J','P','G').

The next two arguments are the replay frame rate, and the size of the images we will be using. In our case, we set these to the values we got from the original (color) video.