news 2026/9/7 9:12:01

基于YOLO与OpenCV的高尔夫球实时追踪系统开发实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于YOLO与OpenCV的高尔夫球实时追踪系统开发实战

猫儿这个高尔夫捕手:从零实现一个智能高尔夫球追踪系统

在计算机视觉和运动分析领域,动物行为追踪一直是个有趣且具有挑战性的课题。最近在开发一个高尔夫球轨迹分析系统时,我意外发现家里的猫对滚动的高尔夫球表现出惊人的追踪能力,这启发了我将动物行为分析与运动物体检测技术相结合的想法。本文将完整分享如何构建一个基于OpenCV和YOLO的智能高尔夫球追踪系统,包含从环境搭建到算法优化的全流程实战代码。

无论你是计算机视觉初学者,还是希望将AI技术应用于体育分析的开发者,本文都能为你提供一套可落地的解决方案。我们将使用Python作为主要开发语言,结合OpenCV进行图像处理,YOLOv5进行目标检测,最终实现高尔夫球的实时追踪和轨迹分析。

1. 项目背景与核心概念

1.1 高尔夫球追踪的技术价值

高尔夫球追踪在体育训练、比赛分析和智能场馆建设中具有重要应用价值。传统的追踪方法依赖人工观察或昂贵的专业设备,而基于计算机视觉的解决方案可以大幅降低成本并提高分析效率。通过实时检测高尔夫球的运动轨迹,我们可以计算球速、飞行角度、落点预测等关键数据,为运动员和教练提供数据支持。

1.2 计算机视觉在运动分析中的应用

计算机视觉技术通过模拟人类视觉系统,让计算机能够"看懂"图像和视频中的内容。在高尔夫球追踪场景中,我们需要解决几个关键技术问题:目标检测(识别高尔夫球)、目标追踪(连续帧间的关联)、轨迹分析(运动路径计算)。本文将重点介绍前两个环节的实现方案。

1.3 系统架构概述

我们的智能高尔夫球追踪系统采用模块化设计,主要包含以下组件:

  • 视频输入模块:支持摄像头实时流和视频文件
  • 预处理模块:图像增强和噪声过滤
  • 目标检测模块:基于YOLOv5的高尔夫球识别
  • 追踪模块:基于卡尔曼滤波的多目标追踪
  • 分析模块:轨迹可视化和运动参数计算

2. 环境准备与依赖配置

2.1 系统环境要求

本项目在以下环境中测试通过,建议使用相似配置以获得最佳效果:

  • 操作系统:Windows 10/11, Ubuntu 18.04+ 或 macOS 10.15+
  • Python版本:3.8-3.10(3.11可能存在兼容性问题)
  • 内存:至少8GB RAM
  • 显卡:支持CUDA的NVIDIA显卡(可选,可加速推理)

2.2 创建虚拟环境

为避免依赖冲突,我们首先创建独立的Python虚拟环境:

# 创建虚拟环境 python -m venv golf_tracker # 激活虚拟环境(Windows) golf_tracker\Scripts\activate # 激活虚拟环境(Linux/macOS) source golf_tracker/bin/activate

2.3 安装核心依赖包

创建requirements.txt文件,包含项目所需的所有依赖:

# requirements.txt torch>=1.9.0 torchvision>=0.10.0 opencv-python>=4.5.0 numpy>=1.21.0 ultralytics>=8.0.0 # YOLOv8官方库 filterpy>=1.4.5 # 卡尔曼滤波实现 scipy>=1.7.0 matplotlib>=3.5.0 Pillow>=8.3.0

使用pip安装依赖:

pip install -r requirements.txt

2.4 验证安装

创建验证脚本检查关键库是否正常安装:

# verify_installation.py import torch import cv2 import numpy as np from ultralytics import YOLO print(f"PyTorch版本: {torch.__version__}") print(f"OpenCV版本: {cv2.__version__}") print(f"CUDA可用: {torch.cuda.is_available()}") # 测试基本功能 try: model = YOLO('yolov5n.pt') # 加载纳米版YOLOv5进行测试 print("YOLO模型加载成功") except Exception as e: print(f"YOLO加载失败: {e}")

