OpenCV - 是双重缓冲视频源所需的.clone()函数吗?

时间:2012-12-19 03:28:23

标签: video opencv double buffer capture

我试图在我的OpenCV程序中对我的VideoCapture输出进行双重缓冲(以减少闪烁)。这是迄今为止的概念:

    Mat frameA, frameB;  //alternating between these two for storage
    VideoCapture cap(0); // open the default camera
    for(;;)
    {
        cap >> frameB; 
        waitKey(30);
        cap >> frameA;
        waitKey(30);


        putText(frameA,SSTR("A"),Point(frameA.cols/2,frameA.rows/2),3,5,CV_RGB(250,200,200));
        putText(frameB,SSTR("B"),Point(frameA.cols/2,frameB.rows/2),3,5,CV_RGB(250,200,200));


        imshow("A",frameA);
        imshow("B",frameB);

        waitKey(30);

    }

作为一个简单的测试,我将文本A或B写在框架的中心。但输出有A和B重叠 - 好像没有两个独立的帧。我做错了什么?
我已经使用.clone()运算符做了一个解决方案,但是我知道在CPU(?)方面这种东西非常昂贵,因此我们希望避免它。希望我们在这里有一些C ++双缓冲专家。

2 个答案:

答案 0 :(得分:1)

我有同样的问题。我想,你在OpenCV(对我而言是2.4.9v)实现中发现了一个错误。在HiGUI模块(cap.cpp)的源代码中:

bool VideoCapture::retrieve(Mat& image, int channel)
{
    IplImage* _img = cvRetrieveFrame(cap, channel);
    if( !_img )
    {
        image.release();
        return false;
    }
    if(_img->origin == IPL_ORIGIN_TL)
        image = Mat(_img); << NO COPY
    else
    {
        Mat temp(_img);    << NO COPY
        flip(temp, image, 0); << Here is deep copy done
    }
    return true;
}

如果_img-&gt; origin == IPL_ORIGIN_TL从IplImage转换为cv :: Mat已完成WITHOUT复制数据,因为构造函数的声明如下所示:

//! converts old-style IplImage to the new matrix; the data is not copied by default
Mat(const IplImage* img, bool copyData=false);

建议的解决方案:

  1. 手动复制抓取cv :: Mat。
  2. 有人应该向OpenCV提交错误。
  3. UPD。似乎这个note来自OpenCV 2.x的实际文档:

      

    注意:OpenCV 1.x函数cvRetrieveFrame和cv.RetrieveFrame返回   存储在视频捕获结构内的图像。这个不允许   修改或发布图像!您可以使用复制框架   cvCloneImage()然后用副本做任何你想做的事。

答案 1 :(得分:0)

OpenCV文档不清楚,但本说明也适用于2.x API:

  

注意:OpenCV 1.x函数cvRetrieveFrame和cv.RetrieveFrame返回存储在视频捕获结构中的图像。不允许修改或释放图像!您可以使用cvCloneImage()复制框架,然后使用副本执行任何操作。

这意味着OpenCV总是使用相同的内存位置来读取摄像头输入,因此无法避免对clone()的调用。