2017-04-18 4 views
0

Android用のXamarinとOpenCV C#バインディングライブラリを使用して、簡単な光学測定アプリケーションを作成しています。BlockingCollections、Tasks、およびOpenCVを使用した場合のパフォーマンスの低下

フレームグラバーを処理から分離するために、生の画像を処理して別のスレッド間で処理した画像を渡すためのブロックコレクションを作成しました。私は約30秒の間に、GUIが美しく滑らかに処理されたビデオ(15秒)から、不安定なビデオ(10秒)、次にクラッシュを示す問題があります。

以下のコードは、コレクションの定義を示しています。 OnCameraFrame(コードの一番下)は、新しい各フレームをcamframesコレクションに移動します。 OnCreateでは、私はCamProcessorというタスクを実行します。このタスクはフレームを受け取り、多くのことを行い、それをoutframesコレクションに埋め込みます。 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(); 

ソリューションは、すべてのフレームグラブでこれらを追加しました

関連する問題