3. 高尔夫球检测模型训练

3.1 数据集准备与标注

高质量的数据集是模型准确性的基础。我们需要收集包含高尔夫球在不同场景下的图像,并进行精确标注。

3.1.1 数据收集策略

收集数据时需要考虑以下场景多样性:

  • 不同光照条件(室内、室外、阴影)
  • 不同背景环境(草地、沙坑、天空)
  • 不同球体状态(静止、运动、半遮挡)
  • 不同拍摄角度和距离

建议收集500-1000张高质量图像,按8:1:1的比例分割为训练集、验证集和测试集。

3.1.2 数据标注工具使用

使用LabelImg或CVAT进行边界框标注,创建PASCAL VOC格式的标注文件:

<!-- 示例标注文件 annotations/image001.xml --> <annotation> <filename>image001.jpg</filename> <size> <width>1920</width> <height>1080</height> <depth>3</depth> </size> <object> <name>golf_ball</name> <bndbox> <xmin>850</xmin> <ymin>420</ymin> <xmax>890</xmax> <ymax>460</ymax> </bndbox> </object> </annotation>

3.2 YOLOv5模型配置

创建自定义的模型配置文件,针对高尔夫球检测进行优化:

# golf_ball_yolov5s.yaml # YOLOv5 🚀 by Ultralytics, GPL-3.0 license # 参数配置 nc: 1 # 类别数量(只有高尔夫球) depth_multiple: 0.33 # 模型深度倍数 width_multiple: 0.50 # 层通道倍数 # 锚点框配置(针对高尔夫球大小优化) anchors: - [10,13, 16,30, 33,23] # P3/8 - [30,61, 62,45, 59,119] # P4/16 - [116,90, 156,198, 373,326] # P5/32 # 骨干网络 backbone: # [来源, 重复次数, 模块, 参数] [[-1, 1, Focus, [64, 3]], # 0-P1/2 [-1, 1, Conv, [128, 3, 2]], # 1-P2/4 [-1, 3, C3, [128]], [-1, 1, Conv, [256, 3, 2]], # 3-P3/8 [-1, 9, C3, [256]], [-1, 1, Conv, [512, 3, 2]], # 5-P4/16 [-1, 9, C3, [512]], [-1, 1, Conv, [1024, 3, 2]], # 7-P5/32 [-1, 1, SPP, [1024, [5, 9, 13]]], [-1, 3, C3, [1024, False]], # 9 ] # 头部网络 head: [[-1, 1, Conv, [512, 1, 1]], [-1, 1, nn.Upsample, [None, 2, 'nearest']], [[-1, 6], 1, Concat, [1]], # 猫系骨干P4 [-1, 3, C3, [512, False]], # 13 [-1, 1, Conv, [256, 1, 1]], [-1, 1, nn.Upsample, [None, 2, 'nearest']], [[-1, 4], 1, Concat, [1]], # 猫系骨干P3 [-1, 3, C3, [256, False]], # 17 (P3/8-small) [-1, 1, Conv, [256, 3, 2]], [[-1, 14], 1, Concat, [1]], # 猫系骨干P4 [-1, 3, C3, [512, False]], # 20 (P4/16-medium) [-1, 1, Conv, [512, 3, 2]], [[-1, 10], 1, Concat, [1]], # 猫系骨干P5 [-1, 3, C3, [1024, False]], # 23 (P5/32-large) [[17, 20, 23], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5) ]

3.3 模型训练脚本

创建完整的训练脚本,包含数据加载、模型训练和验证:

# train_golf_detector.py import torch import yaml from pathlib import Path from ultralytics import YOLO import argparse def setup_training_config(): """配置训练参数""" config = { 'data': 'golf_ball_dataset.yaml', 'cfg': 'golf_ball_yolov5s.yaml', 'weights': 'yolov5s.pt', 'epochs': 100, 'batch_size': 16, 'img_size': 640, 'device': '0' if torch.cuda.is_available() else 'cpu', 'workers': 4, 'patience': 10, 'save_period': 10 } return config def create_dataset_yaml(): """创建数据集配置文件""" dataset_config = { 'path': './datasets/golf_ball', 'train': 'images/train', 'val': 'images/val', 'test': 'images/test', 'nc': 1, 'names': ['golf_ball'] } with open('golf_ball_dataset.yaml', 'w') as f: yaml.dump(dataset_config, f) def main(): # 创建数据集配置 create_dataset_yaml() # 设置训练配置 config = setup_training_config() # 加载预训练模型 model = YOLO(config['weights']) # 开始训练 results = model.train( data=config['data'], epochs=config['epochs'], batch_size=config['batch_size'], imgsz=config['img_size'], device=config['device'], workers=config['workers'], patience=config['patience'], save_period=config['save_period'] ) print("训练完成!模型保存在 runs/train/exp/weights/best.pt") if __name__ == "__main__": main()

4. 实时追踪系统实现

4.1 多目标追踪算法选择

针对高尔夫球追踪的特点,我们选择DeepSORT算法作为基础,结合自定义的卡尔曼滤波器进行优化:

# tracker.py import numpy as np from filterpy.kalman import KalmanFilter from scipy.optimize import linear_sum_assignment import cv2 class GolfBallTracker: def __init__(self, max_age=30, min_hits=3, iou_threshold=0.3): self.max_age = max_age # 最大丢失帧数 self.min_hits = min_hits # 最小确认命中次数 self.iou_threshold = iou_threshold # IOU匹配阈值 self.trackers = [] # 当前活动的追踪器 self.frame_count = 0 # 帧计数器 self.next_id = 1 # 下一个追踪ID def create_kalman_filter(self): """创建针对高尔夫球运动的卡尔曼滤波器""" kf = KalmanFilter(dim_x=7, dim_z=4) # 状态转移矩阵 [x, y, w, h, vx, vy, vw] kf.F = np.array([ [1,0,0,0,1,0,0], [0,1,0,0,0,1,0], [0,0,1,0,0,0,1], [0,0,0,1,0,0,0], [0,0,0,0,1,0,0], [0,0,0,0,0,1,0], [0,0,0,0,0,0,1] ]) # 测量矩阵 kf.H = np.array([ [1,0,0,0,0,0,0], [0,1,0,0,0,0,0], [0,0,1,0,0,0,0], [0,0,0,1,0,0,0] ]) # 协方差矩阵 kf.P[4:,4:] *= 1000. # 速度不确定性 kf.P *= 10. # 测量噪声 kf.R[2:,2:] *= 10. # 过程噪声 kf.Q[-1,-1] *= 0.01 kf.Q[4:,4:] *= 0.01 return kf def update(self, detections): """更新追踪器状态""" self.frame_count += 1 # 预测当前帧所有追踪器的位置 for tracker in self.trackers: tracker.kf.predict() # 匹配检测结果和现有追踪器 matched, unmatched_detections, unmatched_trackers = \ self.associate_detections_to_trackers(detections) # 更新匹配的追踪器 for detection_idx, tracker_idx in matched: detection = detections[detection_idx] self.trackers[tracker_idx].update(detection) self.trackers[tracker_idx].hits += 1 self.trackers[tracker_idx].time_since_update = 0 # 为未匹配的检测创建新追踪器 for idx in unmatched_detections: self.create_new_tracker(detections[idx]) # 处理未匹配的追踪器 i = len(self.trackers) for tracker_idx in reversed(unmatched_trackers): self.trackers[tracker_idx].time_since_update += 1 # 移除长时间未更新的追踪器 if self.trackers[tracker_idx].time_since_update > self.max_age: self.trackers.pop(tracker_idx) # 返回当前活跃的追踪结果 return self.get_tracked_objects()

