本文主要是介绍YOLOv8改进 | 科研必备 | 计算YOLOv8、YOLOv10模型的FPS的脚本【复制 - 粘贴 - 运行】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
秋招面试专栏推荐 :深度学习算法工程师面试问题总结【百面算法工程师】——点击即可跳转
💡💡💡本专栏所有程序均经过测试,可成功执行💡💡💡
专栏目录 :《YOLOv8改进有效涨点》专栏介绍 & 专栏目录 | 目前已有100+篇内容,内含各种Head检测头、损失函数Loss、Backbone、Neck、NMS等创新点改进——点击即可跳转
FPS(Frames Per Second)是衡量模型处理速度的重要指标,反映了模型每秒能处理的帧数。在实时应用中,高FPS确保流畅的用户体验和低延迟,尤其在视频处理、自动驾驶等对实时性要求高的场景中至关重要。同时,FPS也影响硬件需求、能效管理和运营成本,帮助开发者在性能优化和资源配置上做出平衡决策。因此,FPS不仅是速度的标尺,更是评估模型实用性和部署效果的关键指标。此外在论文中经常会有FPS大小的比较,但是官方的代码中并没有给我提供计算FPS的脚本,因此我特意写了这个脚本,方便大家计算FPS。大家复制脚本以后,一般只需要修改模型的路径即可,其他特殊的请看参数修改即可。
专栏地址:YOLOv8改进——更新各种有效涨点方法——点击即可跳转
计算模型的FPS(Frames Per Second,帧率)在模型性能评估中有重要意义,尤其在实时应用和部署场景中。FPS指的是模型每秒处理的图像或帧的数量,是衡量模型处理速度的重要指标。以下是FPS的具体意义和应用:
1. 实时性要求
-
实时应用:在视频处理、实时目标检测、增强现实(AR)、虚拟现实(VR)等应用中,模型需要以较高的FPS进行推理,以确保用户体验的流畅性。例如,FPS低于30时,视频输出会感觉卡顿;而在一些高要求的应用中,可能需要超过60 FPS才能达到流畅效果。
-
延迟敏感性:低FPS通常意味着更高的处理延迟,这在对实时性要求高的应用中是不可接受的,如自动驾驶、机器人控制等。
2. 性能与资源平衡
-
模型优化:FPS可以帮助开发者评估模型在不同硬件平台上的运行表现。通过调整模型架构、剪枝、量化等优化手段,可以提升FPS,使得模型在有限的硬件资源上也能达到实时处理要求。
-
硬件需求:FPS还可以帮助决定所需的硬件性能。在选择边缘设备或服务器时,FPS指标可以帮助你选择适合的硬件规格,确保应用的顺利运行。
3. 部署决策
-
部署环境:在云端、边缘或移动设备上部署模型时,FPS是一个关键考虑因素。高FPS意味着在给定时间内能够处理更多数据,对于高负载的应用场景(如视频流分析)尤为重要。
-
用户体验:对于交互性强的应用程序,高FPS能够提升用户体验,使得操作响应更为及时、自然。
4. 能效与成本
-
能耗管理:FPS与能耗之间存在直接关系。高FPS通常需要更高的计算资源和功耗。通过评估FPS,可以在性能与能效之间找到平衡点,优化设备电池寿命或降低运行成本。
-
运营成本:对于需要处理大量视频流的服务器,FPS直接影响服务器的规模和成本。更高的FPS意味着可以用较少的服务器处理更多的数据流,从而降低总体运营成本。
总的来说,FPS不仅是一个简单的速度指标,更是模型在实际应用中是否能够满足实时性和性能需求的重要衡量标准。在优化模型和选择硬件时,FPS可以提供有价值的参考信息。
注释版本:
import argparse
import logging
import os
import time
import warnings
import numpy as np
import torch
from tqdm import tqdm
from rich.logging import RichHandler
from rich.console import Console
from rich.table import Table
from rich.progress import track from ultralytics.nn.tasks import attempt_load_weights
from ultralytics.utils.torch_utils import select_device warnings.filterwarnings('ignore')# 使用Rich设置日志输出格式
logging.basicConfig(level=logging.INFO, format='%(message)s', handlers=[RichHandler()])
logger = logging.getLogger("YOLOv8 Latency Test") # 创建一个日志记录器
console = Console() # 创建一个Rich控制台对象,用于丰富的终端输出def get_weight_size(path):"""返回模型权重文件的大小(以MB为单位)。"""stats = os.stat(path)return f'{stats.st_size / 1024 / 1024:.1f}' # 返回文件大小,单位为MBdef load_model(weights, device):"""加载模型并返回它。"""if weights.endswith('.pt'): # 确保权重文件是.pt格式model = attempt_load_weights(weights, device=device) # 加载模型权重logger.info(f'[INFO] Loaded model weights from {weights}')total_params = sum(p.numel() for p in model.parameters()) # 计算模型参数总数logger.info(f'Total parameters: {total_params:,}') # 打印模型参数总数else:raise ValueError("Weights file must be a .pt file.") # 抛出错误提示return model.to(device) # 将模型移动到指定设备def perform_warmup(model, example_inputs, warmup_iters):"""通过多次迭代运行模型进行预热。"""logger.info('[INFO] Beginning warmup...')for _ in track(range(warmup_iters), description="[yellow]Warming up...", console=console):model(example_inputs) # 运行模型进行预热logger.info('[INFO] Warmup completed.')def test_latency(model, example_inputs, test_iters, device):"""测试模型的延迟,并返回平均延迟和标准差。"""logger.info('[INFO] Beginning latency test...')time_arr = [] # 用于存储每次推理的时间for _ in track(range(test_iters), description="[yellow]Testing Latency...", console=console):if device.type == 'cuda': # 如果使用GPU,需同步时间torch.cuda.synchronize()start_time = time.time() # 记录开始时间model(example_inputs) # 运行模型if device.type == 'cuda': # 再次同步时间torch.cuda.synchronize()end_time = time.time() # 记录结束时间time_arr.append(end_time - start_time) # 计算并记录推理时间infer_time_per_image = np.mean(time_arr) / example_inputs.size(0) # 计算每张图片的平均推理时间std_time = np.std(time_arr) # 计算时间的标准差logger.info('[INFO] Latency test completed.')return infer_time_per_image, std_time # 返回平均推理时间和标准差def display_results(opt, infer_time_per_image, std_time):"""以格式化表格显示结果。"""table = Table(title="Model Performance Results")table.add_column("Metric", justify="left", style="cyan", no_wrap=True)table.add_column("Value", justify="right", style="magenta")table.add_row("Model weights", opt.weights) # 权重文件路径table.add_row("Device", torch.cuda.get_device_name()) # 设备名称(如GPU名称)table.add_row("Weights size", f"{get_weight_size(opt.weights)} MB") # 权重文件大小table.add_row("Batch size", str(opt.batch)) # 批量大小table.add_row("Image size", f"{opt.imgs[0]}x{opt.imgs[1]}") # 图片尺寸table.add_row("Latency per image", f"{infer_time_per_image:.5f} s ± {std_time:.5f} s") # 每张图片的推理时间table.add_row("Frames per second (FPS)", f"{1 / infer_time_per_image:.1f}") # 每秒帧数console.print(table) # 输出表格到控制台def main():# 解析命令行参数opt = parse_arguments()# 选择设备(如GPU或CPU)device = select_device(opt.device, batch=opt.batch)# 加载模型model = load_model(opt.weights, device)# 准备示例输入数据example_inputs = torch.randn((opt.batch, 3, *opt.imgs)).to(device)# 如果需要,转换为FP16精度if opt.half:model = model.half()example_inputs = example_inputs.half()# 进行模型预热perform_warmup(model, example_inputs, opt.warmup)# 测试模型延迟infer_time_per_image, std_time = test_latency(model, example_inputs, opt.testtime, device)# 以格式化表格显示结果display_results(opt, infer_time_per_image, std_time)def parse_arguments():"""解析并返回命令行参数。"""parser = argparse.ArgumentParser(description="YOLOv8 Inference Latency Test")parser.add_argument('--weights', type=str, default=r'C:\Users\Desktop\yolov8n.pt', help='Path to the trained weights file (.pt)') # 模型权重文件路径parser.add_argument('--batch', type=int, default=1, help='Total batch size for all GPUs') # 批量大小parser.add_argument('--imgs', nargs='+', type=int, default=[640, 640], help='Image size as [height, width]') # 图片尺寸parser.add_argument('--device', default='', help='CUDA device, e.g., "0" or "0,1,2,3" or "cpu"') # 设备选择parser.add_argument('--warmup', type=int, default=200, help='Number of warmup iterations') # 预热迭代次数parser.add_argument('--testtime', type=int, default=1000, help='Number of test iterations') # 测试迭代次数parser.add_argument('--half', action='store_true', help='Use FP16 precision') # 是否使用FP16精度return parser.parse_args()if __name__ == '__main__':main() # 执行主函数
FPS输出样例
Warming up... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:18
[08/30/24 13:04:49] INFO [INFO] Warmup completed.
FPS.py:48 INFO [INFO] Beginning latency test...
FPS.py:52Testing Latency... ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:16
[08/30/24 13:05:05] INFO [INFO] Latency test completed.
FPS.py:71 Model Performance Results
┏━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Metric ┃ Value ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ Model weights │ C:\Users\Desktop\yolov8n.pt │
│ Device │ NVIDIA GeForce │
│ Weights size │ 6.2 MB │
│ Batch size │ 1 │
│ Image size │ 640x640 │
│ Latency per image │ 0.01677 s ± 0.00509 s │
│ Frames per second (FPS) │ 59.6 │
└─────────────────────────┴──────────────────────────────────────────┘
无注释版本:
import argparse
import logging
import os
import time
import warnings
import numpy as np
import torch
from tqdm import tqdm
from rich.logging import RichHandler
from rich.console import Console
from rich.table import Table
from rich.progress import trackfrom ultralytics.nn.tasks import attempt_load_weights
from ultralytics.utils.torch_utils import select_device# Suppress warnings
warnings.filterwarnings('ignore')# Set up logging with Rich
logging.basicConfig(level=logging.INFO, format='%(message)s', handlers=[RichHandler()])
logger = logging.getLogger("YOLOv8 Latency Test")
console = Console()def get_weight_size(path):"""Returns the size of the model weights in MB."""stats = os.stat(path)return f'{stats.st_size / 1024 / 1024:.1f}'def load_model(weights, device):"""Loads the model and returns it."""if weights.endswith('.pt'):model = attempt_load_weights(weights, device=device)logger.info(f'[INFO] Loaded model weights from {weights}')total_params = sum(p.numel() for p in model.parameters())logger.info(f'Total parameters: {total_params:,}')else:raise ValueError("Weights file must be a .pt file.")return model.to(device)def perform_warmup(model, example_inputs, warmup_iters):"""Warms up the model by running it through several iterations."""logger.info('[INFO] Beginning warmup...')for _ in track(range(warmup_iters), description="[yellow]Warming up...", console=console):model(example_inputs)logger.info('[INFO] Warmup completed.')def test_latency(model, example_inputs, test_iters, device):"""Tests the model's latency and returns the average latency and standard deviation."""logger.info('[INFO] Beginning latency test...')time_arr = []for _ in track(range(test_iters), description="[yellow]Testing Latency...", console=console):if device.type == 'cuda':torch.cuda.synchronize()start_time = time.time()model(example_inputs)if device.type == 'cuda':torch.cuda.synchronize()end_time = time.time()time_arr.append(end_time - start_time)infer_time_per_image = np.mean(time_arr) / example_inputs.size(0)std_time = np.std(time_arr)logger.info('[INFO] Latency test completed.')return infer_time_per_image, std_timedef display_results(opt, infer_time_per_image, std_time):"""Displays the results in a formatted table."""table = Table(title="Model Performance Results")table.add_column("Metric", justify="left", style="cyan", no_wrap=True)table.add_column("Value", justify="right", style="magenta")table.add_row("Model weights", opt.weights)table.add_row("Device", torch.cuda.get_device_name())table.add_row("Weights size", f"{get_weight_size(opt.weights)} MB")table.add_row("Batch size", str(opt.batch))table.add_row("Image size", f"{opt.imgs[0]}x{opt.imgs[1]}")table.add_row("Latency per image", f"{infer_time_per_image:.5f} s ± {std_time:.5f} s")table.add_row("Frames per second (FPS)", f"{1 / infer_time_per_image:.1f}")console.print(table)def main():# Parse command-line argumentsopt = parse_arguments()# Select device (CUDA or CPU)device = select_device(opt.device, batch=opt.batch)# Load modelmodel = load_model(opt.weights, device)# Prepare example inputsexample_inputs = torch.randn((opt.batch, 3, *opt.imgs)).to(device)# Convert to FP16 if requiredif opt.half:model = model.half()example_inputs = example_inputs.half()# Perform warmupperform_warmup(model, example_inputs, opt.warmup)# Test latencyinfer_time_per_image, std_time = test_latency(model, example_inputs, opt.testtime, device)# Display results in a formatted tabledisplay_results(opt, infer_time_per_image, std_time)def parse_arguments():"""Parses and returns command-line arguments."""parser = argparse.ArgumentParser(description="YOLOv8 Inference Latency Test")parser.add_argument('--weights', type=str, default=r'C:\Users\Desktop\yolov8n.pt', help='Path to the trained weights file (.pt)')parser.add_argument('--batch', type=int, default=1, help='Total batch size for all GPUs')parser.add_argument('--imgs', nargs='+', type=int, default=[640, 640], help='Image size as [height, width]')parser.add_argument('--device', default='', help='CUDA device, e.g., "0" or "0,1,2,3" or "cpu"')parser.add_argument('--warmup', type=int, default=200, help='Number of warmup iterations')parser.add_argument('--testtime', type=int, default=1000, help='Number of test iterations')parser.add_argument('--half', action='store_true', help='Use FP16 precision')return parser.parse_args()if __name__ == '__main__':main()
这篇关于YOLOv8改进 | 科研必备 | 计算YOLOv8、YOLOv10模型的FPS的脚本【复制 - 粘贴 - 运行】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!