news 2026/9/16 5:55:24

基于俯视相机与球体跟踪的台球自动计分系统实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于俯视相机与球体跟踪的台球自动计分系统实践

打台球的朋友应该都有过这种体验:进球很爽,但记分很烦。尤其打九球或者追分的时候,一边要瞄球、想杆法,一边还要记着当前该打几号、自己打到几比几了,偶尔还会因为记错分跟球友争两句,非常破坏手感。后来我组了个小项目,用一台俯视相机加上视觉识别和球体跟踪,做了一套自动计分系统。简单说,就是相机架在球桌正上方,盯着整张台面,识别每一颗球的位置、颜色和运动轨迹,再根据台球规则自动判断进球、犯规和当前比分。这篇文章把我踩过的坑、验证过的方案、以及能直接复现的工程细节完整写出来,给想入场AI视觉或做台球智能化改造的朋友做个参考。

这套系统的核心难点有两个:一是俯视视角下的球体识别,要解决球与球之间的遮挡、灯光反光和球袋边缘的干扰;二是球体跟踪的稳定性,也就是同一颗球在不同帧画面里必须保持同一个身份ID,否则计分逻辑全乱。我前前后后试了传统图像处理和深度学习两条路线,最后选的是“传统视觉做检测、运动模型做关联、规则引擎做仲裁”的组合方案。整套代码量不大,但工程细节非常多,下面按模块拆开讲。

1. 系统架构与安装方案设计

1.1 为什么选择俯视单相机方案

最早我考虑过两种布点方式:一种是在球桌上方装单个广角相机俯拍,另一种是在天花板对角位置装两到三个相机拼接视角。两三个相机的方案看起来覆盖更全,但实际工程量大得多。多相机涉及同步触发、画面拼接、坐标归一化,任何一个环节有偏差,球的位置在不同相机之间就会跳变,跟踪逻辑很难写。俯视单相机的好处是天然只有一个坐标系,相机画面和桌面坐标是简单的透视变换关系,处理起来又快又准。

还有一个关键点是高度问题。球桌标准尺寸大约是2.54米乘1.27米,如果想一张画面覆盖整张桌子,相机安装高度至少要2.5米以上。装得越高,透视畸变越小,但分辨率利用率越低;装得太低,桌子边缘的球会明显变形,袋口附近还可能出现盲区。我最后定在3米高度,配一颗4mm焦距的镜头,视角大概90度左右,刚好能把球桌加一圈缓冲区域完整框进来。这一点后来实测下来非常稳,球桌四角和袋口全部都在可视范围内,没有出现球到袋口附近突然消失的情况。

相机本身没有用很贵的工业相机,选的是大靶面、低畸变的500万像素USB相机,价格几百块,支持全局快门。全局快门这点很重要,如果用了卷帘快门的摄像头,球速快的时候画面会出现果冻效应,球的位置会明显拉长,跟踪时位置误差能差出一两个球直径,误判概率会大很多。固定相机的支架我用的是天花板吊装支架,安装时把相机镜头朝下,画面中心对准球桌中心。

1.2 镜头标定与坐标映射

相机装好后,第一步不是写算法,而是做标定。俯视画面虽然已经很正了,但广角镜头一定存在桶形畸变,加上安装角度不可能绝对垂直于桌面,画面边缘的球坐标和真实桌面坐标会有偏差。我的做法是打印一张A4纸的棋盘格,放在球桌的四个角、中心、以及两个长边的中间点各拍一张,用OpenCV的findChessboardCorners和calibrateCamera计算畸变系数和相机内参,再做去畸变。

去畸变之后还有一步透视校正。因为镜头和桌面并不是绝对平行的,画面里球桌可能是轻微梯形,所以需要把球桌的四条库边检测出来,然后把四个顶点映射到一个固定分辨率的矩形上。这里推荐用ArUco码贴在球桌四角,因为ArUco码自带角点信息,检测精度比直接找库边高很多。做完透视校正之后,画面里每个像素点都能对应到桌面上的实际物理坐标,后续所有的球位置、运动距离、进球判定都是以这个校正后的坐标系为基准的。

