我正在使用Xamarin for Android和OpenCV C#绑定库编写一个简单的光学测量应用程序。
为了将帧抓取器与处理分开,我创建了一些阻塞集合来传递raw,然后处理不同线程之间的图像。我有一个问题,在大约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 :(得分:0)
在查看Android SDK monitor.bat输出后,我发现这是一个内存泄漏。事实证明它是Java openCV包装器的常见问题,并且是OpenCV的mat堆远大于C#所期望的结果,因此它不会被垃圾收集。
解决方案是在每个帧抓取时附加这些:
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();
GC.WaitForPendingFinalizers();