使用cvQueryframe读取连续帧OpenCV

时间:2010-12-30 23:57:36

标签: image-processing opencv

我对OpenCV中的cvQueryFrame()有一个基本的问题。

我有以下代码:

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

现在我的问题是:如果frame1是指向第一帧的指针,那么frame2是指向第二帧的指针吗?那么两个cvQueryFrame()调用会读取连续的帧吗?

我以为我先检查一下自己,但指针frame1frame2似乎有相同的十六进制值。 :我只需要一次捕获两个帧然后需要处理它们。

提前致谢

编辑:我发现从谷歌调用cvQueryFrame()两次返回相同的指针。现在我有点困惑。如果我在while循环中只使用一次调用它,帧会进展但如果我调用它两次则没有?是否有一种简单的方法可以抓住两个框架?

3 个答案:

答案 0 :(得分:9)

cvQueryFrame()返回指向OpenCV的“私有”内部缓冲区的指针,它始终填充最后一个抓取的帧。
如果您想要2帧,则需要缓存副本。为前一帧分配(例如使用cvCloneImage())空间后,您可以使用cvCopy()仅复制图像数据。 在循环中使用cvCloneImage()因为内部内存分配(和解除分配,否则你也会有内存泄漏)效率非常低。

更新:代码如下所示:

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 );

注意:通常,您可以通过转换来避免这种“冗余”复制时间。
例如,假设您的显示器是彩色的,但您的处理是灰度的。您只需要连续2个灰度副本。由于您无论如何都需要转换为灰度,因此您可以直接从捕获的帧中执行此操作,从而避免冗余cvCopy()。要保存前一帧,您只需在2个分配的灰度图像之间交换指针。

答案 1 :(得分:1)

好的!

你必须复制你的画面。 frame1 = cvQueryFrame(capture);是你说的指针。

我找到的代码是:

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 );

您可以使用waitkey或其他任何内容替换while,但如果您使用

img2 = cvQueryFrame( cap ); 

而不是

img2 = cvRetrieveFrame( cap );

因为你没有

cvGrabFrame( cap )

我不知道我是否清楚......我留在这里^^

享受;)

劳伦

答案 2 :(得分:1)

从劳伦特的回答中可以看出:我相信密钥是cvCloneImage()。 cvCloneImage创建原始图像的新副本,包括标题,ROI,imageData等,然后将frame2指向此新数据。

因为cvQueryFrame是cvGrabFrame&的包装器。 cvRetrieveFrame在一起我不想拆分这些函数,所以通过一个小的修改,我仍然可以使用cvQueryFrame。

以下是我修改过的解决方案。


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 }

我希望你明白我在这里所做的一切。 随意提出更多问题。