App Inventor 2 Posenet人体姿态检测教程

« 返回首页

概述

PoseNet是Google开发的实时人体姿态估计模型,可以检测人体的17个关键点。在App Inventor中通过PoseNet扩展使用。

关键点列表

编号 部位 编号 部位
0 鼻子 9 右手腕
1 左眼 10 左臀
2 右眼 11 右臀
3 左耳 12 左膝
4 右耳 13 右膝
5 左肩 14 左脚踝
6 右肩 15 右脚踝
7 左手肘 16 —
8 右手肘 — —

扩展来源

PoseNet扩展来自MIT App Inventor社区或DeepHost:

  • MIT社区搜索 “PoseNet extension”
  • DeepHost: https://app.deephost.in/

基本用法

界面设计

Screen1
├── 照相机1(或选择图片按钮)
├── 画布1(绘制关键点)
├── 图像1(显示检测结果)
├── PoseNet1(扩展)
├── 按钮_开始检测
└── 标签_结果

检测姿态

when 按钮_开始检测.Click {
  照相机1.TakePicture()
}

when 照相机1.AfterPicture(图片路径) {
  图像1.Picture = 图片路径
  PoseNet1.检测姿态(图片路径)
}

when PoseNet1.检测完成(关键点列表, 置信度) {
  // 关键点列表包含17个点,每个有x, y, score
  标签_结果.Text = "检测到 " + 列表长度(关键点列表) + " 个关键点"
  标签_置信度.Text = "置信度:" + 数学.保留小数(置信度 * 100, 1) + "%"
  
  // 在Canvas上绘制关键点
  画布1.Clear()
  var i = 1
  while i <= 列表长度(关键点列表) {
    var 点 = 列表第i项(关键点列表)
    var x = 点.get("x")
    var y = 点.get("y")
    var score = 点.get("score")
    
    if score > 0.5 {  // 置信度阈值
      画布1.DrawCircle(x, y, 8, color_red)
    }
    var i = i + 1
  }
  
  // 绘制骨骼连线
  绘制骨骼(关键点列表)
}

绘制骨骼连线

procedure 绘制骨骼(关键点列表) {
  // 定义骨骼连接关系 [起点, 终点]
  var 骨骼连接 = [
    [6, 5],   // 左肩-右肩
    [6, 8],   // 右肩-右肘
    [8, 10],  // 右肘-右臀(注:实际是手腕)
    [5, 7],   // 左肩-左肘
    [7, 9],   // 左肘-左手腕
    [6, 12],  // 右肩-右臀
    [5, 11],  // 左肩-左臀
    [12, 14], // 右臀-右膝
    [14, 16], // 右膝-右脚踝
    [11, 13], // 左臀-左膝
    [13, 15]  // 左膝-左脚踝
  ]
  
  var i = 1
  while i <= 列表长度(骨骼连接) {
    var 连接 = 列表第i项(骨骼连接)
    var 起点 = 列表第1项(连接)
    var 终点 = 列表第2项(连接)
    var 点1 = 列表第(起点+1)项(关键点列表)
    var 点2 = 列表第(终点+1)项(关键点列表)
    var s1 = 点1.get("score")
    var s2 = 点2.get("score")
    
    if s1 > 0.5 and s2 > 0.5 {
      画布1.DrawLine(点1.get("x"), 点1.get("y"), 点2.get("x"), 点2.get("y"))
    }
    var i = i + 1
  }
}

实战案例:姿势识别

判断举手

function 是否举手(关键点列表) {
  var 右手腕 = 列表第10项(关键点列表)
  var 右肩 = 列表第6项(关键点列表)
  var 手腕Y = 右手腕.get("y")
  var 肩膀Y = 右肩.get("y")
  
  var 结果 = ""
  // 如果手腕在肩膀上方(Y值更小)
  if 手腕Y < 肩膀Y {
    var 结果 = "右手举起"
  }
  return 结果
}

判断站立/坐着

function 判断姿势(关键点列表) {
  var 左臀 = 列表第12项(关键点列表)
  var 右臀 = 列表第13项(关键点列表)
  var 左膝 = 列表第14项(关键点列表)
  
  var 臀部平均Y = (左臀.get("y") + 右臀.get("y")) / 2
  var 膝盖Y = 左膝.get("y")
  var 膝臀差 = 膝盖Y - 臀部平均Y
  
  var 姿势 = "坐着"
  if 膝臀差 > 50 {
    var 姿势 = "站立"
  }
  return 姿势
}

性能说明

模式 帧率 适用
单张图片检测 1-3秒/张 照片分析
实时视频流 2-5fps 简单交互
降低分辨率 5-10fps 对实时性要求不高

注意:PoseNet在手机端的帧率较低,不适合需要高实时性的应用。

常见问题

Q1: PoseNet检测不到人?

  • 确保图片中人物清晰可见
  • 全身照比半身照检测效果好
  • 光线充足时检测更准确
  • 人物距离适中(不要太远或太近)

Q2: 关键点位置偏移?

PoseNet的坐标基于输入图片尺寸,需要缩放到Canvas的实际尺寸:

global 缩放比X = 画布1.Width / 图片宽度
global 缩放比Y = 画布1.Height / 图片高度
global 实际X = 原始X * 缩放比X
global 实际Y = 原始Y * 缩放比Y

总结

能力 支持
单张图片检测 ✅
实时视频检测 ⚠️ 帧率低
17个关键点 ✅
骨骼绘制 ✅
姿势识别 ✅ 需自己写逻辑
多人检测 部分扩展支持
文档反馈