我刚刚开始使用Kinect v2,我正在运行一些问题。
所以我试图找到彩色图像中物体的x,y,z距离。
我进行了搜索,结果发现我需要使用坐标映射器功能,更具体地说是以下内容:
MapColorFrameToCameraSpace
我不太确定如何使用上述方法。
这是我到目前为止的代码:
public partial class MainWindow : Window, INotifyPropertyChanged
{
/// <summary>
/// Size of the RGB pixel in the bitmap
/// </summary>
private readonly int bytesPerPixel = (PixelFormats.Bgr32.BitsPerPixel + 7) / 8;
/// <summary>
/// Active Kinect sensor
/// </summary>
private KinectSensor kinectSensor = null;
/// <summary>
/// Coordinate mapper to map one type of point to another
/// </summary>
private CoordinateMapper coordinateMapper = null;
/// <summary>
/// Reader for depth/color/body index frames
/// </summary>
private MultiSourceFrameReader multiFrameSourceReader = null;
/// <summary>
/// Bitmap to display
/// </summary>
private WriteableBitmap bitmap = null;
/// <summary>
/// The size in bytes of the bitmap back buffer
/// </summary>
private uint bitmapBackBufferSize = 0;
/// <summary>
/// Intermediate storage for the color to depth mapping
/// </summary>
private DepthSpacePoint[] colorMappedToDepthPoints = null;
/// Intermediate storage for color to camera mapping
///
private CameraSpacePoint[] cameraPoints = null;
/// <summary>
/// Current status text to display
/// </summary>
private string statusText = null;
/// <summary>
/// Initializes a new instance of the MainWindow class.
/// </summary>
public MainWindow()
{
this.kinectSensor = KinectSensor.GetDefault();
this.multiFrameSourceReader = this.kinectSensor.OpenMultiSourceFrameReader(FrameSourceTypes.Depth | FrameSourceTypes.Color);
this.multiFrameSourceReader.MultiSourceFrameArrived += this.Reader_MultiSourceFrameArrived;
this.coordinateMapper = this.kinectSensor.CoordinateMapper;
FrameDescription depthFrameDescription = this.kinectSensor.DepthFrameSource.FrameDescription;
int depthWidth = depthFrameDescription.Width;
int depthHeight = depthFrameDescription.Height;
FrameDescription colorFrameDescription = this.kinectSensor.ColorFrameSource.FrameDescription;
int colorWidth = colorFrameDescription.Width;
int colorHeight = colorFrameDescription.Height;
this.colorMappedToDepthPoints = new DepthSpacePoint[colorWidth * colorHeight];
this.cameraPoints = new CameraSpacePoint[depthWidth * depthHeight];
this.bitmap = new WriteableBitmap(colorWidth, colorHeight, 96.0, 96.0, PixelFormats.Bgra32, null);
// Calculate the WriteableBitmap back buffer size
this.bitmapBackBufferSize = (uint)((this.bitmap.BackBufferStride * (this.bitmap.PixelHeight - 1)) + (this.bitmap.PixelWidth * this.bytesPerPixel));
this.kinectSensor.IsAvailableChanged += this.Sensor_IsAvailableChanged;
this.kinectSensor.Open();
this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText
: Properties.Resources.NoSensorStatusText;
this.DataContext = this;
this.InitializeComponent();
}
/// <summary>
/// INotifyPropertyChangedPropertyChanged event to allow window controls to bind to changeable data
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Gets the bitmap to display
/// </summary>
public ImageSource ImageSource
{
get
{
return this.bitmap;
}
}
/// <summary>
/// Gets or sets the current status text to display
/// </summary>
public string StatusText
{
get
{
return this.statusText;
}
set
{
if (this.statusText != value)
{
this.statusText = value;
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs("StatusText"));
}
}
}
}
/// <summary>
/// Execute shutdown tasks
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void MainWindow_Closing(object sender, CancelEventArgs e)
{
if (this.multiFrameSourceReader != null)
{
// MultiSourceFrameReder is IDisposable
this.multiFrameSourceReader.Dispose();
this.multiFrameSourceReader = null;
}
if (this.kinectSensor != null)
{
this.kinectSensor.Close();
this.kinectSensor = null;
}
}
/// <summary>
/// Handles the user clicking on the screenshot button
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void ScreenshotButton_Click(object sender, RoutedEventArgs e)
{
// Create a render target to which we'll render our composite image
RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)CompositeImage.ActualWidth, (int)CompositeImage.ActualHeight, 96.0, 96.0, PixelFormats.Pbgra32);
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
VisualBrush brush = new VisualBrush(CompositeImage);
dc.DrawRectangle(brush, null, new Rect(new Point(), new Size(CompositeImage.ActualWidth, CompositeImage.ActualHeight)));
}
renderBitmap.Render(dv);
BitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
string time = System.DateTime.Now.ToString("hh'-'mm'-'ss", CultureInfo.CurrentUICulture.DateTimeFormat);
string myPhotos = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
string path = Path.Combine(myPhotos, "KinectScreenshot-CoordinateMapping-" + time + ".png");
// Write the new file to disk
try
{
using (FileStream fs = new FileStream(path, FileMode.Create))
{
encoder.Save(fs);
}
this.StatusText = string.Format(Properties.Resources.SavedScreenshotStatusTextFormat, path);
}
catch (IOException)
{
this.StatusText = string.Format(Properties.Resources.FailedScreenshotStatusTextFormat, path);
}
}
/// <summary>
/// Handles the depth/color/body index frame data arriving from the sensor
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void Reader_MultiSourceFrameArrived(object sender, MultiSourceFrameArrivedEventArgs e)
{
int depthWidth = 0;
int depthHeight = 0;
DepthFrame depthFrame = null;
ColorFrame colorFrame = null;
bool isBitmapLocked = false;
MultiSourceFrame multiSourceFrame = e.FrameReference.AcquireFrame();
// If the Frame has expired by the time we process this event, return.
if (multiSourceFrame == null)
{
return;
}
// We use a try/finally to ensure that we clean up before we exit the function.
// This includes calling Dispose on any Frame objects that we may have and unlocking the bitmap back buffer.
try
{
depthFrame = multiSourceFrame.DepthFrameReference.AcquireFrame();
colorFrame = multiSourceFrame.ColorFrameReference.AcquireFrame();
// If any frame has expired by the time we process this event, return.
// The "finally" statement will Dispose any that are not null.
if ((depthFrame == null) || (colorFrame == null))
{
return;
}
// Process Depth
FrameDescription depthFrameDescription = depthFrame.FrameDescription;
depthWidth = depthFrameDescription.Width;
depthHeight = depthFrameDescription.Height;
// Access the depth frame data directly via LockImageBuffer to avoid making a copy
using (KinectBuffer depthFrameData = depthFrame.LockImageBuffer())
{
this.coordinateMapper.MapColorFrameToCameraSpaceUsingIntPtr(depthFrameData.UnderlyingBuffer,
depthFrameData.Size,
this.cameraPoints);
this.coordinateMapper.MapColorFrameToDepthSpaceUsingIntPtr(
depthFrameData.UnderlyingBuffer,
depthFrameData.Size,
this.colorMappedToDepthPoints);
}
// We're done with the DepthFrame
depthFrame.Dispose();
depthFrame = null;
// Process Color
// Lock the bitmap for writing
this.bitmap.Lock();
isBitmapLocked = true;
colorFrame.CopyConvertedFrameDataToIntPtr(this.bitmap.BackBuffer, this.bitmapBackBufferSize, ColorImageFormat.Bgra);
// We're done with the ColorFrame
colorFrame.Dispose();
colorFrame = null;
for (int y = 0; y < depthHeight; ++y)
{
for (int x = 0; x < depthWidth; ++x)
{
// calculate index into depth array
int depthIndex = (y * depthWidth) + x;
//retrieve the color to space mapping of the current pixel
CameraSpacePoint cameraPoint = this.cameraPoints[depthIndex];
Console.WriteLine(cameraPoint);
}
}
}
finally
{
if (isBitmapLocked)
{
this.bitmap.Unlock();
}
if (depthFrame != null)
{
depthFrame.Dispose();
}
if (colorFrame != null)
{
colorFrame.Dispose();
}
}
}
/// <summary>
/// Handles the event which the sensor becomes unavailable (E.g. paused, closed, unplugged).
/// </summary>
/// <param name="sender">object sending the event</param>
/// <param name="e">event arguments</param>
private void Sensor_IsAvailableChanged(object sender, IsAvailableChangedEventArgs e)
{
this.StatusText = this.kinectSensor.IsAvailable ? Properties.Resources.RunningStatusText
: Properties.Resources.SensorNotAvailableStatusText;
}
}
}
所以我一直在尝试使用SDK中的Kinect坐标映射来解决它,但我没有得到这些值。
我收到以下错误:
未处理的类型&#39; System.ArgumentException&#39;发生在Microsoft.Kinect.dll
其他信息:此API已从HRESULT返回异常:0x80070057
任何帮助都会非常感激。
答案 0 :(得分:1)
如果已安装KinectSDK-v2.0-PublicPreview1407-Setup SDK,请将其卸载并尝试使用新版本KinectSDK-v2.0_1409-Setup here是链接
答案 1 :(得分:1)
this.cameraPoints = new CameraSpacePoint[depthWidth * depthHeight];
问题在于上面的行。它应该改为
this.cameraPoints = new CameraSpacePoint[colorhWidth * colorHeight];