前言
SPORTS是一个由Roboflow开发且开源的一套专注于体育分析的基于Python的计算机视觉工具包。项目的github地址为:https://github.com/roboflow/sports/tree/main。这篇文章就是介绍如何在自己的电脑上配置好这个程序需要的环境,以及训练对应的模型,并简单的使用这个Python库进行简短的足球比赛的分析。
本文使用电脑配置
本文使用的配置为: Windows10,Python环境(使用了Python 3.9.13),使用Pycharm IDE,机器配置为48核心+192G运行内存+90G显存(使用NVIDIA A6000显卡*2)。(如果电脑性能不好,别灰心,本文我提供了训练好的权重,可直接下载使用)
在开始前需要准备的
创建虚拟环境
我们本次使用VENV虚拟环境,首先在Pycharm中创建项目的时候创建一个虚拟环境,如图1所示。
安装显卡驱动
电脑中需要有NVIDIA显卡驱动,这不是本文的重点,所以不细说。
安装PYTORCH
由于后面运行的时候,有一个步骤会使用pip安装Pytorch,但是在这个步骤中使用pip安装的Pytorch是仅使用CPU的版本的,无法使用GPU。所以我个人建议先提前将Pytorch安装好。
Pytorch官网网址:https://pytorch.org/
从官网中拷贝下载命令(请一定选好对应的平台),如图2红圈圈出的命令所示,在虚拟环境下运行这个命令从而安装Pytorch。请注意,这个安装需要较好的网络环境,并且可能会耗费大量的流量。
安装好后可以使用下面我编写的python程序检测下是否正确配置好了。
import torch
def q2019_check_torch():
print("===== Q2019的简易PyTorch 安装检查 =====")
print(f"当前PyTorch 版本: {torch.__version__}")
cuda_ok = torch.cuda.is_available()
print(f"当前CUDA 是否可用: {cuda_ok}")
if cuda_ok:
print(f"CUDA 设备数量: {torch.cuda.device_count()}")
print(f"当前 CUDA 设备: {torch.cuda.current_device()}")
print(f"CUDA 设备的名字: {torch.cuda.get_device_name(0)}")
else:
print("未检测到可用的 CUDA,可能是驱动/环境未配置好。")
if __name__ == "__main__":
q2019_check_torch()
正确配置后这个程序输出的内容应该如下
===== Q2019的简易PyTorch 安装检查 =====
当前PyTorch 版本: 2.8.0+cu126
当前CUDA 是否可用: True
CUDA 设备数量: 2
当前 CUDA 设备: 0
CUDA 设备的名字: NVIDIA RTX A6000
如果CUDA不可用,强烈建议先去想办法解决这个问题,否则后面训练模型的速度会非常非常慢!甚至单纯的推理都会很吃力。
备注:torch的安装不强制要求与显卡的CUDA版本相同。
从源码安装sports库
Sports库不在官方包索引中[1],需要从源码安装。执行下面的命令完成安装
pip install git+https://github.com/roboflow/sports.git
训练模型
这个程序包默认是没有带模型权重的,需要我们自己训练几个模型,否则sports库是无法使用的。下面这个板块就是用来介绍如何自己训练模型权重文件出来(pth文件)。
下载源码
在项目的GitHub页面中,roboflow提供了一些示例代码以及训练,我们前往https://github.com/roboflow/sports/tree/main 点击DownloadZIP将代码文件下载下来(当然,如果乐意的话你也可以用git来拉取)。下载完后解压这个压缩包,解压后的文件夹结构如图3所示,建议将这个包拖动到Pycharm中打开,这样方便我们后续进行运行。
准备好获取数据集的APIKEY
在我们开始训练模型之前,我们先要准备好数据集。好消息是roboflow已经给我们准备好了一些数据集,无需我们手动在网上下载其他数据集。只需要我们在代码中配置好环境变量,程序运行的时候是会自动下载数据集。(当然,我们也可以使用自己准备的数据集)
我们前往roboflow的网站(地址:Sign in to Roboflow )这个站点 注册一个账号。注册完之后,如图5中红框框圈出的部分,点击左侧栏的settings,在弹出的二级菜单中,点击API keys,在右侧新出现的界面,复制给出的好Private API Key,这个我们后面需要拉取数据的时候用到。
训练足球检测模型的权重
现在开始,我们就使用roboflow提供的训练代码来训练出模型。我们首先训练足球检测的模型。
请在pycharm中打开刚刚下载的train_ball_detector.ipynb这个文件(文件路径为 下载目录/sports-main/examples/soccer/notebooks/train_ball_detector.ipynb)。请注意,这个示例的笔记本是为google COLAB准备的,所以我们可能在后面运行的时候需要稍微修改下代码,我会详细介绍这个笔记本中每一步都是在做什么的。(当然,你也可以使用其他软件打开,我这边使用pycharm是因为方便)
检查基本环境
我们点击 ▶️按钮,开始正式执行这个笔记本。本小节对应笔记本中的 “Before you start”版块。本小节是检查计算机中是否有NVIDIA显卡,以及显示出当前程序的工作目录路径。执行后的结果如图6。
安装依赖以及调用
此小节对应笔记本中的的Install dependnecies以及Imports版块。这一步分别使用pip进行依赖安装以及在程序中导入相应的库。(备注:请依照我前面章节,提前安装pytorch,以免在此步骤安装了一个只能使用CPU进行运算的pytorch)
注意,执行导入库的时候会出现报错,由于我们是直接使用Pycharm打开的,没有Colab这个库(这个库只存在于Google的colab环境),直接将from google.colab import userdata调用注释掉即可。修改后如图7所示。
备注:我将我运行环境的依赖详情放在了页脚,如果有需要可以前往下载:[3]
下载数据集
此小节对应笔记本中的Pull dataset版块。
这一步的步骤是让程序自动从roboflow下载训练所需要的数据集。默认情况下,笔记本中的程序会尝试调用colab库,获取API密钥。但是我们不是COLAB环境,所以程序读取不到其中API密钥的。但是!我们可直接将
ROBOFLOW_API_KEY = userdata.get('ROBOFLOW_API_KEY')
这个命令替换为
ROBOFLOW_API_KEY = “前文中我们获取的API秘钥”
(备注:我这里是为了方便起见,真正完善的做法是将密钥写到环境变量中,程序读取环境变量)
执行完这个可以看到notebooks下面出现了个文件夹,叫做football-ball-detections-2这个文件夹。
请注意下,下一步执行的下述命令
!sed -i 's|\(train: \).*|\1../train/images|' {dataset.location}/data.yaml
!sed -i 's|\(val: \).*|\1../valid/images|' {dataset.location}/data.yaml
这一串代码可以删除掉,这串命令作用仅仅是用于配置下数据集路径的位置,但是其实下载好的文件中是已经配置好了的(我已经测试过,删除掉没有什么影响,不删除的话则在windows环境下会报错'sed' 不是内部或外部命令,也不是可运行的程序或批处理文件。
)如图8。
训练模型
本小节对应笔记本中的Custom training板块,到这一个步骤就是开始训练自定义模型了(使用Yolo进行训练)。请注意!这个训练比较吃计算机的性能,我使用本次写博客时候用的计算机,训练占用运存45G,显存40G,并且花费了2个小时才训练完成。
训练完成的结果如图9所示,输出有乱码是正常的,无需担心。
训练时候如果有提示
using dhist requires you to install the `pickleshare` library.
这个报错无需过于担心,这只是提醒你没有安装一个管理shell命令行命令历史的小程序,这个程序不是必须的,对模型的训练没有任何影响。
对于下一步的下述指令
ls {HOME}/runsforpitchkeypointdetector/detect/train/
这个指令可以直接删除,其唯一的用处只是显示运行结果,此指令在windows下执行会出现错误。
训练好的权重文件存在于:下载目录/sports-main/examples/soccer/notebooks/runs/detect/train/weights/ 目录中,请将其中的best.pt拷贝出来,命名为football-ball-detection.pt,先存在别的地方,后续还有需要。(best.pt是最佳权重,last.pt是最后一次的权重文件,我们只需要最佳权重)
该模块剩下的部分只是用来展示一些训练出来的结果图,故不仔细介绍,只放一个运行结果截图(图10)在下面。
验证自定义模型
对应笔记文件的Validate custom model模块,专门用于验证自定义的模型,验证训练出的模型的效果是怎么样的。
这里要提下运行后程序输出的关键指标
Class Images Instances Box(P R mAP50 mAP50-95): 100% (这里是显示进度条,复制的时候这里可能会成乱码) 8/8 1.8it/s 4.4s
all 121 121 0.865 0.851 0.917 0.601
其中的最后一行即是性能指标,在这个结果中,第一个121(Images)代表验证集总共121个图像,第二个121(Instances)代表总共有121个标记的实例(本次训练中,这个实例是足球),0.865(”Box(p” )代表了准确率,0.851(R)代表了回召率,0.917(mAP50)代表了平均精度,0.601(“mAP50-95”)代表了更严格的平均进度
上传训练好的模型(此步骤不推荐执行)
对应笔记本中的Deploy model on Roboflow这个过程。这个步骤唯一的用处就是将刚刚训练的权重发送等到ROBOFLOW这个平台上面,我建议跳过这个步骤,没有必要上传权重。
训练球场检测模型的权重
这个模型是用于球场检测的,其训练笔记本也位于 下载目录/sports-main/examples/soccer/notebooks/train_pitch_keypoint_detector.ipynb ,训练流程和训练足球检测模型的权重是一样的,具体流程不在这里赘述了。
个人建议:如果运行时在同一个目录下面,建议将之前的运行的足球检测模型训练时产生的runs目录给删掉或者重命名或移动到别的地方,以免出现混淆的情况。
这个模型训练我花费了20分钟。训练后请同样将 下载目录/sports-main/examples/soccer/notebooks/runs/pose/train/weights/中的best.pt拷贝出来(请注意,这里是runs目录下的文件夹不是detect目录,而是pose了),并命名为football-pitch-detection.pt,以便后续使用。
训练球员检测模型
此模型用来检测球场上的球员的,训练笔记位于/sports-main/examples/soccer/notebooks/train_player_detector.ipynb,这个训练我的电脑花费了30分钟,当然,也请将/sports-main/examples/soccer/notebooks/runs/pose/train/weights/(这里run下面的目录则又变回了pose了)中的best.pt复制下来,重命名为football-player-detection.pt,为后续用途做准备。
我电脑训练不了权重怎么办?
确实,训练这三个模型对电脑性能要求非常非常的高,有时候我们手上可能很不幸没有符合性能需求的电脑。所以我把我训练好的3个模型权重文件放到了github上,供给有需求的人进行下载。
下载链接:https://github.com/q2019715/sports-pt/releases/tag/0.0.1 [2]
使用模型
刚刚我们只是训练模型,现在我们就是真正的要来运行启用这个模型。
这里插一句嘴:其实刚刚我们的训练的过程中并没有调用sports这个库,训练过程跟sports无关,训练出来的是一个YOLOv8的Pytorch权重文件。但是我们使用模型的时候会需要用到sports库,(其实严格来说,不需要使用sports库也能使用我们刚刚训练的那些模型)
我们首先找到 下载目录/sports-main/examples/soccer/main.py 这个文件,这个文件就是官方的一个使用例子。找到后请跟着步骤接着执行下去。
在这里说明一下,本章节我提到要修改的代码,全部都是修改这个main.py,不需要修改其他的源代码。
我从网上摘了某场比赛一小段的录屏,使用我们刚刚训练的权重以及sports库进行分析,我会在后续对应的模块中嵌入这些视频,这样更能方便大家理解程序做了些什么。视频一就是我们要分析的例子视频的源文件。(为了保证服务器流畅运行,此视频已经被我压缩,清晰度较低).[2]
放置权重
在main.py的同级目录下,新建一个data文件夹,将刚刚训练好/下载好的 三个权重(football-pitch-detection.pt、football-player-detection.pt、football-ball-detection.pt)复制到data文件夹里头。(即文件应该在 下载目录/sports-main/examples/soccer/data/这个文件夹中 )。
进行球员检测
使用下面的命令对数据进行检测,(请注意,不加–device参数则不会使用显卡进行运算)。
其中–source_video_path是输入文件路径。–target_video_path对应的是输出文件路径
python main.py --source_video_path data.mp4 --target_video_path out1.mp4 --device cuda:0
如果没有CUDA的话,可以使用下面的命令来执行(执行会非常非常非常的缓慢)。
python main.py --source_video_path data.mp4 --target_video_path out1.mp4
球员检测常见问题
highgui报错
执行的时候会出现下面的报错:如图11。
cv2.error: OpenCV(4.10.0) D:\a\opencv-python\opencv-python\opencv\modules\highgui\src\window.cpp:1301: error: (-2:Unspecified error) The function is not implemented. Rebuild the library with Windows, GTK+ 2.x or Cocoa support. If you are on Ubuntu or Debian, install libgtk2.0-dev and pkg-config, then re-run cmake or configure script in function 'cvShowImage'
这是因为程序中的OPENCV 尝试将图像输出到窗口,但是pip install安装的opencv-python(就是我们刚刚下载的依赖包,在jupyterz笔记本中执行的那个)缺少highgui的支持,导致程序出现了崩溃的问题。
解决方案有两种
1、修改源代码,让这个程序不输出到窗口(我就是这个样子做的)。将main.py中416行到419的下面内容注释掉(如图12圈出的部分)。(如果后续版本行数有变化,只需要在代码中查找cv2.imshow("frame", frame)
)
cv2.imshow("frame", frame)
if cv2.waitKey(1) & 0xFF == ord("q"):
break
cv2.destroyAllWindows()
2、安装完整的openCV环境,(尝试在有GUI的环境中安装,即不在Jupyter中安装),具体详情本文就不演示了
终端长时间卡住
在没有显卡的时候,这个程序运行分析是需要一些时间的,分析的时候终端是没有响应的(就像是卡死了一样)。所以,如果真的有需要的,我们可以手动给他修改下,让他隔一段时间显示下正在运行。只需要在刚刚注释掉的部分的前面,内容“sink.write_frame(frame)”(414行下面),加上print(“程序正在处理”),让程序每运行一小段就在终端输出“程序正在处理”,告诉我们程序正在运行,如图13,其中高亮显示的是我们添加的代码。
球员检测分析效果视频
如视频二
执行雷达视图检测
执行下述命令(相比上一个命令添加了–mode RADAR这个参数)即可执行雷达图检测。
python main.py --source_video_path data.mp4 --target_video_path out2.mp4 --mode RADAR --device cuda:0
执行雷达图常见问题
Supervision导致的兼容错误
报下面的错误
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
这个原因其实是由于Supervision造成的,Supervision最新版本与这个程序不兼容,我们只需降低supervision的版本即可,执行下面命令降低supervision库版本。
pip install supervision==0.23.0
在配置过程中,如果出现类似下面的错误,请检查一下Jupyter是不是没有正确关闭,建议关闭Pycharm或重启电脑后再次打开
ERROR: Could not install packages due to an OSError: [WinError 5] 拒绝访问。: 'C:\\Users\\admin\\Documents\\ZYL\\SPORT\\Q2019SPORT\\.venv\\Lib\\site-packages\\~il\\_avif.cp39-win_amd64.pyd'
Check the permissions.
识别的关键点不足导致报错
报错代码如下
AttributeError: type object 'Color' has no attribute 'WHITE'
这个是由于当前这一帧的时候,球场的关键点不足,导致程序会报错,这个报错极少出现,只会在特定的视频处理的时候发生。
处理方法:修改原有的render_rader函数,将原来函数中的
mask = (keypoints.xy[0][:, 0] > 1) & (keypoints.xy[0][:, 1] > 1)
修改为我优化过的版本:
# —— 兜底:该帧没有检到球场关键点 / 点数不足时候处理 —— #
if keypoints is None or keypoints.xy is None or len(keypoints.xy) == 0:
return draw_pitch(config=CONFIG)
pts = keypoints.xy[0] # (N, 2) 或空
if pts is None or pts.size == 0:
return draw_pitch(config=CONFIG)
mask = (pts[:, 0] > 1) & (pts[:, 1] > 1)
# 计算单应性至少需要 4 个点
if mask.sum() < 4:
return draw_pitch(config=CONFIG)
这个修改主要是修改了程序的行为,现在碰到没有检查到足够的球场关键点,那么就会直接返回一张空的球场底图。不会触发报错。
雷达图生成效果
如视频三所示
一些其他的功能
后续还有很多功能,我就不一一在这里演示了,使用这些功能只需要修改程序–mode 参数后跟着的参数即可。可用的参数列表如下
参数值 | 参数功能 |
PITCH_DETECTION | 球场标定 |
BALL_DETECTION | 足球检测 |
PLAYER_TRACKING | 球员跟踪 |
TEAM_CLASSIFICATION | 分类归属 |
其他功能执行结果示例
下面的视频四是执行BALL_DETECTION的结果视频,其他的我就不在这里展示了
总结
就如SPORTS的说明一样,SPORTS作为一个综合物体检测、图像分割和关键点检测等功能的一个综合工具包,不仅能用于体育检测,也能扩展用于其他很多的地方。值得我们研究与借鉴。