Kinect& EmguCV& GC

时间:2012-03-26 21:41:06

标签: c# garbage-collection kinect emgucv

我想一起使用Kinect和EmguCV。我设法从Kinect获取图像并创建一个EmguCV的Image对象。我运行应用程序片刻,应用程序在一段时间后崩溃,因为内存未正确释放。

这段小代码从Kinect获取RGB彩色图像并将其转换为HSV彩色图像。我无法解决内存未发布的问题。我已经使用过"使用结构"就像我在互联网和某本书中读过的例子一样。

我希望得到一些关于我在代码中做错的建议,因为我不熟悉C#,我必须拉动我的腿转换图像数据。我也有兴趣看到其他-simple- Kinect + EmguCV项目,如果你推荐任何项目,我将非常感激。

提前致谢。

这是代码:

    private void showHSV(Bitmap bmp)
    {
        Image<Bgr, byte> img = new Image<Bgr, byte>(bmp);
        Image<Hsv, byte> imgHsv = img.Convert<Hsv, byte>();

        Bitmap bmp2 = imgHsv.ToBitmap();

        image2.Source = sourceFromBitmap(bmp2);
    }


    private BitmapSource sourceFromBitmap(Bitmap bmp)
    {
        BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
            bmp.GetHbitmap(),
            IntPtr.Zero,
            System.Windows.Int32Rect.Empty,
            BitmapSizeOptions.FromWidthAndHeight(bmp.Width, bmp.Height));

        return bs;
    }

    private void ColorImageReady(object sender, ColorImageFrameReadyEventArgs e)
    {
        using (ColorImageFrame imageFrame = e.OpenColorImageFrame())
        {
            if (imageFrame != null)
            {   
                byte[] pixelData = new byte[imageFrame.PixelDataLength];
                imageFrame.CopyPixelDataTo(pixelData);

                BitmapSource bmp = BitmapImage.Create(imageFrame.Width, imageFrame.Height, 96, 96, PixelFormats.Bgr32, null,
                    pixelData, imageFrame.Width * imageFrame.BytesPerPixel);

                image1.Source = bmp;

                showHSV(bitmapFromSource(bmp));
            }
            else
            {
                // imageFrame is null because the request did not arrive in time          }
            }
        }
    }

    private System.Drawing.Bitmap bitmapFromSource(BitmapSource bitmapsource)
    {
        System.Drawing.Bitmap bitmap;

        using (System.IO.MemoryStream outStream = new System.IO.MemoryStream())
        {
            BitmapEncoder enc = new BmpBitmapEncoder();
            enc.Frames.Add(BitmapFrame.Create(bitmapsource));
            enc.Save(outStream);
            bitmap = new System.Drawing.Bitmap(outStream);   
        }
        return bitmap;
    }

1 个答案:

答案 0 :(得分:0)

代码中有很多无用的位图,让我指出它们:

private void showHSV(Bitmap bmp)
{
    Image<Bgr, byte> img = new Image<Bgr, byte>(bmp); // Not sure what Image<,> is, but I guess it needs disposing at some point
    Image<Hsv, byte> imgHsv = img.Convert<Hsv, byte>(); // same here

    Bitmap bmp2 = imgHsv.ToBitmap(); // bmp2 is never disposed in your code
    var oldBmp = image2.Source;
    image2.Source = sourceFromBitmap(bmp2);
    oldBmp.Dispose() // try this
}


private BitmapSource sourceFromBitmap(Bitmap bmp)
{
    BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
        bmp.GetHbitmap(),
        IntPtr.Zero,
        System.Windows.Int32Rect.Empty,
        BitmapSizeOptions.FromWidthAndHeight(bmp.Width, bmp.Height));

    return bs;
}

private void ColorImageReady(object sender, ColorImageFrameReadyEventArgs e)
{
    using (ColorImageFrame imageFrame = e.OpenColorImageFrame())
    {
        if (imageFrame != null)
        {   
            byte[] pixelData = new byte[imageFrame.PixelDataLength];
            imageFrame.CopyPixelDataTo(pixelData);

            BitmapSource bmp = BitmapImage.Create(imageFrame.Width, imageFrame.Height, 96, 96, PixelFormats.Bgr32, null,
                pixelData, imageFrame.Width * imageFrame.BytesPerPixel); // bmp never disposed

            var oldBmp = image1.Source;
            image1.Source = bmp;
            oldBmp.Dispose(); // try so

            showHSV(bitmapFromSource(bmp)); // what happens inside? bmp needs to be disposed at some point...
        }
        else
        {
            // imageFrame is null because the request did not arrive in time          }
        }
    }
}

private System.Drawing.Bitmap bitmapFromSource(BitmapSource bitmapsource)
{
    System.Drawing.Bitmap bitmap;

    using (System.IO.MemoryStream outStream = new System.IO.MemoryStream())
    {
        BitmapEncoder enc = new BmpBitmapEncoder();
        enc.Frames.Add(BitmapFrame.Create(bitmapsource));
        enc.Save(outStream);
        bitmap = new System.Drawing.Bitmap(outStream);
    }
    return bitmap;
}

可能有更多泄漏。基本规则是,每个可处理资源(如Bitmap)创建(通过任何方式,所有返回Bitmaps的纯函数创建它们)都需要在完成后处理。

请记住,如果Bitmap当前绑定到某个Control或者以其他方式使用,则不应该丢弃它。用新的替换它,然后处理旧的。