我正在使用Kinect传感器深度数据来创建图像。我想将传感器集成到winforms应用程序中,因此我转换了示例MS应用程序以为Picturebox创建位图。该图像仅用于测试,因此我不关心性能问题。 我遇到的问题是WriteBitmap的返回值无效并导致抛出异常。
是个例外Exception thrown: 'System.ArgumentException' in System.Drawing.dll
代码:
public partial class Results : Form
{
private KinectSensor sensor;
private DepthImagePixel[] depthPixels;
private byte[] colorPixels;
public Results()
{
InitializeComponent();
}
private void Results_Load(object sender, EventArgs e)
{
foreach (var potentialSensor in KinectSensor.KinectSensors)
{
if (potentialSensor.Status == KinectStatus.Connected)
{
this.sensor = potentialSensor;
break;
}
}
if (null != this.sensor)
{
// Turn on the depth stream to receive depth frames
this.sensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
// Allocate space to put the depth pixels we'll receive
this.depthPixels = new DepthImagePixel[this.sensor.DepthStream.FramePixelDataLength];
// Allocate space to put the color pixels we'll create
this.colorPixels = new byte[this.sensor.DepthStream.FramePixelDataLength * sizeof(int)];
this.sensor.DepthFrameReady += this.SensorDepthFrameReady;
// Start the sensor!
try
{
this.sensor.Start();
}
catch (IOException)
{
this.sensor = null;
}
}
if (null == this.sensor)
{
this.statusBarText.Text = "No sensor detected";
}
}
private void Results_FormClosing(object sender, FormClosingEventArgs e)
{
if (null != this.sensor)
{
this.sensor.Stop();
}
}
private void SensorDepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
{
using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
{
if (depthFrame != null)
{
// Copy the pixel data from the image to a temporary array
depthFrame.CopyDepthImagePixelDataTo(this.depthPixels);
// Get the min and max reliable depth for the current frame
int minDepth = depthFrame.MinDepth;
int maxDepth = depthFrame.MaxDepth;
// Convert the depth to RGB
int colorPixelIndex = 0;
for (int i = 0; i < this.depthPixels.Length; ++i)
{
// Get the depth for this pixel
short depth = depthPixels[i].Depth;
// To convert to a byte, we're discarding the most-significant
// rather than least-significant bits.
// We're preserving detail, although the intensity will "wrap."
// Values outside the reliable depth range are mapped to 0 (black).
byte intensity = (byte)(depth >= minDepth && depth <= maxDepth ? depth : 0);
this.colorPixels[colorPixelIndex++] = intensity;
this.colorPixels[colorPixelIndex++] = intensity;
this.colorPixels[colorPixelIndex++] = intensity;
// We're outputting BGR, the last byte in the 32 bits is unused so skip it
++colorPixelIndex;
}
//// Write the pixel data into our bitmap
try {
//// Write the pixel data into our bitmap
if (this.logImage.Image != null) this.logImage.Image.Dispose();
this.logImage.Image = null;
this.logImage.Image = WriteBitmap(this.sensor.DepthStream.FrameWidth, this.sensor.DepthStream.FrameHeight, this.colorPixels);
}catch(Exception ex)
{
Console.Write(ex);
}
}
}
}
Bitmap WriteBitmap(int width, int height, byte[] imageData)
{
using (var stream = new MemoryStream(imageData))
using (var bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppRgb))
{
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0,
width,
height),
ImageLockMode.WriteOnly,
bmp.PixelFormat);
Marshal.Copy(imageData, 0, bmpData.Scan0, imageData.Length);
bmp.UnlockBits(bmpData);
return bmp;
}
}
}
答案 0 :(得分:1)
问题在于,尽管返回了引用,但位图仍在WriteBitmap方法中处理。我原本以为通过返回参考GC无法触摸它。我重新安排了代码,因此创建和赋值都发生在WriteBitmap中。现在它看起来像这个
Bitmap bmp = null;
void WriteBitmap(int width, int height, byte[] imageData)
{
if (this.logImage.Image != null)
{
this.logImage.Image.Dispose();
this.logImage.Image = null;
}
bmp = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format32bppRgb);
try
{
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0,
width,
height),
ImageLockMode.WriteOnly,
bmp.PixelFormat);
Marshal.Copy(imageData, 0, bmpData.Scan0, imageData.Length);
bmp.UnlockBits(bmpData);
this.logImage.Image = bmp;
}
catch (Exception ex)
{
Console.Write(ex);
}
}
它正在发挥作用。