注意:标定不是做一次就完事的。相机支架如果被碰到、或者相机因为热胀冷松出现微移,都要重新做一遍标定。我在系统里加了一个启动自检流程,每次开机先检测四角的ArUco码,如果角和基准位置偏差超过10个像素,就提示需要重新标定。

2. 球体检测与颜色识别

2.1 球体检测算法选型:传统视觉还是深度学习

球体检测是整套系统的地基,这一步错一步后面全错。我先后试了两种主流路线,简单给大家交个底:

  • HoughCircles圆检测:OpenCV自带的函数,参数少、速度快,但实际用下来对台球这种场景非常不友好。台球球体带高光,加上灯光直射产生的镜面反射,HoughCircles经常把高光点误判成圆心,或者把球影子的边缘也算成圆,一帧画面里能出现十几个假圆。而且俯视情况下两颗球紧贴在一起时,圆检测会把两个球并成一个椭圆,根本没法用。
  • 深度学习目标检测(YOLOv8 / RT-DETR):用目标检测模型直接框出每颗球的位置。这个方案鲁棒性高,对遮挡、反光、邻球粘连都有很好的适应性。我用Labellmg标注了大约2000张真实球桌照片,训练了一个YOLOv8s模型,mAP50能到0.97以上,检测速度在CPU上也有30ms一帧,完全够用。

如果只是做一个原型Demo,直接用YOLO是最省事的路线。但要注意,台球比赛对帧率有要求,球速快的时候一秒钟可能要处理30到60帧,如果每帧都跑一遍YOLO,哪怕是很小的模型,树莓派这类设备也扛不住,Jetson系列还能勉强应付。我的方案是间隔检测:每5帧跑一次YOLO做全图检测,中间帧用光流或卡尔曼滤波做预测填充。这样既保证检测精度,又让整体帧率稳定在30fps以上。

2.2 颜色的精准识别与球类映射

检测到球的位置之后,还要知道它是什么颜色的球。这一步我用的是HSV颜色空间提取特征。YOLO检测框返回的是一个bounding box,我把框内像素转到HSV空间里,统计色相、饱和度和明度的分布,再和预设的颜色模板比对。不同颜色球的HSV范围设定如下表:

球色色相H饱和度S明度V备注
白球0-1800-30180-255白色球易受反光影响,需要结合圆形度过滤
黄球20-3580-255120-2551号和9号
蓝球100-13080-25580-2552号和10号
红球0-10 / 170-18080-25580-2553号和11号
紫球125-15560-25560-2554号和12号
橙球10-2580-255120-2555号和13号
绿球40-8060-25560-2556号和14号
棕球10-2060-18060-1607号和15号
黑球0-1800-600-808号

注意这里有个台球特有的坑:1号和9号都是黄色,2号和10号都是蓝色,传统识别到颜色还不够,还要靠位置状态来区分是哪一颗。我的方案是维护一个全局球表,建立“颜色 -> 位置”的索引。比如开局时1号在三角框最前方,9号在中心,初始位置是已知的,之后跟踪器会持续维护每一颗球的ID和坐标,颜色相同但ID不同的球会通过运动轨迹的连续性来区分。

还有一个反光问题。球桌正上方灯光直射下来,球面高光部分会呈现出白色或黄色,导致颜色判断偏差。我在HSV统计时加入了高光像素剔除逻辑:对框内每个像素,如果明度V>240且饱和度S<30,判定为高光,不参与颜色统计。这个简单的过滤操作把颜色识别的准确率从大约85%提升到了98%以上。如果场地灯光特别复杂,还可以再叠加一个中值滤波。

3. 跨帧球体跟踪与运动判断

3.1 多目标跟踪的核心难点:ID稳定性

球体检测解决的是“这一帧画面上哪里有球”的问题,但计分系统需要知道“这个球从上一帧到这一帧去了哪里”,也就是要跨帧关联同一个球。这问题看着简单,实际是整套系统里最容易翻车的地方。我最早用KCF和CSRT这种传统相关滤波跟踪器,一个球一个跟踪器,球少的时候还行,但一旦两颗球交错而过,跟踪器就会跟丢或者跟错目标。球体的外观没有纹理,从任何角度看都是一个圆,相关滤波算法没有足够的外观特征来做区分,所以很快就放弃了。

