理解Kinect坐标映射






4.78/5 (5投票s)
理解Kinect坐标映射
这是我在收到博客订阅者的一些良好反馈后发布的另一篇文章。 似乎很多人在创建Kinect项目时都有一个共同的问题:他们如何才能正确地将数据投射到颜色和深度流之上。
正如您可能知道的那样,Kinect将一些传感器集成到一个设备中
- 一个RGB彩色摄像头 – 版本1中为640×480,版本2中为1920×1080
- 一个深度传感器 – v1中为320×240,v2中为512×424
- 一个红外传感器 – v2中为512×424
这些传感器具有不同的分辨率,并且没有完美对齐,因此它们的视野区域有所不同。 显而易见的是,例如,RGB摄像头覆盖的区域比深度和红外摄像头更广。 此外,从一个摄像头可见的元素可能从其他摄像头不可见。 这就是不同传感器如何查看相同区域的方式
一个示例
假设我们要在彩色图像之上投射人体关节。 人体跟踪是使用深度传感器执行的,因此身体点的坐标 (X, Y, Z) 仅与深度帧正确对齐。 如果您尝试将相同的身体关节坐标投射到彩色帧之上,您会发现骨骼完全错位
CoordinateMapper (坐标映射器)
当然,微软意识到了这一点,因此SDK附带了一个方便的实用程序,名为 CoordinateMapper
。CoordinateMapper
的工作是识别来自3D空间的一个点是否对应于颜色或深度2D空间中的一个点——反之亦然。 CoordinateMapper
是 KinectSensor
类的属性,因此它与每个 Kinect 传感器实例紧密相关。
使用 CoordinateMapper
让我们回到我们的例子。 这是访问人体关节坐标的 C# 代码
foreach (Joint joint in body.Joints)
{
// 3D coordinates in meters
CameraSpacePoint cameraPoint = joint.Position;
float x = cameraPoint.X;
float y = cameraPoint.Y;
float z = cameraPoint.Z;
}
注意:请参阅我之前的文章(Kinect 版本 2:概述),了解如何找到身体关节。
这些坐标是 3D 点,打包到 CameraSpacePoint
结构中。 每个 CameraSpacePoint
都有 X、Y 和 Z 值。 这些值以 米 为单位测量。
视觉元素的尺寸以像素为单位测量,因此我们需要以某种方式将现实世界的 3D 值转换为 2D 屏幕像素。 Kinect SDK 提供了另外两个用于 2D 点的 struct
:ColorSpacePoint
和 DepthSpacePoint
。
使用 CoordinateMapper
,将 CameraSpacePoint
转换为 ColorSpacePoint
或 DepthSpacePoint
非常容易
ColorSpacePoint colorPoint = _sensor.CoordinateMapper.MapCameraPointToColorSpace(cameraPoint);
DepthSpacePoint depthPoint = _sensor.CoordinateMapper.MapCameraPointToDepthSpace(cameraPoint);
这样,一个 3D 点就被映射到一个 2D 点,因此我们可以将其投射到颜色 (1920×1080) 和深度 (512×424) 位图之上。
如何绘制关节?
您可以使用 Canvas
元素、DrawingImage
对象或您喜欢的任何其他方式绘制关节。
这是您可以在 Canvas
上绘制关节的方式
public void DrawPoint(ColorSpacePoint point)
{
// Create an ellipse.
Ellipse ellipse = new Ellipse
{
Width = 20,
Height = 20,
Fill = Brushes.Red
};
// Position the ellipse according to the point's coordinates.
Canvas.SetLeft(ellipse, point.X - ellipse.Width / 2);
Canvas.SetTop(ellipse, point.Y - ellipse.Height / 2);
// Add the ellipse to the canvas.
canvas.Children.Add(ellipse);
}
类似地,您可以在深度帧之上绘制一个 DepthSpacePoint
。 您还可以在两个点之间绘制骨骼(线条)。 这是完美坐标映射在彩色图像之上的结果
注意:请参阅我之前的文章(Kinect v2 颜色、深度和红外流),了解如何创建相机位图。
从 GitHub 下载源代码并享受
在本教程中,我使用了 Kinect for Windows 版本 2 代码,但是,所有内容也适用于较旧的传感器和 SDK 1.8。 以下是您应该注意的相应类和结构名称。 如您所见,关于所用命名约定有一些小的更改,但核心功能是相同的。
版本 1 | 版本 2 |
SkeletonPoint |
CameraSpacePoint |
ColorImagePoint |
ColorSpacePoint |
DepthImagePoint |
DepthSpacePoint |