我试图在我的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 ++双缓冲专家。
答案 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);
建议的解决方案:
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()的调用。