1864 字
9 分钟
- 次浏览
回看一个篮球投篮分析项目:YOLO 之外还有很多活
读前导览

看 ball_gpu_yolo11 时,我最想记下的是:YOLO 跑起来只是开始,投篮分析还得把双目视频、轨迹拟合、状态机和回放界面拆开检查。

正文
1864 字
阅读
9 分钟
结构
9 节

ball_gpu_yolo11 是我这次整理到的一个篮球投篮分析项目。公开仓库在这里:

https://github.com/GitLaughs/ball_gpu_yolo11

它的 README 把功能列得很满:双目立体视觉、YOLOv11、五阶段离线预处理、抛物线物理分析、投篮状态机、Flask Web 界面、Windows 打包分发。第一眼看过去像是在堆功能,但读完之后,我更想记下的是一个很朴素的经验:

只盯着检测精度,会漏掉出手、轨迹和结果判定这些后面的麻烦。

只跑检测还不够#

篮球投篮分析里,YOLO 只能告诉你这一帧里可能有篮球和篮筐。它不能直接回答:

  • 什么时候出手。
  • 球是否进入自由飞行段。
  • 轨迹弧顶在哪里。
  • 球有没有穿过篮筐区域。
  • 框弹、网弹、回弹该怎么判。
  • 统计结果什么时候可以确认。

这些都不是单帧目标检测能回答的,还涉及跨帧时序、物理轨迹和状态机。

所以我觉得这个项目值得写:它没有停在“检测框画出来了”。它先把重计算做成离线预处理,再把回放、状态推进和结果解释放到后面的链路里。

离线预处理让实时界面更稳#

README 里提到五阶段预处理:

检测 -> 跟踪 -> 平滑 -> 导出 -> 物理分析

这个设计很实用。体育视频分析的计算压力并不小,尤其是目标检测、跨帧跟踪、轨迹平滑和抛物线拟合。如果所有事情都挤在实时播放阶段,界面一旦卡住,就很难判断到底是模型慢、跟踪坏了,还是状态机在误判。

把重计算提前做成预处理,有几个好处:

  • 检测结果可以复用。
  • 跟踪和平滑可以单独调参。
  • 物理分析失败时能回看中间结果。
  • Web 界面只负责展示和状态推进,不必承担全部计算压力。

这也是我后来做类似视觉小项目时更愿意采用的拆法:先把可批处理的部分从实时路径里拿出来,别让 UI 帧率替所有上游问题背锅。

出手检测需要物理约束#

一个篮球框在画面里,球从下往上飞,最后可能进也可能不进。只靠检测框中心点的高度变化,很容易误判。

项目里用到的思路是抛物线物理分析:估算像素重力,寻找自由飞行段,再定位出手帧。这个做法不花哨,但能把“看起来像出手”的画面现象转成可以检查的约束。

这比“球开始上升就算出手”更稳。因为真实视频里会有手持球、遮挡、抖动、跟踪断裂和篮筐附近反弹。物理约束能把一部分噪声挡在外面:

  • 自由飞行段应该接近抛物线。
  • 水平方向加速度不该异常大。
  • 垂直拟合需要有足够可信度。
  • 出手点不能落在篮筐或弹地区域里。

视觉项目很容易把所有问题都交给模型,但很多场景里,简单物理约束反而更可解释。

状态机比一堆 if 更可维护#

投篮判定看的是一段过程,不是一帧画面。

README 里把投篮状态拆成几个阶段:

IDLE -> RISING -> TRACKING -> RESULT -> COOLDOWN

这个结构比“每帧写一堆 if 判断”更清楚。每个状态都有自己的入口条件、退出条件和超时逻辑。比如:

  • IDLE 等待出手信号。
  • RISING 观察上升阶段和弧线。
  • TRACKING 跟踪球与篮筐关系。
  • RESULT 固化命中或未中结果。
  • COOLDOWN 防止同一次投篮重复计数。

体育动作识别很适合状态机。动作本身有时间顺序,系统也需要避免一帧噪声直接改变最后结果。

进球判定要容忍真实世界#

真实投篮不是理想轨迹。球可能空心入网,可能打板,可能碰框,可能进网后回弹,可能在篮筐附近多次穿越。

如果判定逻辑只写成“球中心穿过篮筐线就算进”,误判会很多。项目 README 里提到的增强包括网弹容忍、框弹多穿越、弹跳延长跟踪。这些设计说白了是在承认现实世界不干净。

我更喜欢这种处理方式:先定义典型路径,再把常见的非理想情况放进状态机,而不是让一堆例外散落在代码里。我自己更愿意先把这些情况写进流程,再考虑要不要换模型。

双目深度别阻塞主线程#

双目视觉的深度估计本身也很重。README 里提到把 stereo 计算放到后台线程,主线程使用上一帧缓存结果。

这个取舍很工程化。实时界面关心的是稳定帧率和可交互性,不一定要求每一帧都同步等到最新深度。如果后台线程持续产出深度缓存,主线程就可以减少阻塞。

这种流水线并行的思路适合很多视觉项目:

current frame -> submit heavy work
previous result -> render now
next frame -> consume when ready

只要延迟可接受,系统整体体验会比同步等待更好。

Web 界面是观测面,不是重点算法#

这个项目用 Flask 和 MJPEG 流做 Web 展示。它展示左相机、右相机、深度图、投篮统计和历史记录。

这类界面最该提供的是观测能力:

  • 当前处理到哪一帧。
  • FPS 和延迟是否合理。
  • 检测框是否跟对目标。
  • 出手标记是否出现在合理位置。
  • 状态机是否推进到预期阶段。
  • 最后命中统计是否可信。

Web 界面要帮助调试流水线,不能只停在“看起来漂亮”。尤其在视觉项目里,能看到中间状态会极大降低排错成本。

打包分发也要写清楚#

README 里有一个很具体的发布提醒:构建过程中的中间目录不能当成正式分发目录。

这类提醒很实用。很多 Python + PyInstaller 项目都会遇到“我本机能运行,打包目录换台机器就坏”的问题。如果文档不写清楚哪个目录可分发、哪个只是中间成果,验收和部署会很混乱。

一个视觉 demo 如果要给别人试用,算法之外还需要:

  • 安装路径清楚。
  • CPU/GPU 环境说明清楚。
  • 模型文件位置清楚。
  • 视频格式要求清楚。
  • 打包出来的目录哪些能直接发给别人。
  • 常见错误有排查路径。

这些都不是算法亮点,但决定别人能不能真的跑起来。

我最后记下来的东西#

我最后记下来的重点,其实是这个项目把检测、跟踪、轨迹拟合、状态判断和展示分开处理。这样后面哪里坏了,至少知道该回头看哪一段,不会把所有问题都归到模型上。

下次再做类似项目,我会先把数据怎么走、状态怎么变、结果怎么回看画出来,再开始调模型。

回看一个篮球投篮分析项目:YOLO 之外还有很多活
https://blog.sunmmyapi.xyz/posts/basketball-shot-analysis-pipeline-first/
作者
Sun
发布于
2026-05-29
许可协议
CC BY-NC-SA 4.0

继续读

相关内容