核心课程 / 视觉入门课 / EXP-09
EXP-09 · 第 5 阶段 · 人体感知 · 验证性 · 4 学时

骨骼关键点 33 点:把人压成一根能算的火柴人

上一页把脸拆成 468 个点,这一页把整个人拆成 33 个点。它的意义不在「画得好看」,而在于:判断「他在举手」这件事,从此变成比较两个 y 坐标的大小——不需要认出是谁、不需要看清衣服、也不需要语义模型。

难度 ⭐⭐ · 4 学时 BlazePose 33 点35 条拓扑边 可见度 vis动作判定素材
01 颜色02 轮廓03 二维码04 检测05 分类06 分割07 跟踪08 人脸09 骨骼10 3D11 体感12 手势

01目标:33 点 35 线,一根火柴人跟着人动

🎯 实验目标 · 学完你将能
  • 说清关键点为什么比「检测框」更有用:框回答「人在哪」,点回答「他手举到哪了」,而动作判定只需要比坐标
  • 跑通单图与实时两条命令,看到左栏叠骨架、右栏黑底火柴人,状态栏打 Pose: OK
  • 调出骨架的两种坏相:可见度门限抬高 → 手脚断线;人站太远 → 整帧不画
⚠️ 重点与难点 重点:四步链路 —— 缩到 256、一次吐出 33 组坐标、按 vis 筛、按 35 条边连线。
难点:直觉是「33 点就是模型的 33 个输出」,实际是一个 195 维向量里塞了 39 个槽位(33 姿态点 + 6 个附加点),每槽 5 个数(x, y, z, vis, presence)—— 取错了会整体错位。
INPUT · 你给它
images/pose_demo.jpg

一张全身照(举手姿势)。也可以换 --ros 的相机画面。

→
OUTPUT · 你拿到
33 组 (x, y, vis)

双栏图:左 = 原图叠骨架,右 = 黑底红点绿线火柴人,状态栏 Pose: OK。

本实验的目标:人一动,33 个点跟着动;而「他举手了」这句话,可以直接由两个点的 y 坐标比出来。

02问题:判断「举手」不需要看清这个人是谁

隔空控制有一类做法很朴素:手举过肩就算「举手」。它不需要知道你是谁、穿什么、脸朝哪,只要知道手腕和肩膀哪个更高。

这件事用人脸、用检测框都做不到:框只能告诉你「人在这个矩形里」,举手与放下时框几乎一样大。**要把人变成一组可比较的数字**,才谈得上判定动作。

照片:一眼看懂,但没法算 「举手了」是人的判断,不是数 ? 关键点:能直接比大小 腕 y=62 < 肩 y=86 → 举手
图 2-1|同一个姿势的两种表示。右边的判定只用一次比较:手腕的 y 比肩膀的 y 小(画面坐标越小越靠上),就是举手。
对比平时你看到的(黑盒)机器必须做的(白盒)
他手举起来没有一眼就看出来? —— 得先知道手腕和肩膀各在哪
挡住腿还画得出吗看不出来,正常照片没有这个视角? —— 每个点自带「可见度」,低的点不画
人站远了你照样看得见? —— 人占的像素太少,整帧可能都不给点

三个问号拆成三个具体问题:

① 33 个点是模型直接输出的吗?

② 拿到点之后,怎么变成「举手 / 下蹲」这样的结论?

③ 为什么有人画得全、有人只有半截骨架?

照片是给人看的,关键点是给程序算的。33 个点的价值 = 把「动作」翻译成「坐标比较」。

03现象:左栏叠骨架,右栏黑底火柴人

🎬 现象速览 · 30 秒先看效果

你会看到:一张双栏图。左栏把人像叠上骨架(看得清「点对不对得上人」),右栏把背景压黑只留火柴人(看得清「结构对不对」)。底部 FPS: 0 Pose: OK。画面里的人举着右手 —— 右栏那根线就跟着扬起来。

