Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Image processing 使用cvQueryframe读取OpenCV的连续帧_Image Processing_Opencv - Fatal编程技术网

Image processing 使用cvQueryframe读取OpenCV的连续帧

Image processing 使用cvQueryframe读取OpenCV的连续帧,image-processing,opencv,Image Processing,Opencv,关于OpenCV中的cvQueryFrame(),我有一个基本问题 我有以下代码: IplImage*frame1,*frame2; frame1=cvQueryFrame(捕获); frame2=cvQueryFrame(捕获) 现在我的问题是:如果frame1是指向第一帧的指针,那么frame2是指向第二帧的指针吗?那么这两个cvQueryFrame()调用会读取连续的帧吗 我想我应该先检查一下自己,但是指针frame1,frame2似乎有相同的十六进制值:我只需要一次捕获两帧,然后处理它们

关于OpenCV中的cvQueryFrame(),我有一个基本问题

我有以下代码:

IplImage*frame1,*frame2;
frame1=cvQueryFrame(捕获);
frame2=cvQueryFrame(捕获)

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

我想我应该先检查一下自己,但是指针
frame1
frame2
似乎有相同的十六进制值:我只需要一次捕获两帧,然后处理它们

提前谢谢

编辑:我从google发现调用cvQueryFrame()两次返回相同的指针。现在我有点困惑。如果我只在while循环中调用它一次,那么帧会进行,但如果我调用它两次,帧不会进行?有没有一种简单的方法可以抓取两个帧?

好的

你必须复制你的相框。 frame1=cvQueryFrame(捕获);正如你所说,这是一个指针

我找到的代码是:

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 )

我不知道我是否清楚所以。。。我呆在这里^^

享受;)


Laurent

根据Laurent的回答:我相信关键是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 }

IplImage*frame=cvQueryFrame(捕获)//读取帧的属性。
IplImage*frame2=NULL

而(1){ 如果(第2帧) frame=cvCloneImage(frame2);//复制图像以允许抓取下一帧 frame2=cvQueryFrame(捕获);//读取下一帧 if(!frame2)break;//如果无法读取帧,则EOF so从循环中断 }

我希望你明白我在这里做了什么。 请随意提问。

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 );
注意:通常,您可以通过转换来避免这种“多余”的复制时间。

例如,假设您的显示是彩色的,但处理是灰度的。您只需要两个连续的灰度副本。由于无论如何都需要转换为灰度,因此可以直接从捕获的帧转换为灰度,从而避免冗余的
cvCopy()
。要保存上一帧,您只需在两个分配的灰度图像之间交换指针。

嘿,我了解这种方法,但我认为cvQueryFrame只是cvGrabFrame和cvRetrieveFrame的包装器。是的。^^只是如果你改变while并删除cvGrabFrame(像我一样),你就不能正确使用cvRetrieveFrame。这只是一个警告。嘿,我发布了一个答案,至少对我来说更容易实现。劳伦特,这是我最后一年的硕士项目。我需要对热红外摄像机的实时视频进行实时图像处理。你呢?我理解你的方法,但有一个问题。如果建议不要在循环中使用cvCloneImage(),如何查询帧,然后使用cloneimage进行视频。在循环之外它是无用的,因为你只能得到一个帧。谢谢,我现在明白了。将尝试实现该功能并很快更新此线程。@Atharval我们是否可以使用相同的方法从第二帧中删除第一帧,并使用视频完成?然后返回视频?@Angel是的,现在您有了两帧
frame
frame2
,您可以减去它们并存储在
frame3
中。
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 );