4.2 视频处理流水线

创建完整的视频处理流水线,实现端到端的高尔夫球追踪:

# golf_tracker_pipeline.py import cv2 import numpy as np from ultralytics import YOLO from tracker import GolfBallTracker import time class GolfBallTrackingPipeline: def __init__(self, model_path='best.pt', conf_threshold=0.5): # 加载训练好的YOLO模型 self.model = YOLO(model_path) self.conf_threshold = conf_threshold # 初始化追踪器 self.tracker = GolfBallTracker() # 性能统计 self.frame_count = 0 self.fps = 0 self.start_time = time.time() def preprocess_frame(self, frame): """帧预处理:增强对比度和减少噪声""" # 转换为HSV色彩空间进行光照归一化 hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) h, s, v = cv2.split(hsv) # 对亮度通道进行直方图均衡化 v_eq = cv2.equalizeHist(v) hsv_eq = cv2.merge([h, s, v_eq]) frame_eq = cv2.cvtColor(hsv_eq, cv2.COLOR_HSV2BGR) # 高斯模糊减少噪声 blurred = cv2.GaussianBlur(frame_eq, (5, 5), 0) return blurred def detect_golf_balls(self, frame): """使用YOLO检测高尔夫球""" results = self.model(frame, conf=self.conf_threshold) detections = [] for result in results: boxes = result.boxes if boxes is not None: for box in boxes: # 获取边界框坐标和置信度 x1, y1, x2, y2 = box.xyxy[0].cpu().numpy() conf = box.conf[0].cpu().numpy() detections.append({ 'bbox': [x1, y1, x2, y2], 'confidence': conf, 'class': 'golf_ball' }) return detections def draw_tracking_results(self, frame, tracked_objects): """在帧上绘制追踪结果""" for obj in tracked_objects: x1, y1, x2, y2 = obj['bbox'] track_id = obj['track_id'] confidence = obj['confidence'] # 绘制边界框 color = self.get_color(track_id) cv2.rectangle(frame, (int(x1), int(y1)), (int(x2), int(y2)), color, 2) # 绘制标签 label = f"Ball {track_id}: {confidence:.2f}" label_size = cv2.getTextSize(label, cv2.FONT_HERSHEY_SIMPLEX, 0.5, 2)[0] cv2.rectangle(frame, (int(x1), int(y1 - label_size[1] - 10)), (int(x1 + label_size[0]), int(y1)), color, -1) cv2.putText(frame, label, (int(x1), int(y1 - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1) # 绘制轨迹 if 'trajectory' in obj: trajectory = obj['trajectory'] if len(trajectory) > 1: points = np.array(trajectory, dtype=np.int32) cv2.polylines(frame, [points], False, color, 2) # 显示FPS cv2.putText(frame, f"FPS: {self.fps:.1f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2) return frame def get_color(self, track_id): """根据追踪ID生成颜色""" colors = [ (255, 0, 0), (0, 255, 0), (0, 0, 255), (255, 255, 0), (255, 0, 255), (0, 255, 255), (128, 0, 0), (0, 128, 0), (0, 0, 128) ] return colors[track_id % len(colors)] def process_video(self, video_path, output_path=None): """处理视频文件""" cap = cv2.VideoCapture(video_path) # 获取视频属性 width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) fps = cap.get(cv2.CAP_PROP_FPS) # 设置输出视频 if output_path: fourcc = cv2.VideoWriter_fourcc(*'XVID') out = cv2.VideoWriter(output_path, fourcc, fps, (width, height)) while cap.isOpened(): ret, frame = cap.read() if not ret: break # 预处理帧 processed_frame = self.preprocess_frame(frame) # 检测高尔夫球 detections = self.detect_golf_balls(processed_frame) # 更新追踪器 tracked_objects = self.tracker.update(detections) # 绘制结果 result_frame = self.draw_tracking_results(frame.copy(), tracked_objects) # 计算FPS self.frame_count += 1 if self.frame_count % 30 == 0: elapsed = time.time() - self.start_time self.fps = self.frame_count / elapsed # 显示结果 cv2.imshow('Golf Ball Tracker', result_frame) # 保存输出视频 if output_path: out.write(result_frame) # 退出条件 if cv2.waitKey(1) & 0xFF == ord('q'): break # 释放资源 cap.release() if output_path: out.release() cv2.destroyAllWindows() # 使用示例 if __name__ == "__main__": pipeline = GolfBallTrackingPipeline(model_path='runs/train/exp/weights/best.pt') pipeline.process_video('golf_swing.mp4', output_path='tracked_output.avi')

