使用Kinect跟踪举重杆

在健身领域,跟踪举重杆的位置对于监测锻炼进度至关重要。今天,将向展示如何使用Kinect传感器来识别举重杆,并计算它与地面的距离。这样,就可以日复一日地跟踪进步,并检查性能如何。这是一个将在完成本教程后实现的视频示例——请记住,是一名工程师,而不是健身教练!

很酷,对吧?让看看如何在代码中实现它…

先决条件

要开始这个项目,需要以下条件:

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

视频和源代码

像往常一样,为提供了完整的源代码以及演示视频。

  • 观看视频(并确保订阅)
  • 下载源代码

举重杆检测算法

算法的核心是BarDetectionEngine类。这个类封装了下面将要介绍的所有细节。不会展示完整的源代码,因为它超过500行C#代码。将解释代码背后的思考过程和逻辑。

传统的对象跟踪是通过处理RGB彩色图像来完成的。Kinect提供了一种令人难以置信的方式来理解环境。这种手段被称为“深度处理器”。使用其激光传感器,Kinect可以为提供512×424点的点云,以及每个点与传感器平面之间的水平距离。

深度数组中的每个点只是一个原始距离值(以毫米为单位)。要跟踪杆,需要检测与手有相似距离的点。以下是如何访问深度数组的方法:

using ( var depthFrame = frame.DepthFrameReference.AcquireFrame()) { if (depthFrame != null) { depthFrame.CopyFrameDataToArray(_depthData); } }

Kinect SDK为提供了一个方便的帧源:BodyIndex。BodyIndexFrames指定了上述深度点中哪些属于人体!结合Depth和BodyIndex帧,可以提取每个属于人的距离。

using ( var bodyIndexFrame = frame.BodyIndexFrameReference.AcquireFrame()) { if (bodyIndexFrame != null) { bodyIndexFrame.CopyFrameDataToArray(_bodyIndexData); } }

检测玩家手的位置也很简单。如果想了解如何使用Kinect进行关节跟踪,请参考前一个教程。

var handLeft = body.Joints[JointType.HandLeft].Position; var handRight = body.Joints[JointType.HandRight].Position;

现在,已经知道了手在3D空间中的位置(X, Y, Z)。也知道视野中每个点的Z距离!由于举重杆是由手抓住的,它的点会靠近手点。因此,将遍历深度数组,找到那些具有相似Z距离的点。

ushort depth = depthData[depthIndex];

尽管上述代码应该有效,但有一个主要问题:当杆非常靠近身体时,算法会挑选属于胸部、臀部或肩膀的深度点!显然,这些点不属于杆。这正是需要身体索引帧的原因!身体索引帧确定特定点是否属于身体。因此,可以排除属于身体的点,保留其余的点。这就是实现这一功能的代码:

if (bodyIndexData[depthIndex] != 0xff) { // 这个点不属于玩家。 }

可选地,可以平滑值并指定最小/最大距离或杆旋转。在代码中,设置了一个25度的杆旋转阈值。

查看完整的BarDetectionEngine.cs文件。

由于有了属于杆的深度点,现在可以通过取最左边和最右边的点来计算它的长度。也可以找到这些点在2D颜色空间中的坐标。

就是这样,伙计们。可以探索源代码,看看是如何可视化杆并测量各种其他属性的。本教程的目的是展示使用KinectSDK v2处理原始深度帧的强大功能。

使用BarDetectionEngine

上述所有功能都封装在单个类中——BarDetectionEngine。可以按照以下方式使用BarDetectionEngine:

// 1) 初始化 var barDetectionEngine = new BarDetectionEngine(sensor.CoordinateMapper, colorWidth, colorHeight, depthWidth, depthHeight); barDetectionEngine.BarDetected += BarDetectionEngine_BarDetected; // 2) 更新 barDetectionEngine.Update(depthData, bodyIndexData, body); // 3) 事件处理 private void BarDetectionEngine_BarDetected(object sender, BarDetectionResult e) { if (e != null) { var center = e.Trail; var height = e.BarHeight; var length = e.barLength; var left = e.Minimum; var right = e.maximum; } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485