输入照片:一个人举起右手站立
① 输入 images/pose_demo.jpg
运行结果双栏图:左栏人像叠骨架,右栏黑底红点绿线火柴人,底部 FPS: 0 Pose: OK
② 输出:左人右火柴人,Pose: OK

怎么跑出来:进项目根,把包目录加进 PYTHONPATH,用模块方式跑单图。

cd ~/ros2_ws/src/xflz_eai_car1/vision/10_pose_landmark
export PYTHONPATH=$PWD/car1_pose_landmark
python -m pose_landmark_core.demo_image --config config/pose_config.yaml --save out.jpg
W rknn-toolkit-lite2 version: 2.3.2 ← 单图模式不打印统计行;判据是 out.jpg 的状态栏 ← 打开 out.jpg:左栏骨架贴在人上,右栏火柴人,底部 Pose: OK

🔍 看什么:三处,后面都要用。

  • 点落在关节上,不在轮廓上 —— 肩、肘、腕、髋、膝、踝,这些是转动副,正是判动作需要的位置。
  • 线只有 35 条 —— 33 个点两两连起来有 528 对,实际只连「骨架该有的那段」,官方拓扑就是 35 条边。
  • 右栏背景是黑的 —— 只留点和线,方便看结构;这是绘制层的处理,不是模型输出的「黑背景」。

这就是本实验最终要呈现的现象。先照做;第 05 节补上实时相机与「站远 / 半身」两种边界。

04原理:四步:缩到 256、一次吐 33 点、按可见度筛、连成 35 条线

CORE IDEA · 一句话原理

把人缩到 256 见方喂进去,模型一次吐出 33 组坐标;每个点自带一个「我可见吗」的分数,低的就不画;最后按官方拓扑的 35 条边把留下的点连起来。

打个比方:像给木偶拍照后量关节 —— 只在照片上标出关节位置,再按「哪些关节之间本来就有骨头」连线。 揭个盖:木偶缺了个零件(被挡住),你不会硬画一根骨头过去 —— 模型也一样:两端都够可信才连线,这就是骨架「断」而不是「歪」的原因。

四步回答第 02 节的三问:① 33 点怎么来 → 步骤 2;② 怎么变成动作结论 → 步骤 3 与 4;③ 为什么有人只有半截骨架 → 步骤 3 的 vis。

① 缩到 256 见方 resize_pad(256) 等比缩放 + 黑边 记下 scale / pad 供反算 ② 一次吐出 195 个数 x y z vis p | x y z vis p | … 39 个槽位 x 5 个数 前 33 个是姿态点 后 6 个是附加点 195 = 39 x 5 另有 117 维三维世界坐标 本页只用前 33 组屏幕坐标 ③ 解码成 33 点 + 可见度 decode_pose 归一化 x/y 反算成像素 右下那个点 vis 偏低,淡了 ④ 按 35 条边连线 POSE_CONNECTIONS 两端都够可信才画线 所以骨架会「断」,不会「歪」 33 个点两两连线有 528 对,实际只用官方拓扑的 35 条 —— 只连「本来就该有骨头」的地方 模型只跑一次:不裁片、不分级,因为它是「全身一起看」的 这是与 EXP-08 最大的不同:人脸要裁,人体不裁
图 4-1|四步链路。与 EXP-08 对比着看:人脸是「先找脸再裁片」,人体是「整帧缩到 256 一次出完」。

1为什么整帧缩到 256 就够,不用裁?

吃什么:整帧图。做什么:等比缩放并补黑边到 256×256,同时记住缩放比与补边量。吐什么:一张方形输入 + 一组反算参数。

人脸要裁,是因为脸太小;人体本来就占画面一大块,整帧缩到 256 之后人还占几十到上百像素,够模型看清关节。所以省掉了 ROI 那一步 —— 代价是「离得远的小人」会变得看不清(第 02 节第三问)。

动它会怎样:没有可调参数,但 resize_pad 记下的 scale/pad 必须一路传到步骤 3 反算,漏了坐标就整体偏。

