【问题标题】:Capture image frames from Kinect and save to Hard drive从 Kinect 捕获图像帧并保存到硬盘驱动器
【发布时间】:2014-12-17 13:39:05
【问题描述】:

我的目标是以 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,但仍然不完全清楚。也许这就是为什么我无法解决上述错误,因为它的工作不是很清楚。

提前致谢。

【问题讨论】:

    标签: c++ arrays opencv memory-leaks kinect-sdk


    【解决方案1】:

    首先,不要使用 IplImages,请坚持使用 cv::Mat。

    等效的代码是:

    Mat img_borrowed = Mat( height, width, CV_8U4C, colorBuffer, colorLockedRect.Pitch );
    

    注意,这不会自己做任何分配,它仍然是 kinect 的像素,所以你必须 clone() 它:

    rgb[rgb_read++] = img_borrowed.clone();
    

    这与将上面代码中的标志设置为“真”相同。 (深拷贝数据)

    [edit] 跳过无用的第 4 个频道(也需要更少的内存)也许是个好主意,所以,你可以这样做:

    cvtColor( img_borrowed, rgb[rgb_read++], CV_BGRA2BGR); // will make a 'deep copy', too.
    

    所以,- 很糟糕:如果你在你的数组中保存一个深拷贝,你最终会得到乱码(而且都是一样的!)图像,甚至可能由于 kinect 缓冲区的锁定/解锁导致的未定义行为,如果您确实复制它(并且必须),您将需要 大量内存。

    不太可能,您可以在内存中保留 3000 *1024*786*4 = 9658368000 字节,您必须以一种或另一种方式减少它。

    【讨论】:

    • 是的,没错,有时我什至会一遍又一遍地复制相同的图像。非常感谢您的回复。我会检查你所说的方法是否有效。但是为什么第一段代码(我在一个数组中加载 3000 张图像)工作得如此巧妙?
    • 哦!实际上,我从未将存储的图像保存回磁盘进行验证。由于它没有任何内存泄漏,我认为它是完美的。非常感谢您的提醒。
    • 是的,现在我知道出了什么问题。也许我需要减少我的数组限制或考虑其他一些替代方案。它是如此简单,即使那样,它也让我死了很长时间。我会接受答案。 :)
    • 您需要全尺寸图片吗?您可以将它们 resize() 为一半(可能多 4 倍的图片)或转换为 bgr(跳过 alpha,少 1 个通道)
    • 在我的笔记本电脑中,我的全尺寸图像接近 1200 张。一个并行线程也在写。所以如果我使用循环队列,我可能会得到更多,但这还不够。正如我所说,我需要接近 2700 帧。我将尝试减少帧大小,或者可能采用替代帧而不是所有帧。基本上我必须找到一个权衡。
    猜你喜欢
    • 2015-05-16
    • 1970-01-01
    • 2014-06-04
    • 1970-01-01
    • 2017-01-27
    • 1970-01-01
    • 2018-04-03
    • 2019-09-28
    • 2012-12-11
    相关资源
    最近更新 更多