Kinect & EmguCV & GC

本文关键字:amp GC EmguCV Kinect | 更新日期: 2023-09-27 18:29:01

我想同时使用Kinect和EmguCV。我已经设法从Kinect中获取图像,并创建了一个EmguCV的图像对象。我已经运行了一段时间的应用程序,一段时间后应用程序崩溃,因为内存没有正确释放。

这段小代码从Kinect获取RGB彩色图像,并将其转换为HSV彩色图像。我不知道哪里的记忆没有被释放。我使用了"使用结构",就像我在网上和一些书中读到的例子一样。

我想得到一些关于我在代码中做错了什么的建议,因为我对C#不是很熟悉,而且我在转换图像数据时一定很吃力。我也有兴趣看到其他简单的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;
    }

Kinect & EmguCV & GC

代码中有很多未显示的位图,让我指出它们:

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;
}

可能还有更多的泄漏。基本规则是,创建的每个一次性资源(如位图)(无论如何,所有返回位图的纯函数都会创建它们)都需要在使用完它们后进行处理。

请记住,如果位图当前绑定到某个控件或以其他方式使用,则永远不应处理位图。用新的替换它,然后处理掉旧的。