本文目录导读:

分析球员跑动热点图(Heatmap)通常涉及数据获取、坐标映射和可视化三个核心步骤,由于国际足联(FIFA)和主流联赛的官方追踪数据(如STATS、Opta)多为商业机密,普通开发者常用公开的赛事数据或计算机视觉(CV)来生成。
以下提供一个从零开始的实用脚本分析方案,涵盖基于公开数据(如StatsBomb)和基于视频(半自动)两种主流路径。
基于公开事件数据的静态热点图(最常用、最准确)
这是最推荐的方案,如果你能获取到包含X/Y坐标的事件数据(例如StatsBomb的公开数据集),脚本会非常简单。
适用场景:赛后分析、战术复盘。
核心库:pandas(数据处理)、matplotlib + mplsoccer(足球场绘图)。
环境准备
pip install pandas matplotlib mplsoccer
核心脚本逻辑
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mplsoccer import Pitch, VerticalPitch
# --- 假设你已加载数据:DataFrame包含 [player_name, x, y, type] ---
# 数据来源可以是 StatsBomb 开源数据 或 你自己抓取的坐标数据
# df = pd.read_csv('match_events.csv')
def analyze_heatmap(df, player_name='某球员'):
# 1. 数据过滤:筛选目标球员的所有触球/跑动事件(通常排除门将)
player_df = df[(df['player_name'] == player_name) & (df['type'] != 'Goal')]
if player_df.empty:
print(f"未找到球员 {player_name} 的数据")
return
# 2. 数据清洗:过滤异常的坐标点(通常在0-120,0-80之间)
player_df = player_df[(player_df['x'] >= 0) & (player_df['x'] <= 120) &
(player_df['y'] >= 0) & (player_df['y'] <= 80)]
# 3. 绘制球场和热力图
pitch = Pitch(pitch_type='statsbomb', pitch_color='grass', line_color='white',
stripe=True) # 使用 StatsBomb 标准球场
fig, ax = pitch.draw(figsize=(12, 8))
# 关键点:使用 KDE 核密度估计来生成平滑的热力图
# 注意:kdeplot 的 x, y 坐标需要转换比例(StatsBomb的x最大120,y最大80)
sns.kdeplot(
data=player_df[['x', 'y']],
x='x', y='y', # 或者使用 x='x', y='y'
ax=ax,
fill=True, # 填充颜色
cmap='hot', # 使用热度色系,如 'hot', 'inferno', 'plasma'
levels=50, # 等高线密度
thresh=0.05, # 过滤掉低于5%密度的区域,让图更干净
alpha=0.8,
bw_adjust=0.8 # 带宽调整,数值越小越尖锐,越大越平滑
)
# 4. 标注球员名字
ax.set_title(f'{player_name} Run Heatmap', fontsize=16, fontweight='bold')
# 5. 保存图片
plt.savefig(f'heatmap_{player_name}.png', dpi=300, bbox_inches='tight')
plt.show()
print(f"热点图已保存为 heatmap_{player_name}.png")
# 示例调用
# analyze_heatmap(df, 'Lionel Messi')
核心点解析:
Pitch对象:mplsoccer库自带了球场绘制,无需手动画线。kdeplot:这是生成热力图的关键函数,它将离散的跑动坐标点转换为连续的概率密度分布,红色表示高频活动区域。- 坐标系转换:StatsBomb数据用的是
x: 0-120,y: 0-80。
基于视频追踪的半自动脚本(进阶与实用场景)
如果你没有官方数据,只有比赛录像,就需要用目标跟踪(如YOLO)来完成。
适用场景:业余联赛分析、无法拿到转播数据的比赛。
核心库:opencv-python、ultralytics(YOLOv8)、numpy。
脚本思路:这比方案一复杂得多,这里给出简化的流程骨架:
import cv2
from ultralytics import YOLO
import numpy as np
# 1. 加载预训练模型(需训练或下载能识别足球球员的权重)
model = YOLO('yolov8x.pt')
def video_to_heatmap(video_path, target_player_id=1):
cap = cv2.VideoCapture(video_path)
positions = [] # 存储坐标
# 2. 需要在视频第一帧手动选定你要分析的球员
ret, frame = cap.read()
bbox = cv2.selectROI("Select Player", frame) # 手动框选目标球员
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 3. 将裁剪区域送入模型或使用光流法跟踪
# 简易方法:使用模板匹配或均值漂移(CamShift)
# 复杂方法:每帧检测所有球员,通过IoU匹配ID
# 伪代码:假设拿到该球员中心点坐标 (cx, cy)
# positions.append((cx, cy))
# 4. 透视变换(可选):将像素坐标映射到2D战术板的球场坐标
# 这一步需要利用球场四条边线或角球点建立单应性矩阵
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 5. 将收集的像素坐标转换为2D平面坐标后,使用相同的 kdeplot 绘制
# 注意:这里的坐标尺度可能不是0-120,需要归一化
cap.release()
cv2.destroyAllWindows()
关键点:如何将数据变成真正有用的“跑动方向”?
单纯的静态热力图只能显示活动范围,如果希望展示跑动方向,建议叠加箭头或轨迹线。
增强脚本建议:
- 增加时间戳:如果数据包含时间,可以按时间排序,用线连接坐标点,并在头部画箭头,即可生成“跑动轨迹图”。
- 区分攻防:判断当球在前场时和在后场时,球员的坐标分布,分别生成“防守热力图”和“进攻热力图”,对比分析。
- 速度指标:如果数据频率高(如25Hz),计算相邻两帧的距离差与时间差,得出速度,并过滤出冲刺时的坐标点来画图,用于分析高强跑动。
总结与实用建议
- 优先找数据:如果你是做实用分析,先想想哪里能拿到带坐标的数据。StatsBomb开源数据是目前最好用的免费资源,支持英超、西甲、世界杯等。
- 不建议视频识别:除非你有极强的CV背景,否则从视频还原坐标精度极低且耗时巨大,不适合日常分析。
- 可视化细节:
- 推荐使用
cmap='viridis'(色盲友好)或者cmap='plasma'。 - 建议将
thresh参数调高一些(0.1),可以去除噪音,让有意义的“热点”更突出。 - 如果分析守门员,记得单独处理球场禁区范围。
- 推荐使用
如果你能提供具体的数据格式示例(比如有哪些列),我可以帮你写出完全适配的、可以直接跑通的完整代码。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播