Kinect传感器在增强现实中的应用

Kinect传感器不仅在人体动作捕捉方面表现出色,它在识别3D空间中的地面平面方面同样令人惊叹。原生的Kinect SDK为提供了准确识别特定平面是否为地面所需的所有信息。还可以获取诸如Kinect传感器放置高度等信息,甚至可以测量3D空间中某点与地面的距离。所有这些功能对现代增强现实应用有着巨大的影响。

在今天的教程中,将向展示以下内容:

  • 如何检测地面剪辑平面
  • 如何估计Kinect传感器的位置(高度)
  • 如何测量点与地面之间的距离

这是将要开发的一个快照:

先决条件

要运行本文提供的代码和示例,需要以下条件:

  • Kinect for XBOX v2传感器
  • Kinectfor Windows v2 SDK
  • Windows 8.1或更高版本
  • Visual Studio 2013或更高版本
  • 专用USB 3端口

源代码托管在GitHub上。此外,所有这些功能都是Vitruvius的一部分。Vitruvius是最流行的Kinect框架,将帮助轻松创建Kinect应用程序。所以,如果急于开发,只需下载Vitruvius并将其集成到应用程序中。

检测地面剪辑平面

Kinect SDK已经内置了一些地面检测功能。请见FloorClipPlane属性。FloorClipPlane是BodyFrame类的一个成员。很少有人知道它的存在,然而,它是开发运动应用程序时最有用的组件之一。

以下是如何访问FloorClipPlane属性的方法:

using (BodyFrame frame = e.FrameReference.AcquireFrame()) { if (frame != null) { Vector4 floorClipPlane = frame.FloorClipPlane; } }

如所见,FloorClipPlane是一组4个浮点值(Vector4):X、Y、Z和W。X、Y和Z值指示平面在3D空间中的方向。W值指示平面与坐标系原点之间的距离。实际上,Vector4结构表示平面的数学方程。可以在Wolfram MathWorld上阅读更多相关信息。

对于示例,将FloorClipPlane向量封装到一个方便的Floor C#类中:

public class Floor { public float X { get; internal set; } public float Y { get; internal set; } public float Z { get; internal set; } public float W { get; internal set; } public Floor(Vector4 floorClipPlane) { X = floorClipPlane.X; Y = floorClipPlane.Y; Z = floorClipPlane.Z; W = floorClipPlane.W; } }

Kinect传感器高度 - 神奇的W值

正如所看到的,W值指示地面与坐标系原点之间的距离。Kinect坐标系的原点是设备本身!因此,FloorClipPlane的W参数描述了Kinect传感器放置的高度!使用W值,可以向用户提供反馈:

Vector4 floorClipPlane = frame.FloorClipPlane; float height = floorClipPlane.W; if (height < 1f) // 1米 { Debug.WriteLine("The sensor is positioned too low!"); }

当W值为0时,意味着视野受限。这是了解是否有任何物体,如桌子、椅子等阻挡视野的非常简单的方法。

if (height == 0f) { Debug.WriteLine("The field of view is limited."); }

Kinect传感器倾斜角度

除了找到传感器的高度,还可以检测设备的倾斜角度。所需要做的就是使用地面平面的方向:

public double Tilt { get { return Math.Atan(Z / Y) * (180.0 / Math.PI); } }

测量距离

检测到的地面是一个已知距离(W)和方向(X、Y、Z)的平面。3D空间中的点是一组X、Y和Z坐标。

// Plane (X, Y, Z, W) Floor floor = new Floor(frame.FloorClipPlane); // Point (X, Y, Z) CameraSpacePoint point = body.Joints[JointType.WristLeft].Position;

要测量一点与平面之间的距离,需要使用点-平面距离公式:

将如何将这个公式转换为编程代码?让为做数学运算:

public double DistanceFrom(CameraSpacePoint point) { double numerator = X * point.X + Y * point.Y + Z * point.Z + W; double denominator = Math.Sqrt(X * X + Y * Y + Z * Z); return numerator / denominator; }

将此方法添加到Floor.cs类中。就是这样!现在可以得到任何点的3D位置,将其作为参数传递给上述方法,并找到它与地面的距离。

double distance = floor.DistanceFrom(point);

供参考,这是完整的Floor.cs类:

public class Floor { public float X { get; internal set; } public float Y { get; internal set; } public float Z { get; internal set; } public float W { get; internal set; } public Floor(Vector4 floorClipPlane) { X = floorClipPlane.X; Y = floorClipPlane.Y; Z = floorClipPlane.Z; W = floorClipPlane.W; } public float Height { get { return W; } } public double Tilt { get { return Math.Atan(Z / Y) * (180.0 / Math.PI); } } public double DistanceFrom(CameraSpacePoint point) { double numerator = X * point.X + Y * point.Y + Z * point.Z + W; double denominator = Math.Sqrt(X * X + Y * Y + Z * Z); return numerator / denominator; } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485