AI跳舞
先了解你将做出什么
应用介绍
舞蹈看起来很有机、很复杂,但人体动作可以用关键点的位置和距离来描述。本教程使用 PoseNet 把摄像头中的人体转换成骨骼模型,再用坐标关系判断“手举过头顶”“抬膝”“T 形站姿”等动作,并自动累计舞蹈分数。
PoseNet 需要摄像头和手机算力,模拟器不能运行这个扩展。请用真机和 AI2 Companion 测试,并保持光线均匀、背景简单、整个人都在画面中。



设置电脑和手机
- 起始工程:AI跳舞.aia
- 起始工程 Blocks:AI跳舞.asc
- 硬件测试工程:AI跳舞测试.aia
- 测试工程 Blocks:AI跳舞测试.asc
先安装 AI2 Companion,让电脑和手机连接到同一个网络。打开“硬件测试工程”,通过“连接”菜单扫描二维码;如果测试工程没有显示“模型已就绪”或错误信息,请先更换设备,再开始制作完整应用。
AI跳舞教程
1. 认识项目和界面
打开起始工程,先观察它提供的界面和预置组件。你可以调整颜色和布局,但不要重命名组件,因为后续步骤会使用这些名称。

SwapCameraButton 切换前后摄像头,CanvasLiveButton 切换 Canvas 的黑色背景和实时画面,ResetButton 把舞蹈分数归零。WebViewer1 显示摄像头画面,Canvas1 绘制人体骨骼,PosenetExtension1 负责追踪人体关键点。
2. 认识 PoseNet 关键点
PoseNet 会追踪眼睛、耳朵、鼻子、肩膀、手肘、手腕、臀部、膝盖和脚踝。每个能识别到的关键点会返回一个包含 [x, y] 的列表;暂时识别不到时返回空列表。

Canvas 左上角是坐标原点,向右 x 增大,向下 y 增大。因此“手腕在耳朵上方”应比较为 手腕的 y < 耳朵的 y。光线不足、背景凌乱和宽松衣物都可能让某些关键点暂时为空。
3. 检查模型准备状态
起始工程已经提供了界面状态代码。保留 PosenetExtension1.ModelReady 事件,在模型准备好时显示“模型已就绪”;保留 PosenetExtension1.Error 事件,在出错时显示错误信息。
开始追踪前可以让开始按钮保持禁用,收到 ModelReady 后再启用。这样用户不会在扩展尚未加载时触发空数据。

4. 检查预置的界面代码
工程还提供了三个基础事件:ResetButton.被点击时 把舞蹈分数设为 0,SwapCameraButton.被点击时 在前置和后置摄像头之间切换,CanvasLiveButton.被点击时 修改一个布尔变量,用来决定 Canvas 显示实时背景还是纯黑背景。



5. 创建 getX 和 getY 辅助过程
PoseNet 的点是包含两个元素的列表。创建 getX(point) 和 getY(point) 两个过程,分别返回点列表的第 1 项和第 2 项。之后比较坐标时使用过程名,代码会比到处写 选择列表项 更容易阅读。

6. 创建 defined 和 allDefined
创建 defined(point) 布尔过程:当 point 是包含两个元素的列表时返回 true,否则返回 false。
再创建 allDefined(points):遍历一组关键点,只要有一个点未定义就返回 false,全部定义才返回 true。姿态规则在访问坐标前必须先检查关键点,这样模型暂时看不清人时不会因空列表报错。


7. 创建 distance 辅助过程
创建 distance(point1, point2),用勾股定理计算两个点在 Canvas 上的欧氏距离:
距离 = √((x2 - x1)² + (y2 - y1)²)
只有两个点都定义时才计算距离。这个过程之后会用于判断手臂是否伸直,以及 T 形姿势中手腕到肩膀的距离。


8. 创建绘制关键点和骨骼的过程
创建 drawPoint(point),在定义好的点位置画一个半径约 4 像素的小圆;创建 drawLine(point1, point2),在两个定义好的点之间画线。
这两个过程是绘制骨骼的基础:关键点可以用醒目的红色,骨骼可以用另一种颜色,方便观察 PoseNet 的追踪效果。


