开发者

read successive frames OpenCV using cvQueryframe

I have a basic question in regards to cvQueryFrame() in OpenCV.

I have the following code:

IplImage *frame1,*frame2;
frame1 = cvQueryFrame(capture);
frame2 = cvQueryFrame(capture);

Now my question is: if frame1 is a pointer to the first frame, is frame2 a pointer to the 2nd frame? So will the two cvQueryFrame() calls read successive frames?

I thought I'd check myself first but the pointers frame1,frame2 seem to have the same hex value. :s I just need to capture two frames at a time and then need to process them.

Thanks in advance

EDIT: I found from google that calling cvQueryFrame() twice returns the same pointer. now I am slightly confused. If i use call it only once in a while loop, the frames progress but not if i call it twice? Is there a easy w开发者_StackOverfloway to grab two frames?


cvQueryFrame() returns the pointer to OpenCV's "private" internal buffer which it always fills with the last grabbed frame.
If you want 2 frames you will need to cache a copy. Once you allocate (e.g. using cvCloneImage()) space for your previous frame, you can use cvCopy() to copy just the image data. Do not use cvCloneImage() inside the loop as that is very inefficient due to the internal memory allocations (and deallocations, otherwise you'll have memory leaks as well).

Update: the code will look something like this:

IplImage* currFrame = 0;
IplImage* prevFrame = 0;
CvCapture* cap = cvCaptureFromAVI("sample.avi");   
currFrame = cvQueryFrame( cap );

 // Clone the frame to have an identically sized and typed copy
prevFrame  = cvCloneImage( currFrame );

while(currFrame = cvQueryFrame( cap ))
{
    // process the video using currFrame and prevFrame...

    // ...


    // When done, overwrite prevFrame with current copy in preparation
    // for the next frame.
    cvCopy( currFrame , prevFrame); 
} 

cvReleaseImage( &img1 );
cvReleaseCapture( &cap );

Note: Often, you can avoid this "redundant" copying time by doing a conversion instead.
For example, say your display is in color, but your processing is in grayscale. You only need the 2 consecutive copies in grayscale. Since you will need to convert to grayscale anyway, you can do that directly from the captured frame thus avoiding the redundant cvCopy(). To save the previous frame you would just swap pointers between your 2 allocated grayscale images.


Ok !

You have to make a copy of your frame. frame1 = cvQueryFrame(capture); is a pointer as you said.

The code i found is :

IplImage* img1(null), img2(null);
CvCapture* cap = cvCaptureFromAVI("mavideo.avi");
img2 = cvQueryFrame( cap );
img1 = cvCloneImage( img2 ); // on alloue une nouvelle image

while( cvGrabFrame( cap ) )
{
    cvCopy( img2, img1 ); // copie de l'image, pas du pointeur
    img2 = cvRetrieveFrame( cap );
} 

cvReleaseCapture( &cap );
cvReleaseImage( &img1 );

You can replace the while by a waitkey or anything but if you do that use

img2 = cvQueryFrame( cap ); 

instead of

img2 = cvRetrieveFrame( cap );

cause you'll not have the

cvGrabFrame( cap )

anymore

I don't know if i'm clear so... i stay here ^^

Enjoy ;)

Laurent


ok following from Laurent's answer: I believe the key is cvCloneImage(). cvCloneImage creates a new copy of the original image including the header, ROI, imageData etc. and then points frame2 to this new data.

Since cvQueryFrame is a wrapper for cvGrabFrame & cvRetrieveFrame together I didn't want to split up the functions, so with a small modification I can still use cvQueryFrame.

Below is my modified solution.


IplImage *frame = cvQueryFrame(capture); //to read properties of frame.
IplImage *frame2 = NULL;

while (1){ if(frame2) frame = cvCloneImage(frame2); // copy image to allow grabbing next frame frame2 = cvQueryFrame(capture); //read next frame if(!frame2) break; //if frame cannot be read, EOF so break from loop }

I hope you understand what I've done here. Feel free to ask any more questions.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