Read OpenCV sequential frames using cvQueryframe

I have a basic question regarding 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, then is frame2 pointer to the second frame? So will two cvQueryFrame() calls read sequential frames?

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

Thank you in advance

EDIT: I found from google that calling cvQueryFrame () returns the same pointer twice. now i'm a little confused. If I use the call only once in the while loop, the frames progress, but not if I call it twice? Is there an easy way to capture two frames?

+4
source share
3 answers

cvQueryFrame() returns a pointer to the OpenCV "private" internal buffer, which it always fills with the last captured frame.
If you need 2 frames, you will need to cache the copy. Once you have cvCloneImage() (for example, using cvCloneImage() ) the space for your previous frame, you can use cvCopy() to copy only the image data. Do not use cvCloneImage() inside the loop, as it is very inefficient due to the allocation of internal memory (and freeing up memory, otherwise you will also have memory leaks).

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” copy time by doing the conversion instead.
For example, let's say that your display has a color, but your processing is in shades of gray. You only need two consecutive grayscale copies. Since you still need to convert to grayscale, you can do this directly from the captured frame, thereby avoiding excessive cvCopy() . To save the previous frame, you simply swap the pointers between the two selected grayscale images.

+9
source

Good!

You must make a copy of your frame. frame1 = cvQueryFrame (capture); This 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 this by pressing the waitkey button or something else, but if you do,

 img2 = cvQueryFrame( cap ); 

instead

 img2 = cvRetrieveFrame( cap ); 

because you will not have

 cvGrabFrame( cap ) 

more

I don't know if I am clear ... I stay here ^^

Enjoy;)

Laurent

+1
source

ok after 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 frame2 points to this new data.

Since cvQueryFrame is a wrapper for cvGrabFrame and cvRetrieveFrame together, I did not want to separate functions, so with a little 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 did here. Feel free to ask more questions.

+1
source

Source: https://habr.com/ru/post/1333857/


All Articles