后来我换成了经典的多目标跟踪思路:检测器负责出位置,跟踪器负责做数据关联。每一帧拿到检测框之后,用上一帧所有球的位置做预测,然后计算当前帧检测框和预测位置的IoU或中心距离,通过匈牙利算法找最优匹配,匹配上的就沿用上一帧的ID,匹配不上的新检测框就分配一个新ID。这套逻辑看起来很朴素,但配合卡尔曼滤波做运动预测之后,效果非常稳。

实操心得:在匹配代价矩阵里,除了位置距离,我把“预测颜色”也加进去了。假设上一帧某颗球是黄色,那么当前帧所有检测框里只有黄色的框才有资格跟它匹配,否则直接设为无穷大。这样一个简单的颜色约束,就把同色球ID互换的概率降到了很低,代价矩阵的维度也小了不少,处理速度更快。

3.2 卡尔曼滤波的参数设置与轨迹平滑

卡尔曼滤波的原理这里不展开,简单说就是用一个状态向量描述球的当前位置、速度和加速度,每一帧先用运动模型预测下一个位置,再用检测结果做校正。在台球场景里,球的运动近似匀速直线运动,遇到库边反弹后速度方向突变,所以我用的状态向量是[x, y, vx, vy],没有加入加速度项,因为台球在桌面上几乎不受摩擦力以外的影响,加速度近似为0。

过程噪声协方差Q和测量噪声协方差R这两个参数是调出来的。Q设置得越大,滤波器越相信检测结果;R设置得越大,滤波器越相信预测结果。我在真实桌面上反复试了几组,最终用的是Q=0.1,R=1.0。如果你们在复现时发现球的位置抖动明显,可以适当增大R;如果发现球的轨迹滞后于实际位置(球撞库后滤波器反应慢半拍),可以适当增大Q。这组参数的核心思路是:单帧检测精度其实很高,但偶尔会有跳变,所以给预测多一些平滑。

还有一个和卡尔曼滤波配合的小技巧:对于“消失”的球,不要立刻删除它的跟踪轨迹。台球在运动过程中可能被另一颗球挡住,视线里短暂消失一两帧,如果立刻删除,球重新出现时就会被当作一颗新球,计分逻辑就乱了。我的处理是给每个跟踪器设置一个存活计数,连续丢失超过30帧才删除轨迹;在此期间的预测位置依然参与卡尔曼更新,只是测量的置信度降低。

3.3 进球判定与母球落袋处理

进球的本质是球从桌面上消失,并且消失位置在某个袋口附近。但这个判定有一个非常隐蔽的坑:球高速运动到袋口时,由于画面帧率不够,可能出现“上一帧还在袋口,下一帧已经不见了”的情况,这时候如果用消失位置来判定进袋位置,误差会很大。我的方案是把判定分成两步:

第一步,检测球消失。把桌面的有效区域做一层膨胀处理,得到袋口扩展区域。如果一颗球的跟踪轨迹在袋口扩展区域内消失,标记为“疑似进球”。第二步,回看历史轨迹。取消失前最后10帧的位置点,做线性拟合,计算这条轨迹的终点是否落在袋口中心附近30像素范围内。如果满足,判定为真实进球;否则视为跟踪丢失,等待球重新出现。

这个回看机制大大减少了误判。我最初只做第一步,结果发现球在贴库滚动时偶尔会因为球影子和库边颜色太接近而被检测器丢掉,系统就会误报进球,后来加了轨迹回看,误报率降到了1%以内。

母球落袋在台球规则里是一个比较特殊的事件,意味着当前击球犯规,对手获得自由球。视觉上母球落袋和普通目标球落袋没有区别,但在规则引擎里,它触发的是另一套逻辑。所以我的系统在进球事件里会带一个isCueBall标志,规则引擎根据这个标志决定是给当前击球方加分,还是切换击球权并给对手自由球。

4. 计分规则引擎设计

4.1 不同玩法的规则差异与状态机设计