5. 轨迹分析与数据可视化

5.1 运动参数计算

实现高尔夫球运动轨迹的物理参数分析:

# trajectory_analyzer.py import numpy as np from scipy import stats import matplotlib.pyplot as plt class TrajectoryAnalyzer: def __init__(self): self.trajectories = {} # 存储不同球的轨迹数据 def add_trajectory_point(self, track_id, point, timestamp): """添加轨迹点""" if track_id not in self.trajectories: self.trajectories[track_id] = { 'points': [], 'timestamps': [], 'velocities': [], 'accelerations': [] } trajectory = self.trajectories[track_id] trajectory['points'].append(point) trajectory['timestamps'].append(timestamp) # 计算速度和加速度 if len(trajectory['points']) >= 2: self.calculate_motion_parameters(track_id) def calculate_motion_parameters(self, track_id): """计算运动参数""" trajectory = self.trajectories[track_id] points = np.array(trajectory['points']) timestamps = np.array(trajectory['timestamps']) # 计算速度(像素/秒) if len(points) >= 2: displacements = np.diff(points, axis=0) time_diffs = np.diff(timestamps) velocities = displacements / time_diffs[:, np.newaxis] trajectory['velocities'].extend(velocities) # 计算加速度 if len(velocities) >= 2: acceleration = np.diff(velocities, axis=0) / time_diffs[1:, np.newaxis] trajectory['accelerations'].extend(acceleration) def analyze_trajectory(self, track_id): """分析完整轨迹""" if track_id not in self.trajectories: return None trajectory = self.trajectories[track_id] points = np.array(trajectory['points']) if len(points) < 2: return None # 基本统计信息 analysis = { 'total_distance': self.calculate_total_distance(points), 'average_speed': self.calculate_average_speed(trajectory), 'max_speed': self.calculate_max_speed(trajectory), 'flight_time': trajectory['timestamps'][-1] - trajectory['timestamps'][0], 'trajectory_angle': self.calculate_launch_angle(points) } return analysis def calculate_total_distance(self, points): """计算总移动距离""" displacements = np.diff(points, axis=0) distances = np.linalg.norm(displacements, axis=1) return np.sum(distances) def calculate_average_speed(self, trajectory): """计算平均速度""" if not trajectory['velocities']: return 0 speeds = np.linalg.norm(trajectory['velocities'], axis=1) return np.mean(speeds) def calculate_max_speed(self, trajectory): """计算最大速度""" if not trajectory['velocities']: return 0 speeds = np.linalg.norm(trajectory['velocities'], axis=1) return np.max(speeds) def calculate_launch_angle(self, points, num_points=5): """计算发射角度""" if len(points) < num_points: return 0 # 使用前几个点计算初始方向 initial_points = points[:num_points] x_coords = initial_points[:, 0] y_coords = initial_points[:, 1] # 线性回归计算角度 slope, intercept, r_value, p_value, std_err = stats.linregress(x_coords, y_coords) angle = np.degrees(np.arctan(slope)) return angle def visualize_trajectory(self, track_id, save_path=None): """可视化轨迹""" if track_id not in self.trajectories: return trajectory = self.trajectories[track_id] points = np.array(trajectory['points']) plt.figure(figsize=(12, 8)) # 绘制轨迹 plt.subplot(2, 2, 1) plt.plot(points[:, 0], points[:, 1], 'b-', linewidth=2, label='Trajectory') plt.scatter(points[:, 0], points[:, 1], c=range(len(points)), cmap='viridis') plt.xlabel('X Position') plt.ylabel('Y Position') plt.title(f'Golf Ball Trajectory - ID {track_id}') plt.colorbar(label='Frame Number') plt.grid(True) # 绘制速度变化 plt.subplot(2, 2, 2) if trajectory['velocities']: speeds = np.linalg.norm(trajectory['velocities'], axis=1) plt.plot(range(len(speeds)), speeds, 'r-', linewidth=2) plt.xlabel('Frame') plt.ylabel('Speed (pixels/frame)') plt.title('Speed Over Time') plt.grid(True) # 绘制运动方向 plt.subplot(2, 2, 3) if len(points) >= 2: displacements = np.diff(points, axis=0) angles = np.degrees(np.arctan2(displacements[:, 1], displacements[:, 0])) plt.plot(range(len(angles)), angles, 'g-', linewidth=2) plt.xlabel('Frame') plt.ylabel('Direction (degrees)') plt.title('Movement Direction') plt.grid(True) # 显示分析结果 plt.subplot(2, 2, 4) analysis = self.analyze_trajectory(track_id) if analysis: metrics = ['Total Distance', 'Avg Speed', 'Max Speed', 'Flight Time', 'Launch Angle'] values = [ f"{analysis['total_distance']:.1f} px", f"{analysis['average_speed']:.1f} px/frame", f"{analysis['max_speed']:.1f} px/frame", f"{analysis['flight_time']:.2f} s", f"{analysis['trajectory_angle']:.1f}°" ] plt.axis('off') for i, (metric, value) in enumerate(zip(metrics, values)): plt.text(0.1, 0.9 - i*0.15, f"{metric}: {value}", fontsize=12, transform=plt.gca().transAxes) plt.tight_layout() if save_path: plt.savefig(save_path, dpi=300, bbox_inches='tight') plt.show()

