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;
}
代码中有很多未显示的位图,让我指出它们:
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;
}
可能还有更多的泄漏。基本规则是,创建的每个一次性资源(如位图)(无论如何,所有返回位图的纯函数都会创建它们)都需要在使用完它们后进行处理。
请记住,如果位图当前绑定到某个控件或以其他方式使用,则永远不应处理位图。用新的替换它,然后处理掉旧的。