C# 带EmguCV的QueryGrayFrame()上的SystemOutOfMemoryException

C# 带EmguCV的QueryGrayFrame()上的SystemOutOfMemoryException,c#,out-of-memory,emgucv,C#,Out Of Memory,Emgucv,我正在使用此例程将视频的所有帧转换为一组帧: 点击: private int CompareTwoVideos(string _firstVideoPath, string _secondVideoPath) { Capture _capture; List<Image<Gray, Byte>> FirstALLFrames = new List<Image<Gray, Byte>>(

我正在使用此例程将视频的所有帧转换为一组帧:

点击:

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;
        }
private int comparetovideos(string\u firstVideoPath,string\u secondVideoPath)
{
捕获(Capture);;
List FirstALLFrames=新列表();
// ..
_捕获=新捕获(FirstVideoLocation);
//获取所有帧
FirstALLFrames=GetAllFrames(_捕获);
//做一些图像处理
// .. 
_capture.Dispose();
返回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;
}
列出GetAllFrames(捕获)
{
List AllFrames=new List();
int frameScont=0;
尝试
{
FrameScont=(int)_capture.GetCaptureProperty(Emgu.CV.CvEnum.CAP\u PROP.CV\u CAP\u PROP\u FRAME\u COUNT);
对于(int i=0;i
第一次单击时,一切正常

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


有什么想法吗?

我不是100%确定“第二次单击”是什么意思,但我假设这意味着您可以再次直接运行代码来处理另一个视频

看起来你的列表变得太大了,占用了很多内存(这也是写出来的)。您确实处理了捕获对象,但没有处理列表。因此,列表上可能仍然存在引用,这会阻止系统正确地处理和收集该列表(因此,请确保您没有任何其他对该列表的引用)

此外,替换引用(使用
新列表()
实例)不会立即释放收集,垃圾收集器处理对象需要时间。很可能第二次点击只会导致你的程序占用太多内存,因为它现在在内存中包含了太多完整的视频。您是否监控了应用程序内存使用情况

因此,您可以尝试以下几种方法:

  • 使用
    List.Clear()
    方法可能会有所帮助,因为它会消除列表中的值。但它不会直接释放已分配的内存。这可能会有帮助,因为垃圾收集可以快速清理列表,尽管我不确定这对您的情况有多有效

  • 通过调用
    list=null
    确保删除对列表的所有引用。然后通过调用
    GC.collect()
    强制垃圾收集器直接收集垃圾。这将占用资源,因为此时调用收集器可能并不完全合适,但如果性能不是问题,则不应造成问题

  • 最后,尝试处理每一帧,并在处理下一帧之前直接丢弃它。或者尝试分批处理视频(尽可能)。这会减轻你的记忆负担


  • 一旦我将我的行拆分为:
    var frame=capture.QueryGrayFrame();var resized=frame.Resize(ImageWidth、ImageHeight、Emgu.CV.CvEnum.INTER.CV\u INTER\u LINEAR);AllFrames.Add(resized.Copy())
    处理
    调整大小
    在每次迭代中使用它们之后,该函数就像一个魔咒一样工作。谢谢