AForge相机内存泄漏

时间:2013-04-09 10:53:03

标签: memory-leaks camera aforge

我正在用C#开发一个应用程序,我开发了一个用Aforge个摄像头做一些事情的库。其中一点是简单地捕获Web Cam前面的图像并将其显示在特定的PictureBox上:

camera.NewFrame += NewFrame;

private void NewFrame(object sender, NewFrameEventArgs args)
    {
        Bitmap newFrame = new Bitmap(args.Frame);
        args.Frame.Dispose();
        PictureBox.FromBitmapImage(newFrame);
        newFrame.Dispose();
        newFrame = null;
    }

我在这里做的是,我得到每一帧并将其绘制到PictureBox

我怀疑是:

在某些计算机中,这种绘画方式会产生非常高的内存泄漏。相机配置为: 640x480 ,如果更高,则内存泄漏会增加。

电脑配置:

Intel i5:内存泄漏到500Mb

Intel i7:没有内存泄漏。

Double coeur(不那么强大):没有那么多内存泄漏。

修改

    public static void FromBitmapImage(this Image image, Bitmap bitmap)
    {
        BitmapImage bitmapImage = new BitmapImage();

        using (MemoryStream memoryStream = new MemoryStream())
        {
            bitmap.Save(memoryStream, ImageFormat.Bmp);
            memoryStream.Position = 0;
            bitmapImage.BeginInit();
            bitmapImage.StreamSource = memoryStream;
            bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
            bitmapImage.EndInit();
        }

        image.Source = bitmapImage;
        bitmapImage = null;
    }

我不明白为什么我在某些电脑上有内存泄漏而其他电脑没有...请问有什么建议吗?

注意:内存泄漏只发生在Visual Studio 2010的发布模式下,而不是在调试时发生。

注2:我认为问题来自于FromBimapImage,因为我尝试了WindowsForms应用而不是WPF应用,并且没有内存泄漏。

3 个答案:

答案 0 :(得分:3)

AForge owns图片的字节,您应该制作自己的副本。将帧传递给Bitmap构造函数是不够的。如果框架无法正确处理位图,因为您有对它的引用,则会发生泄漏。

试试这个:

private void NewFrame(object sender, NewFrameEventArgs args)
{
    Bitmap newFrame = AForge.Imaging.Image.Clone(args.Frame);
    PictureBox.FromBitmapImage(newFrame);
    newFrame.Dispose();
}

答案 1 :(得分:3)

这适合我。

        if (pictureBox1.Image != null) {
            pictureBox1.Image.Dispose();
        }
        Bitmap bitmap = eventArgs.Frame.Clone() as Bitmap;
        pictureBox1.Image = bitmap;

答案 2 :(得分:0)

在分配新图片之前处理图片框图像有助于防止内存泄漏,但在调整图片框大小时会出现错误。可能问题是由于过早处理图像。它对我有用的是将旧图像保留在队列中,并以5张图像的延迟处理它们。这将使图片框有足够的时间赶上来。

private Queue<Image> _oldImages = new Queue<Image>();
...

if (pictureBox1.Image != null)
{
  _oldImages.Enqueue(pictureBox1.Image);
  if (_oldImages.Count > 5) 
  {
    var oldest = _oldImages.Dequeue();
    oldest.Dispose();
  }
}