我的目标是以30 fps的速度从Kinect捕获所有帧(RGB)并将它们保存到我的硬盘中。为此,我采取了以下方法。
从Kinect获取帧并将它们存储在数组缓冲区中。由于写入磁盘(使用imwrite()
)需要一些时间,因此我可能会错过一些帧,因此我将它们存储在一个数组中,而不是直接将它们保存到磁盘。现在,我有另一个并行线程访问此数组并将各个帧作为映像写入磁盘。
现在我使用了一个大小为3000的静态数组并输入Mat
。这就足够了,因为我需要存储1.5分钟视频(1.5分钟= 2700帧)的帧。我已将数组声明如下:
#define NUM_FRAMES 3000
Mat rgb[NUM_FRAMES];
我已经通过使用以下代码读取图像并将其保存到阵列来测试此限制:
for(int i=0; i<NUM_FRAMES; i++)
{
Mat img = imread("image.jpg", CV_LOAD_IMAGE_COLOR);
rgb[i] = img;
imshow("Image", img);
cvWaitKey(10);
}
上面的代码执行得很完美。
但有一个问题是我用于使用Kinect捕获图像的代码,用IplImage
捕获图像。因此,我需要在使用之前将图像转换为cv::Mat
格式。我使用以下命令转换它:
IplImage* color = cvCreateImageHeader(cvSize(COLOR_WIDTH, COLOR_HEIGHT), IPL_DEPTH_8U, 4);
cvSetData(color, colorBuffer, colorLockedRect.Pitch); // colorBuffer and colorLockedRect.Pitch is something that Kinect uses. Not related to OpenCv
rgb[rgb_read++] = Mat(color, FLAG);
现在这就是我的问题。每当我设置#define FLAG true
时,都会导致内存泄漏并导致OpenCv Error: Insufficient memory (failed to allocate 1228804 bytes)
错误。
但是,如果我使用#define FLAG false
它可以正常工作,但我得到的帧是错误的,如下所示。它们是连续三个帧。
我正在我的手臂上移动,从上面可以看到图像被夹在中间。
有人可以指出这种奇怪行为的原因或任何其他获得所需结果的替代方法。几天以来,我一直在努力解决这个问题。请询问是否需要进一步澄清。
我正在使用OpenCV 2.4.8,Kinect SDK for Windows version-1.8.0和Microsoft Visual Studio 2010。
也可以有人向我解释CopyData
中Mat::Mat
参数的作用。我已经完成了this link,但它还不完全清楚。也许这就是为什么我不能解决上面的错误,因为它的工作不是很清楚。
提前致谢。
答案 0 :(得分:0)
首先,不使用IplImages,请坚持使用cv :: Mat。
该等效代码将是:
Mat img_borrowed = Mat( height, width, CV_8U4C, colorBuffer, colorLockedRect.Pitch );
请注意,这不会自行分配,它仍然是kinect的像素,所以你必须克隆()它:
rgb[rgb_read++] = img_borrowed.clone();
这与将上面代码中的标记设置为&#39; true&#39;相同。 (深层复制数据)
[编辑]也许跳过无用的第4频道是个好主意(也需要更少的内存),所以,你可以这样做,而不是上面的内容:
cvtColor( img_borrowed, rgb[rgb_read++], CV_BGRA2BGR); // will make a 'deep copy', too.
所以, - 这里有点糟糕:如果你没有在你的阵列中保存一份深层拷贝,你最终会出现乱码(以及所有的相同!)图像,可能由于锁定/解锁kinect缓冲区而导致未定义的行为,如果你做复制它(你必须),你将需要很多
不太可能,您可以在内存中保留3000 * 1024 * 786 * 4 = 9658368000字节,您将不得不以某种方式将其删除。