233 个点是怎么塞进一个向量的?

这是本页最反直觉的一点,也是「为什么取错了会整体错位」的答案:

  • 模型输出第一路是 195 个数,不是 33×4=132。
  • 它其实是 39 个槽位 × 5 个数:x, y, z, vis, presence 交错排列。
  • 这 39 个槽位里,前 33 个才是姿态点,后 6 个是模型内部的附加点(不做可视化)。
  • 所以解码时要按「每 5 个取一组、只取前 33 组」来切 —— 直接 reshape(33, 4) 会整体错位。

另外还有一路 117 维的三维世界坐标(39×3),本实验不用它:做机器人控制只需要「画面里的位置」,不需要真实世界尺度。

动它会怎样:没有旋钮。但换模型版本时形状会变,解码必须跟着改 —— 源码注释里就专门写了这条。

3它凭什么知道哪个点「看不见」?

每个槽位自带 vis(可见度)和 presence,都是 logit,要过 sigmoid 才是 0~1 的分数。它们管两件不同的事:

  • vis:这个关节看得见吗。人站在桌子后面、腿被挡住时,膝、踝的 vis 会明显偏低。绘制时低于门限的点就不画。
  • presence:整帧里到底有没有人。它和检测分数一样,用 min_detection_confidence(默认 0.5)卡门限;不过门限就整帧不给点。

这就是第 02 节第三问的答案:骨架「断」不是 bug,是 vis 在告诉你「这段我猜的,别用」。

动它会怎样:绘制门限抬高 → 骨架越来越残缺;降低 → 会出现「凭空的线」(把两个都不确定的点连起来),看着像乱飞。

433 个点怎么变成「举手 / 下蹲」?

这是第 02 节第二问的答案,也是本页最实用的收获:动作判定只是一次坐标比较。

  • 举手:手腕的 y 比同侧肩膀的 y 小(画面坐标越小越靠上)。
  • 下蹲:髋部的 y 超过画面高度的某个比例(人整体压低了)。
  • 抬手多少度:肘关节用三点夹角算(肩-肘-腕)。

注意所有比较都要先归一化(除以画面宽高),否则换个大屏、人走近一点,同一条阈值就失效了 —— 这正是 EXP-11 要处理的第一件事。

动它会怎样:这一步在 EXP-11 里才会出现阈值(0.72 与 0.08);本页只到「点在哪」。

现在回看第 03 节第 ② 张图:右栏那根淡掉的线不是画错了 —— 是那一端的 vis 没过门限,程序主动没连。

先认识 5 个词

关键点 landmark

人体上可定位的关节点,每个是一组 (x, y, vis)。什么时候失效:人被大面积遮挡时,被挡的点只能靠「猜」。

可见度 vis

这个点「有没有看到」的分数(logit 转概率)。什么时候失效:宽松衣服、深色背景会让分数整体偏低。

presence

整帧「有没有人」的判断,与检测分数同源。什么时候失效:只露一条腿、画面里几乎没人时直接掉下门限。

拓扑 POSE_CONNECTIONS

官方定义的 35 条骨架边,规定哪些点之间连线。什么时候失效:换成手部/面部模型时索引完全不同,不能混用。

归一化坐标

点位置除以画面宽高,变成 0~1 的比例。什么时候失效:画面被裁切或缩放后没同步更新比例,判定会整体偏移。

什么时候会翻车:五个真实边界选读 1 分钟
  • 只露上半身 —— 下半身点位全部低可见度,骨架只剩上半截。做「下蹲」判定会永远判不出来。
  • 人站太远 —— 人体占的像素太少,presence 掉下 0.5,整帧不给点。退后一步就是「没反应」。
  • 宽松长裙 / 大衣 —— 髋、膝位置被布料盖住,模型按轮廓外推,蹲下时误差最大。
  • 侧身对着镜头 —— 左右肩重叠,两点几乎重合,靠「左右手」区分动作的逻辑会失效。
  • 两人入镜 —— 本模型只给一个人(取分最高的),第二个人会被静默忽略;要多人得跑多实例或先用人检测裁片。
