QueryGrayFrame()上的SystemOutOfMemoryException与EmguCV

时间:2017-03-15 02:10:48

标签: c# out-of-memory emgucv

我正在使用此例程将视频的所有帧都放入一个帧数组中:

点击:

private int CompareTwoVideos(string _firstVideoPath, string _secondVideoPath)
        {
            Capture _capture;
            List<Image<Gray, Byte>> FirstALLFrames = new List<Image<Gray, Byte>>();
            // ..

            _capture = new Capture(FirstVideoLocation);

            // get all frames
            FirstALLFrames = GetAllFrames(_capture);

            // do some image processing
            // .. 

            _capture.Dispose();
            return 0;
        }

效用函数:

List<Image<Gray, byte>> GetAllFrames(Capture _capture)
{
    List<Image<Gray, byte>> AllFrames = new List<Image<Gray, byte>>();
    int FramesCount = 0;

    try
    {
        FramesCount = (int)_capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP_PROP.CV_CAP_PROP_FRAME_COUNT);

        for (int i = 0; i < FramesCount - 1; i++)
        {
            AllFrames.Add(_capture.QueryGrayFrame().Resize(ImageWidth, ImageHeight, Emgu.CV.CvEnum.INTER.CV_INTER_LINEAR));
        }
    }
    catch (Exception ex)
    {
        // Error pops here
    }

    return AllFrames;
}

第一次点击一切正常。

但是,第二次点击时会弹出错误

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我不是100%肯定你的意思&#34;第二次点击&#34;但我假设这意味着你再次直接运行代码来处理另一个视频。

似乎你的列表变得很大并占用了大量内存(也写成under Exceptions in the List(T) MSDN documentation)。您确实处置了_capture对象,但是您没有处置您的列表。因此,列表中仍可能存在引用,以防止它被系统正确处理和收集(因此请确保您没有对列表进行任何其他引用)。

此外,替换引用(使用new List()实例)不会立即释放集合,并且在垃圾收集器处置对象之前需要一些时间。很可能第二次点击只会导致您的程序使用太多内存,因为它现在在内存中包含太多完整的视频。您是否监控过应用程序内存使用情况?

你可以尝试一些事情:

  1. 使用可能有帮助的List.Clear()方法,因为它消除了列表中的值。但它并没有直接释放分配的内存。这可能会有所帮助,因为垃圾收集可以快速清理列表,虽然我不确定这对你的情况有多大。

  2. 通过调用List = null确保消除对列表的所有引用。然后通过调用GC.Collect()强制垃圾收集器直接收集垃圾。这将占用资源,因为您可能在某个时刻调用收集器可能不太合适,但特别是如果性能不是问题,这不应该造成问题。

  3. 最后,尝试处理每个帧并在处理下一帧之前直接丢弃它。或者尝试批量处理视频(无论什么可能)。这会减轻你的记忆负担。