台球不是一个单一游戏,常见的玩法有中式八球、九球追分、斯诺克等,每种玩法的计分逻辑差别非常大。我的架构是把视觉层和规则引擎层完全解耦,视觉层只负责上报“某颗球在某位置进袋”,规则引擎收到事件后,结合当前游戏状态决定如何计分。这样换玩法的时候只需要改规则引擎配置,视觉层不用动。

以九球为例,规则是“从1号球开始,按顺序击打,打进1号才能打2号,以此类推,最后打进9号球获胜”。如果击球方犯规,比如母球落袋、没碰到台面上最小号码的球,对手获得自由球。这里规则引擎需要维护一个当前目标球号码(currentTarget),每进一颗球就更新它。而且九球有个特殊规则:只要进球,击球方可以继续击球;如果进球的是9号球,比赛直接结束。

中式八球的规则更复杂一些,因为涉及花色选择。开球之后,先进球的球色(全色或花色)归开球方,另一方打另一种球色,最后谁先把自己的球打完再打进黑八,谁获胜。这套状态机比九球多了“球色分配”这个环节,但原理还是一样的:维护一个当前击球方、双方剩余球色列表,每次进球事件触发状态变更。我做规则引擎的时候吃了不少亏,最深的体会是:状态机的状态定义一定要围绕“回合”和“犯规”来设计,而不是围绕“分数”,因为台球规则里“谁继续击球”比“得了几分”更重要。

4.2 犯规判定的视觉依据

犯规判定是整个自动计分系统里最依赖视觉能力的部分。以九球为例,最常见的犯规有两种:一是母球落袋,二是击球时没有先碰到最小号码球。前者靠球体跟踪就能检测到,后者需要判断第一接触球,这是视觉技术里非常大的挑战。

第一接触球的判定逻辑是:在击球瞬间,也就是母球刚开始运动的那一刻,找到距离母球最近的被击打目标球。这个逻辑的关键是准确捕捉“击球瞬间”。我的方法是监测母球速度曲线。当母球从静止突然加速,说明击球发生了;从速度曲线里找到加速起点,再向前回看几帧,找到母球的位置,然后和台面上所有球的坐标做距离排序,最近的球就是第一接触球。

但是这里有一个精度问题:两帧之间母球已经移动了一段距离,离被击打的目标球更近了,距离排序的结果可能倾向离当前帧母球位置更近的球,而不是真正第一接触的球。我的优化是,用卡尔曼滤波预测击球瞬间之前的母球位置,而不是直接使用击球瞬间那一帧的检测位置,这样可以把第一接触球的判断误差从一两颗球的位置缩小到半个球以内。

避坑提示:灯光频闪和球速太快都可能导致某一两帧的检测框出现偏移,进而影响第一接触球判断。我在第一接触球的判定结果后面加了一个置信度分数,如果置信度低于阈值,系统会标记为“需要人工确认”,而不是强行给一个结果,这样比永远正确但偶尔胡说更实用。

5. 常见问题与部署优化实录

5.1 部署环境与性能调优

整套系统我最终跑在Jetson Orin Nano这个边缘设备上,8GB内存,CPU做图像预处理和HSV颜色统计,TensorRT加速的YOLO模型跑在GPU上。实测下来,YOLO检测单帧大约12ms,颜色识别和跟踪大约8ms,规则引擎几乎不耗时间,整体端到端延迟在30ms以内。如果你们想用更便宜的设备,树莓派5也能跑,但需要把YOLO模型换成更小的YOLOv8n,帧率大概会降到15fps左右,勉强能用。

如果想在纯CPU环境跑,还有一个思路是放弃深度学习检测器,改用传统图像处理+YOLO间歇检测的混合模式。具体来说,用YOLO每隔10帧校准一次所有球的位置,中间帧用背景减除快速确认有无运动事件。静止状态下CPU占用率极低,一旦检测到运动,再临时调用YOLO做精确检测。这种方案在低负载场景下很实用,但代码复杂度会高不少。

5.2 实战中的三个经典坑

先说灯光。台球桌对灯光均匀性要求极高。我第一版系统在客厅实测时,发现球桌中间区域的球检测率明显偏低,排查了很久,最后发现是因为客厅吊灯在桌面上形成了一个巨大的高光带,恰好覆盖球桌中央。后来我在相机镜头上加了一个偏振镜,配合调整灯光角度,才把高光影响降到可接受范围。如果你们是室内固定安装,强烈建议在球桌正上方装一个柔光灯箱,灯光均匀度比装多颗射灯好得多。