步数据变成什么为什么非它不可 / 少了会怎样谁在干动参数会怎样
1整帧 → 256×256 + scale/pad模型只认死尺寸;不记参数就无法反算resize_pad无参数
2图 → 195 个数(39×5)+ 117 维世界坐标模型本体;取错槽位就整体错位模型前向min_detection_confidence 卡 presence
3195 → 33 组 (x, y, z, vis) 像素坐标不按 5 个一组切,坐标全乱decode_pose无参数;vis 供绘制筛点
433 点 → 点 + 35 条线不筛直接连,会画出「凭空的骨头」POSE_CONNECTIONS + view绘制门限↑ 骨架残缺;↓ 出现乱线

这张表只看第 2、5 两列就够:第 2 列是形态,第 5 列是旋钮。函数名在第四列。

05实操:单图 / 实时 / 站远与半身三条命令

先看「敲的命令」与「原理第几步」怎么对上号。

环节函数(文件)吃哪个参数对应原理第几步
取图 / 取流cv2.imread / Ros2Camera(demo_image.py / camera_demo.py)source.mode --ros链外
缩放补边resize_pad / prepare(pose.py:43 / :87)(无)步骤 1
推理模型前向(engine.py)min_detection_confidence步骤 2
解码decode_pose(pose.py:56)(无)步骤 3
绘制view.draw + POSE_CONNECTIONS绘制门限步骤 4
推流MjpegServer.set_frameserver.port stream_name链外
  1. 单图跑通,确认「点贴在人上」约 3 分钟

    命令见第 03 节。跑完打开 out.jpg,按下面三行判断对错:

    左栏:骨架关节落在肩/肘/腕/髋/膝/踝上 右栏:火柴人结构与姿势一致(右手是抬起的) 底部:FPS: 0 Pose: OK

    这一步别急着走:右栏那根「扬起来的线」就是后面判「举手」的全部依据。

  2. 实时相机:看它跟不跟得住约 5 分钟

    实时模式走 MJPEG,端口 8082(pose.mjpg)。先起驱动再跑程序,两个终端 ROS_DOMAIN_ID 一致(N 取 0~101,各设备不同)。

    终端一 · 起相机驱动

    source /opt/ros/humble/setup.bash && source ~/ros2_ws/install/setup.bash
    export ROS_DOMAIN_ID=N
    ros2 launch ascamera hp60c.launch.py
    日志持续滚动,无 ERROR

    终端二 · 跑骨骼关键点

    source /opt/ros/humble/setup.bash && source ~/ros2_ws/install/setup.bash
    export ROS_DOMAIN_ID=N
    cd ~/ros2_ws/src/xflz_eai_car1/vision/10_pose_landmark
    export PYTHONPATH=$PWD/car1_pose_landmark
    python -m pose_landmark_core.camera_demo --config config/pose_config.yaml --ros --port 8082
    [camera_demo] MJPEG on http://<板IP>:8082/pose.mjpg ← 浏览器打开,举手/下蹲试着看骨架跟不跟
  3. 故意让它失败两次约 6 分钟

    第一次:站远三步,让整个人只占画面一小块 —— 骨架要么整体消失(presence 掉门限),要么点位乱跳。

    第二次:只露出上半身(蹲到桌子后面)—— 下肢的点会掉到低可见度,骨架只剩上半截。这两次失败比成功更有价值:它们定义了这套方案的适用边界。

    把 min_detection_confidence 从 0.5 降到 0.3 再试一次远距离 —— 能画出点,但会抖。这就是「门限换召回,抖动换稳定」。

🔁 现象呼应这三步跑完出现的画面,就是第 03 节那张双栏图:左人叠骨架、右火柴人、底部 Pose: OK。两处对上了,说明缩放、推理、解码、绘制四段你已完整走通。

