尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

AI台球自动计分系统实战:俯视相机与视觉识别算法解析

AI台球自动计分系统实战:俯视相机与视觉识别算法解析 我们要把“AI台球自动计分”讲透。先说结论用一颗俯视相机挂在球台上方靠视觉识别和球体跟踪把进球、犯规、胜负这些事自动算出来这件事完全可行而且现在做一套原型的成本已经压到很低了。这篇内容我按自己的实际踩坑经历来写从相机选型、算法取舍到计分规则怎么落地尽量把能直接抄作业的细节都放出来。1. 项目概述与整体设计思路1.1 为什么选俯视相机做台球计分台球计分这件事看着简单真做起来挺烦。人工计分要盯着每一杆谁进了什么颜色的球、有没有犯规、黑八什么时候该打都得记清楚。尤其打“8球”这种规则复杂的玩法双方球色分配、自由球、犯规后的摆放记错一次就容易起争执。用相机自动计分的思路很早就有人试过但早年方案大多是从侧面架几台相机。侧面视角有一个很大的问题球和球之间的遮挡太严重。两颗球并排的时候侧面的镜头只能看到前面那颗后面那颗被完全挡住。而且袋口附近区域经常被球员的手、球杆、身体遮挡误判率非常高。换成俯视视角之后整个台面一览无余球和球之间即使挨在一起从正上方看也基本能分辨出轮廓。再加上现在的视觉识别算法足够成熟一颗普通USB相机加一台电脑就能跑起来不需要上工业级别的硬件。1.2 整体架构与核心流程整套系统的数据链路大致是这样相机采集顶视图画面预处理畸变校正、光线归一化球体检测定位台面上每颗球的位置和颜色帧间跟踪匹配前后帧的同一颗球生成运动轨迹事件判断进球、碰库、犯规等计分引擎按规则更新双方分数、局况和胜负这个流程里最难的两个点一个是球体检测的稳定性另一个是规则判断的准确性。检测不稳定后面的跟踪和计分全崩规则判断不准确系统就只是个花架子。下面我把每一块的选型和实现细节拆开讲。2. 硬件搭建与视觉基础2.1 相机选型与安装细节相机这块我试过几款最后定下来的组合是分辨率1080P以上、帧率30fps、定焦广角镜头。太低的帧率在球速快的时候会出现运动模糊太高的帧率普通电脑的推理速度跟不上30fps对台球场景完全够用。安装位置很关键。相机要尽量垂直于台面中心镜头光轴和台面法线的夹角最好控制在3度以内。角度稍微歪一点球在画面边缘的形变就会很严重检测框的坐标映射到真实台面坐标时误差会放大。支架方面如果条件允许直接在球桌正上方的天花板打膨胀螺丝稳定度最好。如果不想破坏环境用落地式的摄影灯架也可以但要注意灯架本身的晃动有人走动或者开关门引起震动时画面会抖对跟踪算法的干扰不容小觑。注意安装相机前先确认球桌上的灯光条件。台球厅的顶部灯经常只照亮局部台面会造成一边亮一边暗这会让球体检测的置信度波动非常大。如果条件允许尽量在均匀光照下安装。2.2 球台坐标系与镜头畸变校正相机装好之后画面里看到的是透视畸变之后的图像即使相机已经尽量垂直广角镜头还是会带来桶形畸变。我们需要做一个“图像坐标到真实台面坐标”的映射这一步如果跳过后续的距离计算、轨迹判断都会有系统性误差。畸变校正的常规做法是棋盘格标定打印一张棋盘格平铺在台面上。拍摄5到10张不同角度的照片。用OpenCV的cv2.calibrateCamera计算内参和畸变系数。得到矫正映射后提前一次性生成矫正后的图像运行时直接调用不需要每帧重复计算。真实台面坐标系的建立简单的方式是在画面里手动标定台面四个角的像素位置然后用透视变换映射到标准台面尺寸比如中式八球的台面是2540x1270mm。这样后续求球速、判断是否碰库都是在标准毫米坐标系里计算而不是在像素坐标系里瞎估。实操心得标定完第一次之后把透视变换矩阵保存成配置文件。下次系统重启直接加载不再需要重新标。但要注意相机如果被人碰过、支架松了必须重新标定否则位置信息全部偏移这个坑很多人踩过。3. 核心算法球体检测与持续跟踪3.1 球体检测传统视觉与深度学习的取舍球体检测我先后试了两套方案一套是传统的霍夫圆检测一套是基于深度学习的YOLO系列。两者各有利弊我分别说说实际效果。霍夫圆检测的好处是零训练成本直接对着灰度图跑cv2.HoughCircles就能得到候选圆。在光照均匀、台面干净的情况下它能稳稳地找到所有球。但它的硬伤也很明显对参数极其敏感minDist、param1、param2这套参数换一个球房就要重新调而且遇到球和球紧贴、球上有品牌Logo这类情况容易出现漏检或误检。YOLO方案需要提前准备数据集但一次训练完之后泛化能力比霍夫圆强得多。我自己标了大概2000帧图像涵盖了不同球色、不同聚堆情况用小模型yolov8n训练在CPU上单帧推理大约80msGPU上可以跑到实时。检测精度和稳定性都远超霍夫圆。如果让我给建议做原型跑通逻辑可以用霍夫圆十几行代码就能跑出结果做成一个能长期用的产品级系统直接上YOLO把数据积累做好别在传统视觉上浪费太多时间。3.2 颜色分类与识别检测到球的位置之后下一步是分辨每颗球的颜色。台球一共16颗球1颗白球、15颗彩球7色加黑八每种颜色两颗其中一颗是带白底的条纹球。颜色识别的准确率直接关系到“哪个球属于谁”的判断。颜色分类的流程我分成三步把检测框内的像素从RGB转到HSV空间。统计主色调确定球的颜色类别。用球的颜色和纹理特征区分“全色球”和“花色球”。HSV空间里H色调对光照变化相对不敏感比直接用RGB做阈值稳定得多。彩色球的主色调在HSV里都有相对固定的范围比如黄球的H值大概在20到35之间红球在0到10附近。有个细节容易翻车球面上的品牌Logo或者数字标号会干扰主色调统计。解决方法是取检测框中心区域的像素做统计因为球面Logo一般在靠近边缘的位置中心区域的颜色基本就是球的底色。注意白色球和银色球不要靠颜色硬分。白球在图像里经常会被高光打成一片白甚至和台面颜色接近。建议先单独检测白球方法是寻找台面上最亮、且饱和度最低的圆形区域如果找不到再考虑用轨迹预测的历史位置来补偿。3.3 帧间跟踪与轨迹处理检测是一帧一帧做的事情但“跟踪”要求我们把前后帧的同一颗球关联起来。如果每一帧都重新识别所有球那么只要某一帧漏检下一帧就得重新建立身份非常容易把球队的身份搞混。我用的方案是基于坐标距离的贪心匹配用上一帧所有球的位置预测下一帧的位置然后在预测位置附近找一个最近的检测结果距离小于阈值就认为是同一颗球。台球运动的特点是“大部分时间静止一杆之后快速运动”所以帧间位移很小的球可以直接用位置匹配并且非常稳定。匹配完成之后每颗球会带一条历史轨迹。这条轨迹有两个用途判断是否在运动以及运动方向预测下一帧位置辅助匹配球的运动速度可以根据帧间隔和位移算出来。比如30fps的摄像头一帧间隔约33毫秒一帧内球移动了10个像素换算到真实坐标大约是5毫米那么球速就是5毫米/33毫秒约0.15米/秒。用球速和方向可以判断球是刚被击中、在滚动还是已经静止。静止阈值我设在0.02米/秒低于这个值认为球停住了。轨迹数据还可以用来判断“是否进球”如果球的位置沿着一条直线接近袋口然后在某个袋口区域消失且之后几帧都没有再出现就认为这颗球已经落袋。4. 计分引擎与规则判断4.1 进球判定机制进球判定不能只看球是否在袋口附近消失因为球落到袋口还可能弹出来。我试过直接检测袋口圆形区域里是否有球效果不是很好因为袋口区域本身是深色的球进入后识别框会变模糊。后来我换了一种思路结合“轨迹终点”和“全局消失”两个条件。轨迹终点某颗球在连续几帧内向袋口方向运动并最终停在袋口附近。全局消失这颗球从全台面的检测结果中消失后续也没有重新出现。满足“轨迹接近袋口”并且“全局消失”才判定为进球。这两个条件同时成立误判率就低很多了。进球的归属判断需要结合当前双方指定的球色。系统在开球时需要知道双方分别打全色球还是花色球。这个判断在开球后第一颗非白球落袋时自动确定——哪方打进哪种球另一方就自动分到另一种。之后每次有球落袋如果颜色属于当前击球方计分加一如果是对方的球则算犯规。4.2 犯规与特殊局面处理犯规判断是计分系统里最容易被忽略、但实际使用中最容易出问题的地方。常见的犯规场景包括白球落袋自由球未击中己方球目标错误击球后没有球碰库白球落袋后碰到对方球用视觉来判断这些犯规难点在于“没有球碰库”这种负向事件。系统需要知道击球后是否发生了库边碰撞。我的做法是拿到球杆击中白球的瞬间之后持续监听所有球的碰撞事件。碰撞事件的判定依据是球速度方向的突变。比如白球击出后以0.8米/秒的速度向右运动碰到库边后瞬间反弹速度方向改变。当速度方向的改变超过45度、且在空间上靠近库边时就记一次碰库事件。如果一次击球后既没有球落袋也没有检测到任何碰库事件就判定为犯规。这个逻辑在实战中需要反复调参。因为球和球碰撞、球和库边碰撞、球速自然衰减到静止这三者的视觉表现不同。球的碰撞是一个瞬间的速度方向剧变自然减速则是速度缓慢下降、方向基本不变区分起来相对容易。黑八的处理是整个规则的收官环节。黑八被击入袋口时需要判断是哪一方击入的、是否在此之前已经把己方所有球清完。这两种情况分别对应胜出和输局。建议在UI上单独做一个状态显示明确提示“黑八已入袋本局结束”避免误判后观感混乱。5. 调试实录踩过的坑与优化技巧5.1 反光与阴影干扰的应对台球桌面是绿色毛呢表面有很强的纹理而且会在灯光下产生不规则反光。反光区域的颜色偏白偏亮和白色球非常接近。我用YOLO检测时反光区域偶尔会被误检成一个球。解决反光干扰用过两个比较有效的手段图像预处理时加一层饱和度和亮度的过滤反光区域通常饱和度过低、亮度过高不属于任何真实球的颜色范围直接过滤掉。在时间维度上加确认逻辑只有连续3帧以上都检测到的候选球才认为是真球。单帧的误检噪声基本被这个机制过滤掉了。阴影问题主要出现在球和球紧贴时在球之间的缝隙会产生深色阴影。这个对球的检测影响不大但对“球是否触碰”的判断会有干扰。如果系统需要判断球是否发生了碰撞建议用检测框之间的实际距离判断而不是用图像中的重叠面积。5.2 工程化配置与性能调优把算法跑通是一回事跑得稳定是另一回事。我在工程化过程中遇到的主要性能瓶颈在检测环节。YOLO模型在GPU上很流畅但部署到只有CPU的普通电脑上推理速度会掉到10到15帧虽然还能用但帧率不稳会直接影响跟踪质量。分享一下我在边缘设备上做性能调优时的几个压榨方案降低输入分辨率。YOLO输入从640降到416速度和精度的折中比较理想台球场景下球的尺寸偏小但416分辨率依然够用。把模型导出为ONNX或者TensorRT格式推理速度比PyTorch原生提升明显CPU上实测能快20%到30%。只在“球可能运动”的时刻跑全图检测静止周期内用上一帧的位置做静态保持大幅降低平均推理次数。检测之外跟踪模块也要注意性能。如果贪方便每帧都对所有球做全局匹配球多的时候开销会上去。更合适的做法是先按台面区域分块匹配只对邻近的球做配对复杂度从O(n²)降到线性。5.3 常见问题速查现象可能原因解决办法某颗球经常漏检球和台面颜色接近或反光干扰调高检测置信度阈值检查ROI区域是否被遮挡球的颜色识别错乱光照变化或球面Logo干扰改在HSV空间统计主色只取中心区域像素白球进入袋口后偶尔检测不到袋口深色背景下目标太小结合轨迹预测和消失判断不要依赖单帧检测进球事件漏判球落袋速度太快帧率不足提高相机帧率用轨迹终点速度方向辅助判断犯规误报球速阈值设置不合理记录多次正常击球的速度基线动态调整阈值画面一到晚上就不稳定灯光亮度变化加固定曝光重新做白平衡必要时调整检测阈值6. 经验总结与后续扩展空间整套系统做完我最大的感受是视觉识别算法本身已经不是门槛门槛在于“如何把视觉结果转化成可靠的规则判断”。检测、跟踪、计分三个环节任何一个出错都会影响最终的用户体验。尤其是真实台球场景光线复杂、球的碰撞频繁算法需要足够的鲁棒性才能在实战中稳定输出。如果后续想继续扩展我有几个方向在考虑第一加入球杆检测自动判断击球瞬间。现在系统通过检测球的运动启停来判断击球事件但如果能识别球杆的位置和运动轨迹就能更精确地捕捉“击球开始”这个时刻对计时的准确度和犯规判断都有帮助。第二多台相机的融合。俯视相机有一个天然的盲区袋口附近垂直于台面方向的遮挡如果球员的手恰好挡在袋口和相机之间球的轨迹可能被短暂遮挡。增加一到两台低角度相机用于袋口区域的补充观测能显著降低漏判率。第三不同规则的适配。目前主要针对8球规则但9球、斯诺克的计分逻辑差别挺大。把规则引擎抽象成配置文件通过切换规则模块来适配不同玩法是产品化必经的一条路。最后再分享一个小技巧开发阶段一定要保留录像回放功能。相机每帧都记录原始画面同时叠加检测框、轨迹、判定结果。出问题的时候回放录像能看到算法“是怎么想的”排查效率比对着日志猜高得多。我这里所有判定逻辑的调优几乎都是靠回放录像完成的。
返回列表