随着时间的推移使用BlockingCollections,Tasks和OpenCV降低性能

问题描述:

我正在使用Xamarin for Android和OpenCV C#绑定库编写一个简单的光学测量应用程序。随着时间的推移使用BlockingCollections,Tasks和OpenCV降低性能

为了将图像采集卡与处理分离,我创建了一些阻塞集合来传递原始数据,然后在不同线程之间处理图像。我有一个问题,在大约30秒的时间内,GUI显示了精美流畅的处理视频(15s),然后是波涛汹涌的视频(10s),然后是崩溃。

下面的代码显示了集合的定义。 OnCameraFrame(代码的底部)将每个新帧都推送到camframes集合中。在OnCreate中,我运行了一个名为CamProcessor的任务,它接收框架,执行许多操作并将其填充到外框集合中。然后,OnCameraFrame将处理后的帧显示给GUI。为了这篇文章和测试的目的,我已经完全评论了我的所有处理,所以这个问题只是通过将原始数据传递到集合中而存在。

另一个需要注意的是我的收藏似乎运行速度非常快。我从来没有超过1帧,所以这不是一个溢出问题(我认为)。

任何人都可以指出,为什么这个策略运作不好?

BlockingCollection<Mat> camframes = new BlockingCollection<Mat>(10); 
BlockingCollection<Mat> outframes = new BlockingCollection<Mat>(10); 
public CameraBridgeViewBase mOpenCvCameraView { get; private set; } 

    protected override void OnCreate(Bundle savedInstanceState) 
    { 
     //LayoutStuff 

     mOpenCvCameraView = FindViewById<CameraBridgeViewBase>(Resource.Id.squish_cam); 

     Task.Run(() => camProcessor()); 
    } 

    public void camProcessor() 
    { 
     while (!camframes.IsCompleted) 
     { 
      Mat frame = new Mat(); 
      try 
      { 
       frame = camframes.Take(); 
      } 
      catch (InvalidOperationException) { } 

      Mat frameT = frame.T(); 
      Core.Flip(frame.T(), frameT, 1); 
      Imgproc.Resize(frameT, frameT, frame.Size()); 
      outframes.Add(frameT); 
     } 
    } 

    public Mat OnCameraFrame(CameraBridgeViewBase.ICvCameraViewFrame inputFrame) 
    { 
     mRgba = inputFrame.Rgba(); 
     Mat frame = new Mat(); 
     Task.Run(() => camframes.Add(mRgba)); 
     try 
     { 
      frame = outframes.Take(); 
     } 
     catch (InvalidOperationException) { } 

     return frame; 
    } 

查看Android SDK monitor.bat输出后,我发现这是内存泄漏。结果发现它对于Java openCV包装器来说很常见,并且是OpenCV的堆堆比C#所期望的大得多的结果,所以它不会被垃圾收集。

将溶液在每一帧抓取追加这些:

   GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; 
      GC.Collect(); 
      GC.WaitForPendingFinalizers();