你该看到的画面

正常
全身骨架

33 点、35 线齐全,关节落在肩肘腕髋膝踝上。

只露上半身
骨架断在腰

下肢 vis 低,连线自动省略 —— 不是画错,是「不敢连」。

站太远
整帧空白

presence 掉下 0.5,程序认为画面里没有人。

异常 · Pose: NO
一个点都没有

先靠近、再看光线;或把门限降到 0.3 试一次。

踩坑速查

现象原因怎么办
报 ModuleNotFoundError: pose_landmark_core没加 PYTHONPATHexport PYTHONPATH=$PWD/car1_pose_landmark,用 -m 跑
点位整体偏到一边scale/pad 没传到反算,或画面被裁过检查解码用的缩放参数;不要手动裁帧后再喂模型
只画出半截骨架下肢被挡 / 出画,vis 低退到全身入镜;或接受「只用上半身判定」
骨架抖动厉害人太远、光不足,点位噪声大靠近镜头;必要时对点位做几帧平滑
状态栏 Pose: NOpresence 低于 0.5靠近、露全身;或把 min_detection_confidence 降到 0.3
--ros 报 cannot open ros topic驱动没起 / ROS_DOMAIN_ID 不一致 / 话题被 remap先起 ascamera;两终端 export 同一个 N;别改话题名
进阶 1 · 用三点夹角算「抬手多少度」约 20 分钟

取肩-肘-腕三个点,用余弦定理算夹角。手臂垂下时约 170°,举平约 90°,举过头顶会小于 60°。

比「比 y 大小」更细腻:可以做「抬到一半停住」「挥手」这类连续量判定,也是 EXP-12 手势识别的同一套数学。

进阶 2 · 把点位画成一条「运动轨迹」约 25 分钟

把最近 30 帧的右手腕坐标钉在画面上,连成一条线 —— 挥手、画圈这些动作会立刻显现出形状。

这是「时序特征」的起点:单帧只能判姿态,多帧才能判动作,EXP-11 的动作分类就建立在这个思路上。

🧪 Vibe Coding · 自己把这段代码读明白约 20 分钟

你要产出三样:模块职责表 → 控制流流程图 → 时序图。与真源码逐条对照。

提示词 1 · 模块职责分析

请阅读这个骨骼关键点项目的模块:pose_landmark_core/pose.py、engine.py、config.py、view.py、demo_image.py。
它们共同完成「读一张图 → 输出 33 个关键点 → 画骨架」。
请输出一张表,每行一个模块,四列:模块名 / 一句话职责 / 被谁调用 / 从哪个配置项取值。
关键函数标行号;不确定的地方请明说。

提示词 2 · 控制流流程图

请为 pose.py 的 decode_pose 画一张流程图。
必须说清:模型的 195 维输出如何按「每 5 个数一组」拆成 39 个槽位、只取前 33 个;归一化 x/y 如何按 scale 与 pad 反算成原图像素;vis 与 presence 各自用在哪一步。
框里写函数名或变量名,不要写「处理数据」这类空词。

提示词 3 · 时序图

请为实时模式画一张时序图,参与者用真实名字:ros2_camera 节点、Ros2Camera 回调、PoseEngine、view.draw、MjpegServer。
按顺序标出:话题帧到达、缩放补边、模型推理、解码、绘制、推流。
并说明这条链路里只有一次模型推理,没有 ROI 裁剪,所以比人脸关键点那条链更短。

自查三问:能指出 195 = 39×5 在代码里的位置?能说清 scale/pad 在解码里怎么用?时序图里说清了「只推理一次」?

三处必然的差异:

差异点AI 版常见写法工程版(本仓)为什么工程这么写
输出怎么切reshape(33, 4) 当成 x/y/z/vis按 39×5 交错切、只取前 33 组(pose.py:62-76)模型实际是 39 个槽位、每槽 5 个数;切错则整体错位
要不要裁片照人脸那套先裁出人再回归整帧缩到 256 直接推理(pose.py:43)人体本来就大,裁片收益小、还多一次变换与误差
点位怎么画所有点全连成网只用官方 35 条边,且两端 vis 都要过门限(pose.py:21)528 对全连会糊成一团;低可信点连线会画出「凭空的骨头」

