Playing a video with OpenCV is almost as easy as displaying a single picture. The only new issue we face is that we need some kind of loop to read each frame in sequence; we may also need some way to get out of that loop if the movie is too boring. See Example 2-2.
Example 2-2. A simple OpenCV program for playing a video file from disk
#include "highgui.h" int main( int argc, char** argv ) { cvNamedWindow( "Example2", CV_WINDOW_AUTOSIZE ); CvCapture* capture = cvCreateFileCapture( argv[1] ); IplImage* frame; while(1) { frame = cvQueryFrame( capture ); if( !frame ) break; cvShowImage( "Example2", frame ); char c = cvWaitKey(33); if( c == 27 ) break; } cvReleaseCapture( &capture ); cvDestroyWindow( "Example2" ); }
Here we begin the function main()
with the usual
creation of a named window, in this case "Example2
".
Things get a little more interesting after that.
CvCapture* capture = cvCreateFileCapture( argv[1] );
The function cvCreateFileCapture()
takes as its
argument the name of the AVI file to be loaded and then returns a pointer to a CvCapture
structure. This structure contains all of the
information about the AVI file being read, including state information. When
created in this way, the CvCapture
structure is
initialized to the beginning of the AVI.
frame = cvQueryFrame( capture );
Once inside of the while(1)
loop, we begin reading from the AVI file. cvQueryFrame()
takes as its argument a pointer to a CvCapture
structure.
It then grabs the next video frame into memory (memory that is actually part of the CvCapture
structure). A pointer is returned to that frame.
Unlike cvLoadImage
, which actually allocates memory for
the image, cvQueryFrame
uses memory already allocated in
the CvCapture
structure. Thus it will not be necessary
(or wise) to call cvReleaseImage()
for this "frame"
pointer. Instead, the frame image memory will be freed when the CvCapture
structure is released.
c = cvWaitKey(33); if( c == 27 ) break;
Once we have displayed the frame, we then wait for 33 ms.[11] If the user hits a key, then c
will be set to
the ASCII value of that key; if not, then it will be set to –1. If the user hits the Esc key
(ASCII 27), then we will exit the read loop. Otherwise, 33 ms will pass and we will just
execute the loop again.
It is worth noting that, in this simple example, we are not explicitly controlling the
speed of the video in any intelligent way. We are relying solely on the timer in cvWaitKey()
to pace the loading of
frames. In a more sophisticated application it would be wise to read the actual frame rate
from the CvCapture
structure (from the AVI) and behave
accordingly!
cvReleaseCapture( &capture );
When we have exited the read loop—because there was no more video data or because the
user hit the Esc key—we can free the memory associated with the CvCapture
structure. This will also close any open file handles to the AVI
file.
[11] You can wait any amount of time you like. In this case, we are simply assuming that
it is correct to play the video at 30 frames per second and allow user input to interrupt between each frame (thus we pause for input 33 ms between
each frame). In practice, it is better to check the CvCapture
structure returned by cvCaptureFromCamera()
in order to determine the actual frame rate (more on
this in Chapter 4).