2017-04-18 44 views
0

我正在使用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; 
    } 

回答

0

查看Android SDK monitor.bat輸出後,我發現這是內存泄漏。結果發現它對於Java openCV包裝器來說很常見,並且是OpenCV的堆堆比C#所期望的大得多的結果,所以它不會被垃圾收集。

將溶液在每一幀抓取追加這些:

   GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; 
      GC.Collect(); 
      GC.WaitForPendingFinalizers(); 
相關問題