改一处、先预测再验证:把绘制门限从默认调到 0.9,先写下骨架会变成什么样,再跑一次对答案。

06互动:拖可见度门限,看骨架是残缺还是乱连

📌 这一节是「掌握检查」:亲手改一个参数,看现象是否朝你预期的方向变,还要能说出为什么 —— 说得出,才算掌握。

第 04 节说「骨架断不是 bug,是 vis 在过滤」。这一节把那条门限交给你:挡住几个部位是场景,门限多高是你说了算。

⚡ 参数实验台 · 遮挡几处 × 可见度门限
2
0.40
遮挡 2 处、门限 0.40:共 15 个主关节,画 13 个点、1 条线被断开。
互动 6-1|为便于观察,这里只画 15 个主关节(鼻/肩/肘/腕/髋/膝/踝),判定规则与真实的 33 点完全一致:点低于门限不画,线的两端任一低于门限就断开。遮挡位置固定为左手腕、右膝、左肩、鼻、右脚踝这 5 处。

怎么读出规律:先不动门限、只加遮挡 —— 看骨架从「少一个点」变成「断几段」;再把门限往下压到 0.2 —— 点都回来了,但那些点是猜的。所以门限不是「越高越好」,而是「要可信还是要完整」。

遮挡 0 · 门限 0.4
完整骨架

15 点 14 线齐全,就是第 03 节那张图的样子。

遮挡 2 · 门限 0.4
断两段

手腕和膝的点不画,对应两条线断开 —— 骨架「断」不是错。

遮挡 5 · 门限 0.4
只剩躯干

四肢大段丢失,只能判「人在不在」,判不了动作。

门限压到 0.2
点都回来了

但被挡部位的点是外推出来的,位置可能离谱 —— 判定动作会被骗。

骨架断不是画错,是 vis 在替你保守。门限抬高要完整度,降低要覆盖面 —— 这一步选错,后面的动作判定全跟着错。

07验证:三道小测

✅ 目标对账 · 验证掌握得有多好

回页首对照「实验目标」:① 关键点为何比框有用 → 试 Q1;② 单图与实时跑通了没有、Pose: OK 能否解释 → 回第 05 节;③ 两种坏相(断线 / 整帧空白)调出来没有 → 试 Q2 与 Q3,并回第 06 节把门限推到两端。三条全 ✓ 就完成。

Q1判断「他举手了」,用关键点比用检测框强在哪?
关键点算得更快
框只能说明人在哪一块,举手和放下时框几乎不变;而手腕与肩膀的 y 坐标一比就能定性
关键点能识别这个人是谁
对。动作判定的本质是坐标比较:腕 y 小于肩 y 就是举手。框给不了这个粒度,所以做体感控制必须先有关键点。第三个选项是常见误解:关键点只说形状,认人需要另一类模型。
Q2模型第一路输出是 195 个数,正确理解是?
33 个点 × 4 个值(x/y/z/vis)再补 63 个冗余
39 个槽位 × 5 个值(x/y/z/vis/presence)交错排列,只用前 33 个槽位
195 是画面里的人数乘点数
对。这是本页最容易踩的坑:直接 reshape(33, 4) 会整体错位,画出来的骨架完全对不上人。源码注释专门写了「不是参考写的 [x,y,z,vis]×33」,就是提醒这一点。
Q3实时画面里人只露上半身,骨架断在腰上。最该先做什么?
换个更大的模型
接受它:下肢 vis 低,程序主动不连;要么让全身入镜,要么改用只依赖上半身的判定
把 pool.workers 调大
对。断线是「可见度过滤」的正常结果,不是故障。把门限压到很低能让线连回去,但那是猜出来的线,用来判下蹲会一路出错。workers 只影响帧率,与点质量无关。

