随着时间的推移使用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();