5.2 实时数据显示界面

创建实时数据显示界面,方便训练和比赛中的即时分析:

# realtime_dashboard.py import cv2 import numpy as np from datetime import datetime class RealtimeDashboard: def __init__(self, width=1200, height=800): self.width = width self.height = height self.canvas = np.ones((height, width, 3), dtype=np.uint8) * 40 # 深灰色背景 # 显示区域划分 self.video_width = int(width * 0.6) self.stats_width = width - self.video_width def update_dashboard(self, video_frame, tracked_objects, analysis_data): """更新仪表板显示""" # 清空画布 self.canvas.fill(40) # 显示视频帧 if video_frame is not None: video_frame = self.resize_frame(video_frame, self.video_width, self.height) self.canvas[0:video_frame.shape[0], 0:video_frame.shape[1]] = video_frame # 显示统计信息 self.display_statistics(tracked_objects, analysis_data) # 显示时间戳 self.display_timestamp() return self.canvas def resize_frame(self, frame, target_width, target_height): """调整帧尺寸""" h, w = frame.shape[:2] scale = min(target_width / w, target_height / h) new_w, new_h = int(w * scale), int(h * scale) resized = cv2.resize(frame, (new_w, new_h)) return resized def display_statistics(self, tracked_objects, analysis_data): """显示统计信息""" x_start = self.video_width + 20 y_start = 20 line_height = 30 # 标题 cv2.putText(self.canvas, "GOLF BALL TRACKING STATS", (x_start, y_start), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 255), 2) y_start += line_height * 2 # 追踪对象信息 cv2.putText(self.canvas, f"Active Balls: {len(tracked_objects)}", (x_start, y_start), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 1) y_start += line_height for i, obj in enumerate(tracked_objects): track_id = obj['track_id'] confidence = obj['confidence'] text = f"Ball {track_id}: {confidence:.3f}" cv2.putText(self.canvas, text, (x_start, y_start), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 1) y_start += line_height # 分析数据 if analysis_data: y_start += line_height cv2.putText(self.canvas, "ANALYSIS RESULTS:", (x_start, y_start), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 0), 1) y_start += line_height for key, value in analysis_data.items(): text = f"{key}: {value}" cv2.putText(self.canvas, text, (x_start, y_start), cv2.FONT_HERSHEY_SIMPLEX, 0.4, (255, 255, 255), 1) y_start += line_height def display_timestamp(self): """显示时间戳""" timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") cv2.putText(self.canvas, timestamp, (10, self.height - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)

