stroke4 几何探针 — 外部关键点能不能救正反手
★
新:把动作分解图当参考图喂给模型 → clear acc 0.693→0.792,超过此前所有方案:
看这一页
→
2026-09-22 新规范(持拍手/中线/拍面 重新定义)+ 3D pose 对比:
看这一页
⚠ 结论:不能,判据没过。这一页存在的理由是让你自己看一眼几何抽得对不对 —— 整个否定结论都压在
「检测器读出的几何是否可信」上,所以它必须可查验,而不是只给一张汇总表。
注意:下面「符号翻转的真正原因」一节修正了我先前的判断 —— 10.6% 的翻转是我的符号锚点
在双手握拍时失效,不是这条线索本身不可用。融合无增量的结论仍成立,但需要修完锚点再复核一遍。
绿框=球员 · 橙框=球拍 · 白点/黄线=17 关键点 · 红线=肩线 ·
粉线=躯干中线。左边是原图,右边是镜像。
镜像不改变网球的正反手标签,所以两边读出的几何本该完全一致。
为什么做这个
p1–p4 四版 prompt 都是让 VLM 自己从像素里读身体和球拍的相对几何,而它读得不稳:
把图水平翻转后 16.6% 的答案会变(标签本不该变)。在这些翻转样本上正反手准确率只有
0.486,等于抛硬币;而在镜像稳定的样本上是 0.872。
所以设想是:用 racketeer + 姿态检测器把这些几何量显式算出来再喂给模型,绕开它不稳的读数。
结果一:几何抽得出来,但关键那一位是噪声
| 指标 | 值 | 读法 |
| 能抽到持拍球员 + 可用关键点 | 86.0% | 失败 102 例全是 no_holding_player |
| 原图与镜像都抽到 | 84.8% | — |
| 关键路由位「球拍是否越过身体中线」符号翻转 | 10.6% |
这是 p2/p4 路由表的主轴,也是本方案的主线索 |
| 躯干扭转角偏移 >10% 尺度 | 51.6% | 阶段线索基本不可用 |
结果二:只用几何比 VLM 还差,而且主线索权重≈0
| 方法 | 正反手 acc | 说明 |
| 多数类基线 | 0.585 | — |
| 只用几何(13 维,按摄影师分组 5 折 CV) | 0.708 | 有信号,但弱 |
| Opus 5 / p4 prompt | 0.796 | 同一批 368 张 |
线性权重里 racket_along(球拍是否过身体中线)= −0.009,约等于零。
整个方案建立在这条线索上,而它在检测器读出的几何里没有预测力。
真正带信号的是 racket_area_ratio / wrist_gap / offhand_to_racket ——
也就是「双手握把 / 非持拍手在哪」,恰好是 p4 已经用得很好的那条。
结果三:融合没有增量
| 特征 | acc | 相对 p4 自读 |
| p4 的答案 + 它自己报的证据字段 | 0.881 | — |
| + 全部 13 维几何 | 0.859 | −0.022 |
| + 仅镜像稳定的 5 维几何 | 0.876 | −0.005 |
oracle(逐张二选一的理论上限)是 +9.1 点,但真实融合拿不到,噪声特征还倒扣。
唯一的亮点:在 p4 镜像翻转的 60 张上,几何 0.517 vs p4 0.467,能救回 15 张 ——
方向对,强度不够穿过融合噪声。
一个已修正的错误结论
过程中我一度报过「用 VLM 自己的证据字段重新路由 → +16 点、救 38 张坏 0 张」。那是泄漏。
重路由器是二分类、只能输出正手/反手,而被测样本里 VLM 有一部分答的是 serve/other ——
4 类口径算错,二分类口径被强行折算成正反手之一,等于白送了「这张一定是正反手」这个信息。
改成同口径 4 类后:0.688 → 0.713(+2.5,救 10 坏 0,p=0.002),
而在无泄漏的正反手子问题上(n=187)是 0.856 → 0.856,救 0 坏 0。
那 +2.5 点全部来自修「是不是底线球」的边界,在正反手决策上一点没动。
怎么判「过中线 / 没过中线」
三步,全在 stroke4_geom_extract.py:geometry() 里:
① 定中线 —— 取左右肩关键点(COCO 5/6)连成红线,
其中点作垂线 = 粉线,即躯干中线。
② 定持拍手 —— 左右手腕(9/10)里离球拍框中心更近的那只。
这一步决定正负号朝哪边:「正」永远指向持拍肩一侧,所以它与画面左右无关,镜像也不该改变它。
③ 投影 —— 把球拍框中心投到肩线方向,量它到粉线的距离,除以肩宽归一化。
读角标:同侧 +1.97 = 球拍在持拍肩那一侧,没过中线;
过线 −2.03 = 越到了另一侧,过中线。数值单位是肩宽,
−0.8 就是越过中线约 0.8 个肩宽。阈值是硬性的 0,没有死区。
一张图要看的是:左右两个角标的符号是否一致。镜像不改变网球的正反手,
所以「同侧」在两边都该是「同侧」。符号不一致 = 这张图上这条线索不可信。
符号翻转的真正原因(我上一版的判断是错的)
我原先说翻转说明「这条线索本身模棱两可」。
量过之后不是。
| | 翻转 (33) | 未翻转 (279) |
| 判定时离中线距离 |值| 中位 | 2.02 肩宽 | 1.97 肩宽 |
两手腕间距 wrist_gap 中位 | 0.62 | 1.46 |
| 原图/镜像持拍手位置差 >0.5 肩宽 | 28/33 | — |
翻转样本离中线
一点都不近(2 个肩宽),所以
不是阈值噪声 —— 死区阈值放到 0.30 仍有 9.4% 翻转。
真正原因在上面的
第 ② 步:
28/33 的翻转是「换了只手认持拍」。
双手握把时两只手腕挨在一起(
wrist_gap 中位 0.62),「离球拍最近的手腕」就是掷硬币,
一旦选反,整套正负号定义整体倒过来。佐证:翻转样本里反手占
61%(全体 42%),
而
wrist_gap<0.6 的样本有
69% 是反手。
这是我实现里的锚点选错了,不是这条线索不可用。可修:改用「球拍
手臂挂在哪个肩上」定号
(p2 原本就是这么写的),或把双手握把单独分桶。修完需要重跑一遍探针,才知道
racket_along 权重≈0 这个结论里有多少是我的 bug 造成的。
逐图查验