再说球形误检。球杆在击球时会进入画面,而且球杆在画面里通常是一根长条,和球的外观差异很大,YOLO误检的概率不高。但球杆的阴影就不好说了,特别是灯光从侧面打过来,球杆阴影会拉得很长,形状接近一条深色曲线,偶尔会被识别成球的边缘。我的处理是在检测结果里加了尺寸过滤规则,宽高比超过1.5的检测框直接丢弃,同时要求检测框内的圆形度大于0.7。

最后是同色球ID互换的终极难题。虽然我前面说了加颜色约束能大幅降低ID互换概率,但在球速极快、两球交错的极端情况下,ID还是会偶尔互换。我的补救方案是:在规则引擎层加了一个轨迹一致性校验,如果某颗球的轨迹在某帧出现了不合理的速度突变(比如同一颗球瞬间从桌面左侧“瞬移”到右侧),系统会把这个事件标记为异常,等待下一个静止状态后用颜色和位置重新初始化ID。

5.3 视觉识别之外的扩展应用

做完了自动计分之后,我发现在这套视觉识别和球体跟踪的基础上,还能延伸出很多有用的功能。比如,我已经实现了“击球回放”功能:每当发生进球或犯规事件,系统会自动截取事件前10秒的完整画面,合成一个短视频。这样打球过程中不需要手动录像,赛后复盘可以直接看每个关键回合的完整过程。

另一个正在开发中的功能是击球轨迹分析。有了每颗球在每帧的位置,就能重建整局比赛的击球序列,包括每次击球母球的初始速度、方向和目标球,这些数据可以用于统计球员的准度、走位习惯和犯规倾向。对想提升球技的玩家来说,这种数据化复盘方式比感觉型复盘有说服力得多。目前我已经把这部分数据导出成CSV和JSON,可以直接喂给可视化大屏或者做进阶的数据分析。

根据我个人的经验,这套系统最大的价值倒不是省掉了记分员,而是它把台球的每一杆都变成了可量化的数据。以前打台球只能凭感觉判断自己哪里打得不好,现在回放和轨迹数据摆在那里,哪一杆力大了、哪一杆角度薄了,一目了然。这种玩法对业余爱好者来说非常上头。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 5:54:43

宽带测速总不准?从原理到实操教你精准测速

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 5:54:33

AI前端流式处理与TypeScript状态管理实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 5:53:47

工业4.0的底层逻辑:从数据驱动到智能制造落地路径

工业4.0这个概念&#xff0c;我在制造业圈子里听了快十年&#xff0c;每次技术交流会总有人问&#xff1a;工业4.0到底是个啥&#xff1f;为什么我们上了MES、买了机械臂、搞了AGV小车&#xff0c;还是觉得自己离“4.0”差了十万八千里&#xff1f;这个问题问得特别好。因为绝大…

作者头像 李华
网站建设 2026/9/16 5:53:04

JavaEE图书借阅系统:Servlet+JSP+MySQL完整闭环实现

简介&#xff1a;本资源是一份面向高校计算机专业本科生的JavaEE期末综合实践项目&#xff0c;聚焦图书管理网站开发&#xff0c;助力学生系统掌握企业级Web应用开发全流程。项目覆盖需求分析、系统设计、Servlet/JSP后端开发、MySQL数据库操作、JPA对象关系映射及MVC架构实现等…

作者头像 李华
网站建设 2026/9/16 5:53:00

大模型工具调用(Tool Use)技术解析与实践指南

1. 大模型与Agent能力概述在人工智能领域&#xff0c;大模型&#xff08;Large Language Model&#xff09;已成为推动技术发展的核心引擎。这些拥有数百亿甚至千亿参数的神经网络模型&#xff0c;通过海量数据训练获得了惊人的语言理解和生成能力。而Tool Use&#xff08;工具…

作者头像 李华
网站建设 2026/9/16 5:52:46

Unity客户端面试网络篇:TCP/UDP、HTTP、Socket及同步机制全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华