08章节总结:33 个点 + 35 条线,把「看懂人」压成「比大小」

这页讲了什么,它们怎么串起来

概念它解决了什么和别的关系
resize_pad 到 256把任意尺寸的画面变成模型认得的方形输入记住的 scale/pad 是步骤 3 反算的唯一依据
195 维输出一次前向给出全身所有关节的候选位置39×5 交错,只取前 33 槽 —— 与 EXP-08 的「裁片」形成对照:人体不需要裁
33 组坐标把「人」变成可计算的数字下游所有动作判定都建立在这 33 组数上
vis 可见度告诉调用方「这个点是看到的还是猜的」决定点画不画、线连不连;也是「骨架会断」的原因
presence判断整帧里到底有没有人与 min_detection_confidence 挂钩;不过门限整帧空白
POSE_CONNECTIONS规定 35 条骨架边,让结构可读只影响显示;换模型必须换表
归一化比较让「举手/下蹲」的阈值与画面尺寸无关是 EXP-11 动作判定的第一步
⚠ 三个反直觉的地方 ① 直觉是模型输出 33 个点的坐标,实际是 195 个数里塞了 39 个槽位、每槽 5 个数,取错就整体错位;
② 直觉是骨架断线是模型不行,实际是 vis 在主动保守 —— 硬把线连回去反而更糟;
③ 直觉是人体也要像人脸那样先裁片,实际是整帧缩到 256 就够,因为人体本来就占画面一大块。
💡 四条要注意 ① 195 = 39 × 5,不是 33 × 4;另有 117 维世界坐标,本页不用,别把两路搞混;
② min_detection_confidence 卡的是 presence(整帧要不要),画点的门限是 vis(每个点要不要)—— 两个门限管两件事;
③ 端口是 8082(pose.mjpg),与前两个实验的 8080/8081 错开;
④ 只支持一个人(取分最高),两人入镜第二人会被静默忽略 —— 需要多人得先做人检测再逐个裁片。

前置依赖 · 缺一样就跑不起来

类型具体项缺了会怎样 / 怎么补
环境板上 Python 在 ~/ros2_venv;实时模式还需 ROS 2 Humble 两级 source 与相机节点未激活 venv → python: command not found;未 source ROS → ImportError: librcl_action.so
Python 库numpy、opencv-python、pyyaml、rknnlite、mjpeg_streamer缺 rknnlite 模型加载失败;缺 mjpeg_streamer 实时启动即退出
模型 / 资源models/pose_landmark_full.rknn(约 7MB)+ images/pose_demo.jpg模型缺失没有任何输出;示例图太小(384×407)会让人误以为「分辨率低所以不准」,其实换大图点位更稳
配置config/pose_config.yaml:min_detection_confidence: 0.5、source.mode: image、server.port: 8082缺 key 抛 ConfigError;mode: image 没写 rgb_path 直接报错
运行方式项目根目录 + PYTHONPATH 含 car1_pose_landmark,用 -m 模块方式运行直接跑 .py 文件会因相对导入失败

这套代码用在哪儿

  • 体感控制:举手→前进、下蹲→后退,机器人/小车隔空操作 —— 这就是 EXP-11 要做的。
  • 健身与康复:深蹲计数、手臂角度纠正,靠三点夹角与重复次数统计。
  • 工业人机协作:判断人是否进入危险区、是否弯腰作业,替代穿戴式传感器。
  • 不该用它的场合:只需要「有没有人」用检测就够(EXP-04);要精细手势(比耶、OK)得上手部关键点(EXP-12),33 点里手只到腕。
核心记忆点:33 点 + 35 线 = 把「看懂一个人在干什么」压成「比几个坐标」。vis 决定哪段敢用,presence 决定这帧算不算有人。

下一个实验离开人体,回到几何:画面里那个物体,离我到底多远?EXP-10 用深度图把第三维补上。