本文目录导读:

这是一个非常具体且偏向体育数据分析(尤其是足球、篮球等)的问题,为了给你一个实用的脚本,我需要先明确统计的定义和数据来源。
由于我无法直接观看比赛视频,通常这类统计需要基于事件数据(如StatsBomb、Opta、Wyscout的XML/JSON文件)或人工标注的Excel表格。
下面我提供一个基于 Python 的实用脚本,并给你两种模式:处理结构化数据 和 处理手工记录,你可以根据自己的情况选择。
核心定义(请先确认你的标准)
在写脚本前,必须明确什么算“犯规战术阻止反击”,通常满足以下条件:
- 球队失去球权(传球失误、被抢断)。
- 对方获得球权并试图向前推进(反击)。
- 防守方在中前场(或中场区域)立刻对持球人进行战术犯规(拉拽、铲球犯规、阻挡)。
- 裁判吹停比赛,且未出牌或仅出示黄牌(红牌通常不算战术犯规,因为代价过大)。
处理“结构化事件数据” (JSON格式)
假设你有一份比赛事件数据(例如来自StatsBomb),每个事件有 type 和 possession 信息。
import json
def count_tactical_fouls(events):
"""
统计战术犯规阻止反击的次数。
逻辑:搜索 'Foul' 事件,检查该犯规前 5 秒内是否发生 'Ball Loss'(丢失球权)且处于防守方半场。
"""
count = 0
fouls = [e for e in events if e.get('type', {}).get('name') == 'Foul']
for foul in fouls:
# 1. 判断是否在防守方半场(假设队伍是 home,犯规方是 home)
location = foul.get('location', [0, 0])
is_defensive_side = location[0] < 40 if foul['team']['name'] == 'Home' else location[0] > 60
if not is_defensive_side:
continue # 在本方禁区前沿犯规通常不算“阻止反击”
# 2. 往前查找 5 秒内的事件,看是否有丢失球权
lost_ball = False
for event in events:
if event['id'] == foul['id']:
break
# 简单的判断:如果前面有 Interception 或 Miscontrol
if event.get('type', {}).get('name') in ['Interception', 'Miscontrol']:
lost_ball = True
if lost_ball:
count += 1
return count
# 使用示例
# with open('match_events.json') as f:
# data = json.load(f)
# print("战术犯规防反次数:", count_tactical_fouls(data))
处理“手工记录” (Excel/CSV)
如果你是通过看录像后自己记录的,表格可能长这样: | 时间 | 犯规队 | 犯规人 | 是否阻止反击 | 地点 | 备注 | | :--- | :--- | :--- | :--- | :--- | :--- | | 23:45 | 主队 | 5号 | 是 | 中场 | 拉人 | | 30:12 | 客队 | 8号 | 否 | 后场 | 普通争抢 |
那么这个脚本就很简单了:
import pandas as pd
def count_from_manual_table(file_path='tactical_fouls.csv'):
"""从手动记录的CSV中统计次数"""
df = pd.read_csv(file_path)
# 方式1:直接计数标题为“是”的列
if '是否阻止反击' in df.columns:
count = df[df['是否阻止反击'] == '是'].shape[0]
print(f"战术犯规阻止反击次数: {count}")
return count
# 方式2:如果是视频剪辑软件生成的时间码列表
elif '时间' in df.columns:
# 假设所有记录都是战术犯规,只统计数量
print(f"记录次数: {len(df)}")
return len(df)
# 使用
# count_from_manual_table()
视频辅助分析 (进阶版)
如果你想通过分析视频的“死球”片段来自动识别,这涉及到计算机视觉,这里提供一个伪代码思路,告诉你如何用OpenCV辅助人工统计:
这个脚本的作用是:加速你的看片过程,它扫描视频,检测到裁判吹哨(往往伴随画面暂停或球员举手),然后自动截取片段,让你快速判断这次犯规是不是战术犯规。
import cv2
import numpy as np
# 伪代码,仅指示逻辑
def detect_break_in_play(video_path):
cap = cv2.VideoCapture(video_path)
fps = cap.get(cv2.CAP_PROP_FPS)
frame_count = 0
prev_frame = None
clips = []
while True:
ret, frame = cap.read()
if not ret:
break
# 1. 运动检测:计算帧差
if prev_frame is not None:
diff = cv2.absdiff(frame, prev_frame)
gray = cv2.cvtColor(diff, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5,5), 0)
_, thresh = cv2.threshold(blur, 25, 255, cv2.THRESH_BINARY)
movement = np.sum(thresh) / 255
# 2. 如果运动量突然骤降(从剧烈运动到静止),说明吹停了
if prev_movement > 5000 and movement < 500:
# 记录这个时间点(前3秒到后2秒)
clips.append((frame_count/fps - 3, frame_count/fps + 2))
prev_frame = frame.copy()
prev_movement = movement
frame_count += 1
cap.release()
# 输出需要人工检查的时间段
for start, end in clips:
print(f"请检查 {start:.1f}秒 到 {end:.1f}秒 是否为战术犯规")
总结建议
如果你是想快速出报告:
- 建议手工记录(用Excel),因为AI目前无法完美判断“战术意图”。
- 使用 方案二 的脚本,直接输入“是/否”,一键生成统计结果,并可以顺带生成饼图(如犯规区域分布)。
如果你是要处理大量比赛数据:
用 方案一,并确保数据里有 possession 和 location 字段。
请问你的数据源是什么? (是现成的数据库,还是需要从视频里手动标?)如果你能提供具体的文件格式(比如一个 CSV 表头),我可以把脚本改得更好用。