6. 性能优化与工程实践

6.1 模型推理优化

针对实时性要求,实施多种优化策略:

# optimization.py import torch import torch_tensorrt import onnxruntime as ort from ultralytics import YOLO class ModelOptimizer: def __init__(self, model_path): self.model_path = model_path self.original_model = YOLO(model_path) def optimize_for_inference(self, precision='fp16'): """模型推理优化""" # 切换到评估模式 self.original_model.model.eval() # 示例优化配置 optimization_config = { 'precision': precision, 'workspace_size': 1 << 30, # 1GB 'min_block_size': 5, 'torch_executed_ops': ['aten::view', 'aten::reshape'] } # 使用TorchScript优化 traced_model = self.convert_to_torchscript() # 使用TensorRT进一步优化(如果可用) if torch.cuda.is_available(): optimized_model = self.optimize_with_tensorrt(traced_model, optimization_config) return optimized_model return traced_model def convert_to_torchscript(self): """转换为TorchScript格式""" example_input = torch.randn(1, 3, 640, 640).cuda() if torch.cuda.is_available() else torch.randn(1, 3, 640, 640) traced_script_module = torch.jit.trace(self.original_model.model, example_input) # 保存优化后的模型 torch.jit.save(traced_script_module, 'optimized_model.pt') return traced_script_module def optimize_with_tensorrt(self, model, config): """使用TensorRT优化""" try: # 编译模型 trt_model = torch_tensorrt.compile( model, inputs=[torch_tensorrt.Input((1, 3, 640, 640))], enabled_precisions={torch.float16} if config['precision'] == 'fp16' else {torch.float32}, workspace_size=config['workspace_size'], min_block_size=config['min_block_size'], torch_executed_ops=config['torch_executed_ops'] ) return trt_model except Exception as e: print(f"TensorRT优化失败: {e},回退到TorchScript") return model def export_to_onnx(self): """导出为ONNX格式""" success = self.original_model.export(format='onnx', dynamic=True, simplify=True) if success: print("ONNX导出成功") return True else: print("ONNX导出失败") return False # 使用示例
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/7 9:11:52

图像算法培训实战:从数据处理到模型部署的全流程指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/7 9:09:39

统一标准C驱动兼容LIS2DH12/LIS2DW12/LIS2DS12

简介&#xff1a;面向嵌入式、物联网及可穿戴设备开发者&#xff0c;这份标准C实现的demo代码包聚焦意法半导体&#xff08;ST&#xff09;多款传感器&#xff0c;覆盖LIS2DS12、LIS2DH12、LIS2DW12、LSM6DSM等常用型号&#xff0c;用于解决驱动移植、传感器数据读取及基础功能…

作者头像 李华
网站建设 2026/9/7 9:08:37

企业级AI Coding落地:8个Skill构建可控Harness工程体系

开头 在企业里做 AI Coding&#xff0c;最难的不是让模型写出能跑的代码&#xff0c;而是让它在真实的工程约束下稳定地产出可用结果。过去一年我带着团队尝试了各种姿势&#xff1a;从裸调大模型、写 prompt 模板&#xff0c;到后来搭建了一套完整的 Harness 工程体系&#xf…

作者头像 李华
网站建设 2026/9/7 9:06:07

SolidWorks-FESTO插件详解:气动元件选型到装配体模型的高效实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华