From my perspective one of the most intriguing applications of all this simple image and file handling so far is reading in data from a webcam. I was pleasantly surprised at how easy it was using OpenCV. Below is the code I used to read in information from a webcam and save it to a file.

# include "highgui.h" # include "cv.h" int main( int argc, char** argv ) { CvCapture* capture; capture = cvCreateCameraCapture(0); assert( capture != NULL ); IplImage* bgr_frame = cvQueryFrame( capture ); CvSize size = cvSize( (int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_WIDTH), (int)cvGetCaptureProperty( capture, CV_CAP_PROP_FRAME_HEIGHT) ); cvNamedWindow( "Webcam", CV_WINDOW_AUTOSIZE ); CvVideoWriter *writer = cvCreateVideoWriter( argv[ 1 ], CV_FOURCC('D','I','V','X'), 30, size ); while( (bgr_frame = cvQueryFrame( capture )) != NULL ) { cvWriteFrame( writer, bgr_frame ); cvShowImage( "Webcam", bgr_frame ); char c = cvWaitKey( 33 ); if( c == 27 ) break; } cvReleaseVideoWriter( &writer ); cvReleaseCapture( &capture ); cvDestroyWindow( "Webcam" ); return( 0 ); }

Get the code from my Git Repository

If you need help with Git, follow this quick introduction – Getting Started With Git

So the idea behind the program is this… First I wanted to make a pointer to a CvCapture structure, because I’m going to need somehwere to store the webcam information and capture feed. When I initialized the new capture structure, I used a new function CreateCameraCapture…

CvCapture* cvCreateCameraCapture( int index )

index - The camera device number Index Device 0 /dev/video0 1 /dev/video1 2 /dev/video2 3 /dev/video3 ... 7 /dev/video7 with -1 /dev/video

So I initialized the structure with my webcam /dev/video0, any number can be used, and the -1 will choose one arbitrarily.

Next I needed an IplImage structure pointer for displaying each frame captured by my webcam, but I wanted to do more than just display it. I wanted to write each frame down into a file as the camera was running. For the CreateVideoWriter function, which we’ll see momentarily, I needed the size of the images being captured by my webcam. There is another structure for storing the sizes, CvSize. It’s declared inside cxtypes.h as simply as it sounds.

typedef struct { int width; int height; } CvSize;

After declaring a variable of type CvSize, I instantiated it with the cvSize function.

CvSize cvSize( int width, int height ) { CvSize s; s.width = width; s.height = height; return s; }

It’s as easy as that, I don’t think that needs much explanation.

What does deserve an explanation is the super handy dandy cvGetCaptureProperty function. Notice I used it to get the height and width of my camera’s captured images and set that as the height and width of the new CvSize structure. Here is how it works.

double cvGetCaptureProperty(CvCapture* capture, int property_id);

capture - This is the structure containing all the information about it's video/camera/movie property_id - The property information desried. Can be any of the following: CV_CAP_PROP_POS_MSEC 0 CV_CAP_PROP_POS_FRAMES 1 CV_CAP_PROP_POS_AVI_RATIO 2 CV_CAP_PROP_FRAME_WIDTH 3 CV_CAP_PROP_FRAME_HEIGHT 4 CV_CAP_PROP_FPS 5 CV_CAP_PROP_FOURCC 6 CV_CAP_PROP_FRAME_COUNT 7 CV_CAP_PROP_FORMAT 8 CV_CAP_PROP_MODE 9 CV_CAP_PROP_BRIGHTNESS 10 CV_CAP_PROP_CONTRAST 11 CV_CAP_PROP_SATURATION 12 CV_CAP_PROP_HUE 13 CV_CAP_PROP_GAIN 14 CV_CAP_PROP_EXPOSURE 15 CV_CAP_PROP_CONVERT_RGB 16 CV_CAP_PROP_WHITE_BALANCE 17 CV_CAP_PROP_RECTIFICATION 18

I find this to be a great function, one worth memorizing. Take note that it returns a double, so I needed to static cast them to integers for the cvSize function to accept them.

Inside the loop I’m thinking, I want to be writing the frames from the video feed before I display them. This is from remembering that IplImage structures instantiated to a CvCapture’s frames are released immediately after the function ends. So I’d have to write each frame down before they were released, and to write an image I needed a writer…

typedef struct CvVideoWriter CvVideoWriter; CvVideoWriter* cvCreateVideoWriter( const char* filename, int fourcc, double fps, CvSize frame_size );

filename - Name of the output video file. fourcc - 4-character code of codec used to compress the frames. For example, CV_FOURCC('P','I','M','1') is MPEG-1 codec, CV_FOURCC('M','J','P','G') is motion-jpeg codec etc. Under Win32 it is possible to pass -1 in order to choose compression method and additional compression parameters from dialog. fps - Framerate of the created video stream. frame_size - Size of video frames.

I had some trouble with this function for a bit. The codec you choose to compress the frames must be on your computer. I put in a codec I believed was on my system only to find it not writing the file, after a while of searching and reading through the source, I found the problem which I recorded in my OpenCV Errors section.

I know what you’re thinking. “Hey! You put the fps in manually to 30, but I remember seeing a CV_CAP_PROP_FPS, why didn’t you use the cvGetCaptureProperty function and store it in a double and put it in that way?” Well I tried that. For a reason I’m not sure of yet, my webcam doesn’t seem to be sharing that information nicely with my computer, so I was receiving an error telling me it couldn’t read the fps from the CvCapture structure. Oh well. 30 fps seems to be working fine.

So I’m ready for the loop. I get it going with some new pizazz, but the logic is the same. As planned I write the frame first, then display it.

int cvWriteFrame( CvVideoWriter* writer, const IplImage* image );

writer - Video writer structure. image - The frame to be written.

It does precisely what it says, takes in an image and writes it to the file that was given to the CreateVideoWriter function. Then show the image, and do that standard clean up, including releasing the new CvVideoWriter with the usual approach.

void cvReleaseVideoWriter( CvVideoWriter** writer );

writer - Pointer to the video file writer structure.

That’s that. Now by running this program a window will pop up displaying everything the webcam sees and save it to a file given as the first parameter to the main function. You can use the video player that was written in the previous post Basic Video Manipulation to test out the newly recorded video.

References

I’m studying from Gary Bradski’s Learning OpenCV