实用脚本统计交叉跑位造成威胁几次?

wen 实用脚本 2

统计交叉跑位造成威胁次数

下面给你一个可直接运行的 Python 脚本模板,用于统计足球/篮球等比赛中「交叉跑位造成威胁」的次数,你可以根据实际数据源(视频标注、追踪数据、事件日志)替换输入部分。

实用脚本统计交叉跑位造成威胁几次?


先定义“交叉跑位造成威胁”的判定规则

因为不同项目定义不同,脚本里把规则参数化:

条件 说明 参数
两名进攻球员轨迹交叉 距离小于阈值 cross_dist=2.0 米
交叉发生在危险区域 如禁区前沿/禁区 zone 区域
交叉后 3 秒内形成威胁 射门/关键传球/进入禁区 threat_window=3.0 秒
防守球员被吸引/失位 防守距离变化 defender_pull=1.5 米

只有 1+2+3(可选 4)同时满足,才计一次“威胁”。


脚本(基于追踪数据 DataFrame)

假设你有逐帧追踪数据,字段如下:

frame, time, player_id, team, x, y
import pandas as pd
import numpy as np
from itertools import combinations
# ============ 参数配置 ============
CROSS_DIST      = 2.0    # 两人距离小于2米算交叉
CROSS_ANGLE     = 30     # 轨迹夹角(度)突变阈值,可选
THREAT_WINDOW   = 3.0    # 交叉后3秒内
ZONE_X          = (70, 105)  # 危险区域 x 范围(进攻方向)
ZONE_Y          = (20, 48)   # 危险区域 y 范围
DEFENDER_PULL   = 1.5    # 防守被拉开距离
# ============ 读取数据 ============
df = pd.read_csv("tracking.csv")
df = df.sort_values(["frame", "player_id"])
# ============ 工具函数 ============
def in_danger_zone(x, y):
    return ZONE_X[0] <= x <= ZONE_X[1] and ZONE_Y[0] <= y <= ZONE_Y[1]
def dist(a, b):
    return np.hypot(a[0]-b[0], a[1]-b[1])
# ============ 主逻辑 ============
events = []          # 记录所有交叉事件
threat_count = 0     # 威胁次数
frames = sorted(df["frame"].unique())
for i, f in enumerate(frames):
    cur = df[df["frame"] == f]
    # 只看进攻方
    attackers = cur[cur["team"] == "attack"]
    defenders = cur[cur["team"] == "defend"]
    # 两两组合检查交叉
    for p1, p2 in combinations(attackers.itertuples(), 2):
        d = dist((p1.x, p1.y), (p2.x, p2.y))
        if d > CROSS_DIST:
            continue
        # 是否在危险区域
        if not (in_danger_zone(p1.x, p1.y) or in_danger_zone(p2.x, p2.y)):
            continue
        # 检查交叉后 THREAT_WINDOW 秒内的威胁事件
        t0 = p1.time
        future = df[(df["time"] > t0) & (df["time"] <= t0 + THREAT_WINDOW)]
        threat = False
        # 示例:未来窗口内有人进入禁区或射门
        for r in future.itertuples():
            if r.team == "attack" and in_danger_zone(r.x, r.y):
                threat = True
                break
        # 可选:防守被吸引
        if threat and len(defenders) > 0:
            min_def_dist = min(dist((p1.x, p1.y), (d.x, d.y))
                               for d in defenders.itertuples())
            if min_def_dist > DEFENDER_PULL:
                pass  # 记录用,不强制
        if threat:
            threat_count += 1
            events.append({
                "frame": f,
                "time": t0,
                "player1": p1.player_id,
                "player2": p2.player_id,
                "x": p1.x, "y": p1.y
            })
# ============ 输出 ============
print(f"交叉跑位造成威胁次数: {threat_count}")
print(pd.DataFrame(events))

输出示例

交叉跑位造成威胁次数: 7
   frame  time  player1  player2     x     y
0    320   8.2        9       11  82.3  30.1
1    415  10.6       11        7  88.5  28.4
...

如果你没有追踪数据,只有事件日志

可以用更简单的版本——人工/半自动标注:

import pandas as pd
# 事件表: time, type, player, x, y, note
events = pd.read_csv("events.csv")
# 找出 “交叉跑位” 且 note 含 “威胁” 的事件
threats = events[
    (events["type"] == "cross_run") &
    (events["note"].str.contains("威胁", na=False))
]
print(f"交叉跑位造成威胁次数: {len(threats)}")
print(threats)

想更准?可以加这些增强项

  1. 轨迹夹角:用前后几帧算速度向量,夹角 > 30° 才算真交叉。
  2. 防守反应:交叉后防守球员重心偏移 > 1.5 米。
  3. xG/威胁值:交叉后 3 秒内 xG 增量 > 0.05。
  4. 可视化:用 matplotlib 画出交叉点 + 威胁路径。

如果你告诉我:

  • 项目是足球还是篮球?
  • 数据是视频、追踪、还是手工事件表?
  • 危险区域怎么定义?

我可以帮你把脚本改成直接能跑你数据的版本。

上一篇实用脚本复盘称哪次射门最具决定性?

下一篇当前分类已是最新一篇

抱歉,评论功能暂时关闭!