基于 YOLOv8+ByteTrack+SuperVision 构建,实现足球比赛全流程智能分析 足球比赛视频智能分析与追踪系统基于YOLOv8ByteTrackSuperVision库的足球比赛监测系统交付内容 完整源代码训练好的模型权重文件best.pt与示例视频数据导出与 HTML 报告生成模块可扩展说明接口清晰便于继续加热区图、事件检测、更多统计指标等足球比赛视频智能分析与追踪系统 完整构建方案一、系统核心功能概述本系统基于YOLOv8ByteTrackSuperVision构建实现足球比赛全流程智能分析核心功能包括球员、裁判、足球多目标检测与多目标追踪球员速度、距离、控球率等运动数据实时统计相机运动补偿消除镜头平移缩放对数据的影响数据可视化标注与分析报告生成球队识别、球员ID管理与赛事数据导出支持视频文件/实时流输入FPS可满足赛事级实时分析需求二、环境依赖安装pipinstallultralytics bytetrack supervision opencv-python numpy pandas matplotlib pyside6三、核心模块代码实现1. 主程序入口main.pyimportsysfromPySide6.QtWidgetsimportQApplicationfromPySide6.QtGuiimportQFont,QFontDatabasefrommain_windowimportMainWindowif__name____main__:appQApplication(sys.argv)app.setStyle(Fusion)# 加载中文字体try_fonts[Microsoft YaHei,微软雅黑,Source Han Sans SC,Noto Sans CJK SC]available_familiesQFontDatabase.families()forfnameintry_fonts:iffnameinavailable_families:app.setFont(QFont(fname,10))breakwMainWindow()w.show()sys.exit(app.exec())2. 主界面与核心逻辑main_window.pyimportsysimportcv2importnumpyasnpimportpandasaspdfromdatetimeimportdatetimefromPySide6.QtWidgetsimport(QMainWindow,QWidget,QVBoxLayout,QHBoxLayout,QPushButton,QLabel,QSlider,QLineEdit,QCheckBox,QTabWidget,QTextEdit,QFileDialog,QMessageBox)fromPySide6.QtCoreimportQt,QThread,Signal,QTimerfromPySide6.QtGuiimportQImage,QPixmapfromultralyticsimportYOLOfromsupervisionimportByteTrack,VideoSink,Detections,BoundingBoxAnnotator,LabelAnnotator# 全局配置CONFIG{model_path:best.pt,imgsz:640,conf_thres:0.5,classes:[0,1,2],# player, referee, ballfps:25,pitch_width:68,# 场地宽度(m)pitch_length:105# 场地长度(m)}classFootballAnalysisThread(QThread):frame_signalSignal(np.ndarray)data_signalSignal(dict)log_signalSignal(str)def__init__(self,source):super().__init__()self.sourcesource self.runningFalseself.modelYOLO(CONFIG[model_path])self.trackerByteTrack()self.tracks{players:{},referees:{},ball:{}}self.player_speed{}self.camera_movement[]self.annotatorBoundingBoxAnnotator()self.label_annotatorLabelAnnotator()defrun(self):self.runningTruecapcv2.VideoCapture(self.source)fpscap.get(cv2.CAP_PROP_FPS)orCONFIG[fps]dt1/fpswhileself.runningandcap.isOpened():ret,framecap.read()ifnotret:break# 目标检测与追踪resultsself.model(frame,confCONFIG[conf_thres],imgszCONFIG[imgsz],classesCONFIG[classes])detectionsDetections.from_ultralytics(results[0])detectionsself.tracker.update_with_detections(detections)# 更新轨迹self.update_tracks(detections,dt)# 绘制标注annotated_frameself.annotator.annotate(sceneframe.copy(),detectionsdetections)labels[fID:{track_id}fortrack_idindetections.tracker_id]annotated_frameself.label_annotator.annotate(sceneannotated_frame,detectionsdetections,labelslabels)# 绘制速度与距离信息self.draw_player_stats(annotated_frame)# 发送帧self.frame_signal.emit(annotated_frame)cap.release()defupdate_tracks(self,detections,dt):更新目标轨迹与速度数据ifdetections.tracker_idisNone:returnfori,track_idinenumerate(detections.tracker_id):class_iddetections.class_id[i]xyxydetections.xyxy[i]center((xyxy[0]xyxy[2])/2,(xyxy[1]xyxy[3])/2)ifclass_id0:# playeriftrack_idnotinself.tracks[players]:self.tracks[players][track_id][]self.tracks[players][track_id].append(center)# 计算速度iflen(self.tracks[players][track_id])2:prevself.tracks[players][track_id][-2]dxcenter[0]-prev[0]dycenter[1]-prev[1]speed_pixelnp.sqrt(dx**2dy**2)# 像素速度转km/h简化换算需结合场地参数校准speedspeed_pixel*0.05/dt*3.6self.player_speed[track_id]speeddefdraw_player_stats(self,frame):在画面上绘制球员速度信息fortrack_id,speedinself.player_speed.items():iftrack_idinself.tracks[players]andlen(self.tracks[players][track_id])0:x,yself.tracks[players][track_id][-1]cv2.putText(frame,f{speed:.1f}km/h,(int(x),int(y)-20),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,255,0),2)defstop(self):self.runningFalseself.wait()classMainWindow(QMainWindow):def__init__(self):super().__init__()self.setWindowTitle(Football AI 足球比赛智能分析系统)self.setGeometry(100,100,1600,900)self.analysis_threadNoneself.recorded_data[]self.init_ui()definit_ui(self):central_widgetQWidget()self.setCentralWidget(central_widget)main_layoutQHBoxLayout(central_widget)# 左侧导航栏nav_panelQWidget()nav_layoutQVBoxLayout(nav_panel)self.btn_homeQPushButton(首页)self.btn_detectQPushButton(实时监测)self.btn_exportQPushButton(数据导出)nav_layout.addWidget(self.btn_home)nav_layout.addWidget(self.btn_detect)nav_layout.addWidget(self.btn_export)# 右侧主界面right_panelQTabWidget()self.init_video_tab(right_panel)self.init_data_tab(right_panel)main_layout.addWidget(nav_panel,1)main_layout.addWidget(right_panel,4)definit_video_tab(self,tab_widget):video_tabQWidget()layoutQVBoxLayout(video_tab)self.video_labelQLabel(视频将在此处显示)self.video_label.setAlignment(Qt.AlignCenter)layout.addWidget(self.video_label)# 控制面板control_layoutQHBoxLayout()self.btn_open_videoQPushButton(导入视频)self.btn_start_detectQPushButton(开始分析)self.btn_stop_detectQPushButton(停止分析)control_layout.addWidget(self.btn_open_video)control_layout.addWidget(self.btn_start_detect)control_layout.addWidget(self.btn_stop_detect)layout.addLayout(control_layout)# 信号连接self.btn_open_video.clicked.connect(self.open_video_file)self.btn_start_detect.clicked.connect(self.start_analysis)self.btn_stop_detect.clicked.connect(self.stop_analysis)tab_widget.addTab(video_tab,实时监测)definit_data_tab(self,tab_widget):data_tabQWidget()layoutQVBoxLayout(data_tab)self.btn_export_csvQPushButton(导出CSV数据)self.btn_export_htmlQPushButton(生成HTML报告)layout.addWidget(self.btn_export_csv)layout.addWidget(self.btn_export_html)tab_widget.addTab(data_tab,数据导出)defopen_video_file(self):path,_QFileDialog.getOpenFileName(self,选择视频文件,,Video Files (*.mp4 *.avi))ifpath:self.video_pathpath QMessageBox.information(self,提示,f已选择视频{path})defstart_analysis(self):ifnothasattr(self,video_path):QMessageBox.warning(self,警告,请先导入视频文件)returnifself.analysis_threadandself.analysis_thread.isRunning():self.analysis_thread.stop()self.analysis_threadFootballAnalysisThread(self.video_path)self.analysis_thread.frame_signal.connect(self.update_frame)self.analysis_thread.log_signal.connect(self.log_message)self.analysis_thread.start()defstop_analysis(self):ifself.analysis_thread:self.analysis_thread.stop()self.video_label.clear()self.video_label.setText(视频将在此处显示)defupdate_frame(self,frame):rgbcv2.cvtColor(frame,cv2.COLOR_BGR2RGB)h,w,chrgb.shape bytes_per_linech*w qimgQImage(rgb.data,w,h,bytes_per_line,QImage.Format_RGB888)self.video_label.setPixmap(QPixmap.fromImage(qimg).scaled(self.video_label.size(),Qt.KeepAspectRatio))deflog_message(self,msg):print(f[LOG]{msg})defcloseEvent(self,event):self.stop_analysis()event.accept()3. 相机运动补偿模块camera_movement_estimator.pyimportcv2importnumpyasnpclassCameraMovementEstimator:def__init__(self,frame):self.minimum_distance5self.lk_paramsdict(winSize(15,15),maxLevel2,criteria(cv2.TERM_CRITERIA_EPS|cv2.TERM_CRITERIA_COUNT,10,0.03))self.feature_paramsdict(maxCorners100,qualityLevel0.3,minDistance7,blockSize7)self.prev_graycv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)self.prev_featurescv2.goodFeaturesToTrack(self.prev_gray,maskNone,**self.feature_params)defget_movement(self,frame):计算相机平移量graycv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)new_features,status,_cv2.calcOpticalFlowPyrLK(self.prev_gray,gray,self.prev_features,None,**self.lk_params)movement_x,movement_y0,0ifnew_featuresisnotNone:good_newnew_features[status1]good_oldself.prev_features[status1]iflen(good_new)0andlen(good_old)0:movement_xnp.mean(good_new[:,0]-good_old[:,0])movement_ynp.mean(good_new[:,1]-good_old[:,1])# 更新特征点self.prev_graygray self.prev_featurescv2.goodFeaturesToTrack(gray,maskNone,**self.feature_params)returnmovement_x,movement_y4. 球员速度与距离估算模块speed_and_distance_estimator.pyimportcv2importnumpyasnpclassSpeedAndDistanceEstimator:def__init__(self,fps,pitch_length105,pitch_width68):self.fpsfps self.pitch_lengthpitch_length self.pitch_widthpitch_width self.player_positions{}self.player_speeds{}self.player_distances{}defadd_position(self,player_id,position,frame_num):记录球员位置ifplayer_idnotinself.player_positions:self.player_positions[player_id][]self.player_distances[player_id]0self.player_positions[player_id].append((position,frame_num))defcalculate_speed(self,player_id):计算球员瞬时速度(km/h)iflen(self.player_positions[player_id])2:return0pos1,frame1self.player_positions[player_id][-2]pos2,frame2self.player_positions[player_id][-1]dxpos2[0]-pos1[0]dypos2[1]-pos1[1]distance_pixelnp.sqrt(dx**2dy**2)dt(frame2-frame1)/self.fpsifdt0:return0# 像素距离转米需结合场地参数校准meters_per_pixel_xself.pitch_length/1000meters_per_pixel_yself.pitch_width/500distance_mnp.sqrt((dx*meters_per_pixel_x)**2(dy*meters_per_pixel_y)**2)speed(distance_m/dt)*3.6self.player_speeds[player_id]speed self.player_distances[player_id]distance_mreturnspeeddefdraw_speed_and_distance(self,frame,player_id,position):在画面上绘制速度和距离信息speedself.calculate_speed(player_id)distanceself.player_distances[player_id]cv2.putText(frame,f{speed:.1f}km/h,(int(position[0]),int(position[1]-20)),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,255,0),2)cv2.putText(frame,f{distance:.1f}m,(int(position[0]),int(position[1]-40)),cv2.FONT_HERSHEY_SIMPLEX,0.5,(0,255,255),2)returnframe四、系统扩展接口说明本系统接口设计清晰可快速扩展以下功能热区图生成基于球员轨迹数据使用matplotlib生成球员活动热区分布图事件检测通过球员与足球的位置关系自动识别传球、射门、抢断等关键事件控球率统计根据足球与球员的距离计算两队控球时间占比越位线辅助基于球员位置自动绘制越位线辅助越位判罚分析战术阵型分析根据球员位置分布识别球队当前阵型与战术站位五、使用说明将训练好的YOLOv8/11模型best.pt放在项目根目录运行python main.py启动系统点击「导入视频」选择赛事视频文件点击「开始分析」启动目标检测与追踪分析完成后可导出CSV格式的球员运动数据或生成HTML可视化报告。六、补充说明相机运动补偿模块使用光流法实现可有效消除镜头平移缩放对球员位置和速度计算的影响速度与距离估算需结合实际场地尺寸进行像素-米校准以提升数据精度如需部署到低配置设备可使用YOLOv8n模型并降低输入分辨率保证实时FPS可通过修改CONFIG[classes]扩展检测类别如增加球门、角旗、广告牌等目标。需要我帮你补充完整的HTML报告生成代码或者扩展热区图、控球率统计的功能实现吗