9. 处理 PoseUpdated 事件
当人体位置发生变化时,PosenetExtension1.PoseUpdated 会触发。起始工程已经准备好事件外壳;其中的条件会根据 CanvasLiveButton 的状态决定是否把摄像头实时画面显示在 Canvas 背景上。
在这个事件中调用 drawKeyPoints、drawBody 和 drawHead。先让事件正常触发,再逐个完成这些过程,排错会更容易。

10. 绘制人体关键点和骨骼
在 drawKeyPoints 中把 Canvas 的 PaintColor 设为醒目的颜色,然后遍历 PosenetExtension1.KeyPoints 列表,对每个定义好的点调用 drawPoint。
在 drawBody 中遍历 PosenetExtension1.Skeleton。列表中的每一项是一根由两个端点组成的骨骼,取出两个端点后调用 drawLine。例如小腿骨骼的两个端点就是脚踝和膝盖。




11. 可选:绘制圆形头部
如果希望骨骼模型有一个圆形头部,可以完成 drawHead:
- 检查
LeftEar和RightEar都已定义。 - 用两只耳朵的中点作为圆心,使用中点公式计算圆心。
- 用两耳之间距离的一半作为半径,让圆经过两只耳朵。
如果只画耳朵、眼睛和鼻子的关键点而不画圆形头部,程序仍然可以正常工作。



12. 第一次测试应用
用 AI2 Companion 在真机上测试:确认人体关键点能出现,骨骼线段能连接正确,Canvas 和 WebViewer 的宽高完全一致。
手机屏幕较小时,可以滚动屏幕;也可以隐藏显示舞者图片的 HorizontalArrangement1。如果隐藏 WebViewer1,仍必须让 Canvas1 保持和 WebViewer 原来相同的尺寸,否则坐标会错位。
13. 认识待检测的舞步
本教程用四类动作练习规则:双手举过头顶、抬膝、特拉沃尔塔式动作和 T 形姿势。每个动作都可以拆成“关键点定义检查 + 坐标或距离比较 + 得分”的流程。




14. 检测双手举起
创建 checkForHandsintheAirMove:
- 检查左右手腕和左右耳都已定义。
- 比较右手腕 y 与右耳 y、左手腕 y 与左耳 y。
- 两只手腕都在各自耳朵上方时,增加舞蹈分数。
由于 y 越小表示位置越高,所以判断条件是两个手腕的 y 坐标分别小于对应耳朵的 y 坐标。


15. 检测抬膝
创建 checkForKneeUpMove:
- 检查左右膝和左右臀都已定义。
- 判断右膝是否高于右臀,或左膝是否高于左臀。
- 任意一侧满足条件时增加舞蹈分数。


16. 检测 Travolta 动作
自己尝试创建 checkForTravoltaMove:右手腕高于右耳且左手腕低于左肩,或左手腕高于左耳且右手腕低于右肩。任意一种姿势成立时就增加分数。
先写出判断条件,再用 allDefined 确认需要的手腕、耳朵和肩膀都存在。不要在关键点为空时直接比较坐标。

17. 检测 T 形姿势
T 形姿势要求左右手臂水平伸展,身体看起来像字母 T。可以从下面两类条件入手:
- 左右手腕和肩膀的 y 坐标要足够接近,保证手臂大致水平。
- 手腕到肩膀的直线距离要接近“手腕到手肘距离 + 手肘到肩膀距离”,保证手臂大致伸直。
使用 distance 计算这些长度,并为“足够接近”设置合理误差,不要要求浮点数完全相等。


18. 再次测试并观察得分
分别测试四种舞步,确认每个动作只有在条件满足时增加舞蹈分数。保持动作不动时,如果分数持续快速增加,说明程序需要增加“上一帧未达成、这一帧达成”的边沿判断,让同一个动作只奖励一次。
最佳测试条件是光线均匀、背景单色、衣服贴身,并让整个人保持在摄像头范围内。也可以用背景清楚的独舞视频测试 PoseNet 对画面中舞者的追踪效果。

扩展应用
- 为每个舞步增加去重机制,动作保持时只奖励一次,检测到新动作后才允许再次得分。
- 为动作不标准的情况设计扣分规则,例如手臂接近 T 形姿势但没有保持水平。
- 把舞步换成瑜伽姿势,正确姿势加分,偏离姿势时给出提示。
- 在不改变关键点安全检查的前提下,设计并实现更多可以用坐标和距离描述的动作。
卡在哪一步?直接查操作
不用退出当前教程。速查会在新页面打开,查完回来继续刚才的进度。