YOLOv9-0.1部分代码阅读笔记-benchmarks.py

benchmarks.py

benchmarks.py

目录

benchmarks.py

1.所需的库和模块

2.def run(weights=ROOT / 'yolo.pt', imgsz=640, batch_size=1, data=ROOT / 'data/coco.yaml', device='', half=False, test=False, pt_only=False, hard_fail=False,): 

3.def test(weights=ROOT / 'yolo.pt', imgsz=640, batch_size=1, data=ROOT / 'data/coco128.yaml', device='', half=False, test=False, pt_only=False, hard_fail=False,): 

4.def parse_opt(): 

5.def main(opt): 

6.if __name__ == "__main__": 


1.所需的库和模块

import argparse
import platform
import sys
import time
from pathlib import Pathimport pandas as pd# 这段代码是Python代码的一部分,它的作用是将YOLO的根目录添加到Python的系统路径中。这样做的目的是为了能够从项目的任何子目录中导入YOLO项目中的模块。
# 获取当前执行文件的路径,并将其解析为绝对路径,存储在变量 FILE 中。
FILE = Path(__file__).resolve()
# 获取 FILE 的父目录,也就是YOLO项目的根目录,并将其存储在变量 ROOT 中。
ROOT = FILE.parents[0]  # YOLO root directory
# 检查 ROOT 目录的字符串表示是否已经在 sys.path 中, sys.path 是一个列表,包含了Python解释器搜索模块时会查找的目录。
if str(ROOT) not in sys.path:# 如果 ROOT 不在 sys.path 中,那么会将 ROOT 目录的路径添加到 sys.path 列表中。这样,Python解释器在导入模块时就会搜索这个目录。sys.path.append(str(ROOT))  # add ROOT to PATH
# 这是一个被注释掉的代码行,如果取消注释,它会将 ROOT 转换为相对于当前工作目录的相对路径。
# current_working_directory = Path.cwd()
# 在Python中, cwd() 函数是 pathlib 模块中的一个方法,用于获取当前工作目录。这个方法是 Path 类的一个实例方法, Path 类是 pathlib 模块中用于处理文件系统路径的类。
# 功能描述 :
# Path.cwd() 方法返回一个 Path 对象,该对象代表当前工作目录的路径。
# 返回值 :
# Path.cwd() 方法返回的是 Path 对象,这个对象提供了许多方法来操作路径,例如 .resolve() 可以获取路径的绝对路径, .as_posix() 可以将路径转换为跨平台的字符串形式等。
# 异常处理 :
# Path.cwd() 方法通常不会抛出异常,因为它只是返回当前工作目录的路径。但是,如果系统出现问题,导致无法确定当前工作目录,可能会抛出异常,这种情况下应该进行异常处理。
# ROOT = ROOT.relative_to(Path.cwd())  # relative
# 这段代码通常用于Python项目中,以确保项目中的模块可以被正确导入。import export
from models.experimental import attempt_load
from models.yolo import SegmentationModel
from segment.val import run as val_seg
from utils import notebook_init
from utils.general import LOGGER, check_yaml, file_size, print_args
from utils.torch_utils import select_device
from val import run as val_det

2.def run(weights=ROOT / 'yolo.pt', imgsz=640, batch_size=1, data=ROOT / 'data/coco.yaml', device='', half=False, test=False, pt_only=False, hard_fail=False,): 

# 这段代码定义了一个名为  run  的函数,它用于测试和验证YOLO模型的不同导出格式的性能。
# 定义了一个名为 run 的函数,它接受多个参数。
# 1.weights :这是一个路径参数,指向YOLO模型的权重文件(例如 .pt 文件)。默认情况下,它被设置为 ROOT / 'yolo.pt' ,意味着权重文件位于YOLO项目的根目录下,文件名为 yolo.pt 。
# 2.imgsz :这个参数指定了推理时的图像尺寸,单位是像素。默认值为640,意味着模型将在640像素的尺寸下进行推理。
# 3.batch_size :这个参数定义了推理时的批量大小。默认值为1,表示每次推理处理一张图像。
# 4.data :这是一个路径参数,指向包含数据集信息的 .yaml 文件。默认情况下,它被设置为 ROOT / 'data/coco.yaml' ,意味着数据集配置文件位于YOLO项目的 data 子目录下,文件名为 coco.yaml 。
# 5.device :这个参数用于指定推理时使用的设备。它可以是GPU设备编号(例如 0 表示第一个GPU),多个GPU编号(例如 0,1,2,3 ),或者 cpu 表示使用CPU进行推理。默认为空字符串,意味着将自动选择设备。
# 6.half :这是一个布尔参数,用于指定是否使用半精度(FP16)进行推理。默认为 False ,表示使用全精度(FP32)。
# 7.test :这是一个布尔参数,用于指定是否仅测试模型的导出功能。默认为 False ,表示进行全面的基准测试。
# 8.pt_only :这是一个布尔参数,用于指定是否仅测试PyTorch格式的模型。默认为 False ,表示测试所有支持的格式。
# 9.hard_fail :这是一个布尔参数,用于指定在基准测试失败时是否抛出错误。默认为 False ,表示在测试失败时记录警告而不是抛出错误。如果这个参数被设置为字符串,它将被解释为一个表达式,用于定义mAP的最低阈值,如果测试结果低于这个阈值,将抛出错误。
def run(weights=ROOT / 'yolo.pt',  # weights pathimgsz=640,  # inference size (pixels)batch_size=1,  # batch sizedata=ROOT / 'data/coco.yaml',  # dataset.yaml pathdevice='',  # cuda device, i.e. 0 or 0,1,2,3 or cpuhalf=False,  # use FP16 half-precision inferencetest=False,  # test exports onlypt_only=False,  # test PyTorch onlyhard_fail=False,  # throw error on benchmark failure
):# 这段代码是 run 函数的一部分,它负责初始化一些变量和设置,然后遍历所有支持的导出格式,并进行一系列的断言检查以确保环境配置正确。# y 初始化一个空列表,用于存储每个导出格式的测试结果。# t 记录当前时间(以秒为单位),用于后续计算整个测试过程的耗时。y, t = [], time.time()# 调用 select_device 函数来确定实际使用的设备(CPU或GPU)。这个函数会根据 device 参数的值来选择设备,并返回一个设备对象。# def select_device(device='', batch_size=0, newline=True):# -> 根据用户提供的参数选择使用 CPU、单个 GPU 或多个 GPU,并返回一个对应的 PyTorch 设备对象。返回一个 PyTorch 设备对象,用于指定后续计算应该在哪个设备上执行。# -> return torch.device(arg)device = select_device(device)# 使用 attempt_load 函数尝试加载模型权重文件( weights 参数指定的路径), fuse=False 表示不融合模型中的某些层。 type 函数用于获取加载的模型的类型,例如 DetectionModel 或 SegmentationModel 等。# def attempt_load(weights, device=None, inplace=True, fuse=True):# -> 用于加载一个或多个预训练的模型权重,并创建一个模型集合( Ensemble )。这个函数处理了模型权重的加载、兼容性更新和模型融合。返回最终构建的模型集合( Ensemble )。# -> return modelmodel_type = type(attempt_load(weights, fuse=False))  # DetectionModel, SegmentationModel, etc.# DataFrame.iterrows()# 在Pandas中, iterrows() 是一个用于遍历 DataFrame 对象行的方法。它返回每一行的索引和行数据,其中行数据是以 Series 对象的形式返回的。这个方法通常用于逐行访问 DataFrame 中的数据,但它不是最高效的行遍历方法,特别是在处理大型数据集时。# 参数 :无参数。# 返回值 :# 返回一个迭代器,迭代器产生索引和 Series 对象的元组。# 注意事项 :# iterrows() 返回的行数据是 Series 对象,这意味着你可以通过列名来访问数据,如 row['Name'] 。# iterrows() 通常比直接通过位置访问行数据慢,特别是在大型数据集上。如果可能,考虑使用其他方法,如 itertuples() 或 apply() 。# 修改通过 iterrows() 返回的 Series 对象不会改变原始 DataFrame。# 这个方法是 Pandas 提供的一个便捷工具,用于快速遍历和处理 DataFrame 中的数据行。# 遍历 export_formats 函数返回的 DataFrame ,这个 DataFrame 包含了所有支持的导出格式的信息。 i 是索引, name 是导出格式的名称, f 是文件名, suffix 是文件后缀, cpu 表示是否支持CPU, gpu 表示是否支持GPU。# def export_formats(): -> 用于生成一个包含不同模型导出格式及其相关信息的数据框架(DataFrame)。返回值。函数返回一个 pandas.DataFrame 对象,其中包含了不同模型导出格式的详细信息。 -> return pd.DataFrame(x, columns=['Format', 'Argument', 'Suffix', 'CPU', 'GPU'])for i, (name, f, suffix, cpu, gpu) in export.export_formats().iterrows():  # index, (name, file, suffix, CPU, GPU)# 开始一个try块,用于捕获并处理在测试过程中可能发生的异常。try:# 断言当前索引 i 不是9或10,因为这些索引对应的导出格式(Edge TPU和TF.js)不支持推理。assert i not in (9, 10), 'inference not supported'  # Edge TPU and TF.js are unsupported    推理不受支持。# 断言当前索引 i 不是5,或者操作系统是Darwin(macOS)的系统,因为索引5对应的导出格式(CoreML)只在macOS系统上支持。assert i != 5 or platform.system() == 'Darwin', 'inference only supported on macOS>=10.13'  # CoreML    推理仅支持 macOS >=10.13 。# 如果设备类型包含 cpu ,则检查当前导出格式是否支持CPU。if 'cpu' in device.type:# 断言当前导出格式支持CPU,否则抛出异常。assert cpu, 'inference not supported on CPU'    # CPU 不支持推理。# 如果设备类型包含 cuda ,则检查当前导出格式是否支持GPU。if 'cuda' in device.type:# 断言当前导出格式支持GPU,否则抛出异常。assert gpu, 'inference not supported on GPU'    # GPU 不支持推理。# 这些代码行的目的是确保在开始测试之前,环境配置是正确的,并且所选的导出格式与设备兼容。如果任何断言失败,将抛出异常,提示用户配置错误。# 这段代码是 run 函数中的一部分,它负责根据提供的参数导出YOLO模型到不同的格式,并进行验证。# Export    表明接下来的代码块用于模型导出。# 检查当前的导出格式 f 是否为 '-' 。如果是,表示不需要进行实际的导出操作,而是直接使用PyTorch格式的模型权重。if f == '-':# 如果 f 是 '-' ,那么变量 w 被赋值为 weights 参数,即原始的PyTorch模型权重路径。w = weights  # PyTorch format# 如果 f 不是 '-' ,表示需要导出模型到其他格式。else:# 调用 export.run 函数来导出模型。这个函数接受以下参数 : weights 模型权重文件的路径。 imgsz 一个包含推理尺寸的列表。 include 一个包含要导出的格式的列表。 device 用于推理的设备。 half 是否使用半精度(FP16)。# [-1] : export.run 函数返回的是一个列表,通过 [-1] 索引来获取列表中的最后一个元素,即导出的模型权重。w = export.run(weights=weights, imgsz=[imgsz], include=[f], device=device, half=half)[-1]  # all others# 断言语句用于验证导出是否成功。它检查导出的模型权重 w 的字符串表示中是否包含预期的文件后缀 suffix 。如果 suffix 不在 w 的字符串表示中,将抛出一个异常,提示“export failed”。assert suffix in str(w), 'export failed'# 这段代码负责根据指定的格式导出YOLO模型,并验证导出是否成功。如果导出失败,将通过断言抛出异常。这个过程对于确保模型可以在不同的环境和框架中使用至关重要。# 这段代码是 run 函数中的一部分,它负责根据不同的模型类型(分割模型或检测模型)执行验证,并记录性能指标。# Validate# 判断当前模型是否为分割模型( SegmentationModel )。if model_type == SegmentationModel:# 如果是分割模型,调用 val_seg 函数进行验证。这个函数计算分割模型的性能指标,如精度、召回率和平均精度(mAP)。 参数包括数据集配置文件路径、模型权重、批量大小、图像尺寸等。result = val_seg(data, w, batch_size, imgsz, plots=False, device=device, task='speed', half=half)# 从 val_seg 函数返回的结果中提取第8个性能指标(索引从0开始)。metric = result[0][7]  # (box(p, r, map50, map), mask(p, r, map50, map), *loss(box, obj, cls))# 如果模型不是分割模型,则是检测模型( DetectionModel )。else:  # DetectionModel:# 调用 val_det 函数进行检测模型的验证,计算性能指标。result = val_det(data, w, batch_size, imgsz, plots=False, device=device, task='speed', half=half)# 从 val_det 函数返回的结果中提取第4个性能指标。metric = result[0][3]  # (p, r, map50, map, *loss(box, obj, cls))# 提取推理时间,这通常是结果列表中的第三个元素的第二个值。speed = result[2][1]  # times (preprocess, inference, postprocess)# 将 导出格式的名称 、 模型文件大小 ( MB ) 、 性能指标 ( mAP ) 和 推理时间 ( ms )添加到结果列表  y  中。# def file_size(path):# -> 用于计算指定文件或目录的大小,以兆字节(MB)为单位。# -> 如果 path 是一个文件,使用 path.stat() 获取文件的状态信息,其中 st_size 属性表示文件大小(字节)。然后将其转换为兆字节并返回。# -> 如果 path 是一个目录,使用 path.glob('**/*') 递归地获取目录中所有文件的路径。然后,对每个文件使用 f.stat().st_size 获取其大小,并累加这些大小。最后,将总大小转换为兆字节并返回。# -> 如果 path 既不是文件也不是目录,函数返回 0.0 。# -> return path.stat().st_size / mb# -> return sum(f.stat().st_size for f in path.glob('**/*') if f.is_file()) / mb# -> return 0.0y.append([name, round(file_size(w), 1), round(metric, 4), round(speed, 2)])  # MB, mAP, t_inference# 捕获验证过程中可能发生的任何异常。except Exception as e:# 如果设置了 hard_fail 参数,检查异常类型。if hard_fail:# 如果异常是 AssertionError ,则断言失败,并提供错误信息。assert type(e) is AssertionError, f'Benchmark --hard-fail for {name}: {e}'    # 基准测试 --hard-fail for {name}: {e} 。# 如果没有设置 hard_fail 或异常不是 AssertionError ,则记录警告信息。LOGGER.warning(f'WARNING ⚠️ Benchmark failure for {name}: {e}')    # 警告 ⚠️ {name} 的基准测试失败:{e} 。# 在结果列表  y  中添加一个包含失败信息的条目。y.append([name, None, None, None])  # mAP, t_inference# 如果设置了 pt_only 参数,并且当前处理的是PyTorch格式(索引为0),则退出循环。if pt_only and i == 0:# 退出循环,不再处理其他导出格式。break  # break after PyTorch# 这段代码的目的是根据不同的模型类型执行相应的验证函数,记录性能指标,并在发生异常时进行错误处理。如果设置了 pt_only 参数,它将只测试PyTorch格式的模型。# 这段代码是 run 函数的最后一部分,它负责打印和处理基准测试的结果。# Print results    表明接下来的代码块用于打印结果。# 使用日志记录器 LOGGER 打印一个换行符,以便在日志输出中创建一个空行。LOGGER.info('\n')# 调用 parse_opt 函数,这个函数用于解析命令行选项或配置。parse_opt()# 调用 notebook_init 函数,这个函数可能用于初始化Jupyter Notebook环境或打印系统信息。# def notebook_init(verbose=True): -> 用于在 Jupyter Notebook 环境中初始化和检查系统软硬件配置。函数返回 display 对象,这可能是为了在 Jupyter Notebook 中使用 display 的功能。 -> return displaynotebook_init()  # print system info# 定义列名列表 c 。如果存在一个名为 map 的变量(可能是一个布尔值),则使用包含性能指标的列名;否则,使用一个简化的列名列表。c = ['Format', 'Size (MB)', 'mAP50-95', 'Inference time (ms)'] if map else ['Format', 'Export', '', '']    # ['格式', '大小 (MB)', 'mAP50-95', '推理时间 (ms)'] , ['格式', '导出', '', ''] 。# pd.DataFrame(data, index=None, columns=None, dtype=None, copy=False)# pd.DataFrame 是 Pandas 库中的一个构造函数,用于创建 DataFrame 对象。DataFrame 是 Pandas 中最核心的数据结构之一,它提供了一个二维标签化数据结构,可以存储不同类型的数据,如数值、字符串、布尔值等。# 参数说明 :# data :这是创建 DataFrame 时必须提供的数据。 data 可以是以下几种类型之一 :# 一个字典,其中键是列名,值是数据列表或数组。# 一个二维 NumPy 数组或类似数组的结构。# 另一个 DataFrame 或相似的表格型数据结构。# 一个列表或列表的列表。# index :(可选)索引标签,可以是索引对象或数组。如果未指定,Pandas 将自动创建一个从 0 开始的整数索引。# columns :(可选)列名,可以是列名列表。如果未指定且 data 是字典,则使用字典的键作为列名。# dtype :(可选)数据类型,用于强制 DataFrame 中的数据类型。如果未指定,Pandas 将自动推断数据类型。# copy :(可选)布尔值,指示是否在创建 DataFrame 时复制数据。默认为 False,即不复制数据。# 返回值 :# 返回一个 DataFrame 对象。# 将之前收集的结果 y 转换为Pandas DataFrame py ,并指定列名。py = pd.DataFrame(y, columns=c)# 记录基准测试完成的信息,并打印测试耗时(从变量 t 开始计算的时间差)。LOGGER.info(f'\nBenchmarks complete ({time.time() - t:.2f}s)')    # 基准测试完成 ({time.time() - t:.2f}s) 。# 根据 map 变量的值,打印完整的结果DataFrame或仅打印前两列。LOGGER.info(str(py if map else py.iloc[:, :2]))# 如果 hard_fail 参数被设置,并且它的类型是字符串,则执行以下操作。if hard_fail and isinstance(hard_fail, str):# 从 DataFrame py 中提取 mAP50-95 列的值。metrics = py['mAP50-95'].array  # values to compare to floor# eval(expression, globals=None, locals=None)# eval() 函数是 Python 的内置函数,用于计算表达式字符串,并返回表达式的值。# 参数 :# expression :一个字符串形式的 Python 表达式。这个表达式可以包含 Python 中有效的任意表达式,例如数字、变量、运算符、函数调用等。# globals :一个字典,包含表达式将会使用的全局变量。如果为 None (默认值),则使用当前环境的全局变量。如果提供了 globals 参数,它将覆盖当前环境的全局变量。# locals :一个字典,包含表达式将会使用的局部变量。如果为 None (默认值),则使用当前环境的局部变量。如果提供了 locals 参数,它将覆盖当前环境的局部变量。# 返回值 :# 返回 expression 表达式计算后的结果。# 安全性 :# 使用 eval() 时需要特别小心,因为它可以执行任意代码。如果 expression 来自不可信的源,那么它可能会执行恶意代码,导致安全问题。# 在实际编程中,通常推荐避免使用 eval() ,除非完全信任输入源,或者确实需要动态执行代码。在很多情况下,可以使用更安全的方法来替代 eval() ,例如使用 ast.literal_eval() 来计算字面量表达式。# 评估 hard_fail 字符串为一个值,这个值定义了性能指标的最低阈值。floor = eval(hard_fail)  # minimum metric floor to pass# 断言所有非空的 mAP50-95 值都大于 floor 定义的阈值。如果有任何一个值不满足条件,则抛出 AssertionError 。assert all(x > floor for x in metrics if pd.notna(x)), f'HARD FAIL: mAP50-95 < floor {floor}'    # 硬故障:mAP50-95 < floor {floor} 。# 函数返回包含基准测试结果的 DataFrame py 。return py# 这段代码的目的是汇总和打印基准测试的结果,并在必要时进行断言检查以确保性能指标满足预设的最低要求。如果测试结果不满足要求,将抛出错误。
# 这个 run 函数是一个基准测试工具,用于测试和验证YOLO模型在不同导出格式下的性能。它接受模型权重、推理尺寸、批量大小等参数,并遍历所有支持的导出格式,对每个格式进行推理性能测试,记录文件大小、mAP和推理时间等信息,最后将结果以DataFrame的形式返回。如果设置了 hard_fail 参数,还会检查mAP是否低于预设的阈值,并在必要时抛出错误。

3.def test(weights=ROOT / 'yolo.pt', imgsz=640, batch_size=1, data=ROOT / 'data/coco128.yaml', device='', half=False, test=False, pt_only=False, hard_fail=False,): 

# 这段代码定义了一个名为 test 的函数,它用于测试 YOLO 模型权重文件在不同导出格式下的导出功能是否成功。
# 1.weights :这是一个路径参数,指向 YOLO 模型的权重文件(例如 .pt 文件)。默认情况下,它被设置为 ROOT / 'yolo.pt' ,意味着权重文件位于项目的根目录下,文件名为 yolo.pt 。
# 2.imgsz :这个参数指定了推理时的图像尺寸,单位是像素。默认值为 640,意味着模型将在 640 像素的尺寸下进行推理。
# 3.batch_size :这个参数定义了推理时的批量大小。默认值为 1,表示每次推理处理一张图像。
# 4.data :这是一个路径参数,指向包含数据集信息的 .yaml 文件。默认情况下,它被设置为 ROOT / 'data/coco128.yaml' ,意味着数据集配置文件位于项目的 data 子目录下,文件名为 coco128.yaml 。
# 5.device :这个参数用于指定推理时使用的设备。它可以是 GPU 设备编号(例如 0 表示第一个 GPU),多个 GPU 编号(例如 0,1,2,3 ),或者 cpu 表示使用 CPU 进行推理。默认为空字符串,意味着将自动选择设备。
# 6.half :这是一个布尔参数,用于指定是否使用半精度(FP16)进行推理。默认为 False ,表示使用全精度(FP32)。
# 7.test :这是一个布尔参数,用于指定是否仅测试模型的导出功能。默认为 False ,表示进行全面的测试。
# 8.pt_only :这是一个布尔参数,用于指定是否仅测试 PyTorch 格式的模型。默认为 False ,表示测试所有支持的格式。
# 9.hard_fail :这是一个布尔参数,用于指定在基准测试失败时是否抛出错误。默认为 False ,表示在测试失败时记录警告而不是抛出错误。
def test(weights=ROOT / 'yolo.pt',  # weights pathimgsz=640,  # inference size (pixels)batch_size=1,  # batch sizedata=ROOT / 'data/coco128.yaml',  # dataset.yaml pathdevice='',  # cuda device, i.e. 0 or 0,1,2,3 or cpuhalf=False,  # use FP16 half-precision inferencetest=False,  # test exports onlypt_only=False,  # test PyTorch onlyhard_fail=False,  # throw error on benchmark failure
):# 这段代码是 test 函数的主体部分,它负责执行模型权重文件的导出测试。# y 初始化一个空列表,用于存储每种导出格式的测试结果。# t 记录当前时间(以秒为单位),用于后续计算整个测试过程的耗时。y, t = [], time.time()# 调用 select_device 函数来确定实际使用的设备(CPU或GPU),基于 device 参数的值。device = select_device(device)# 遍历 export.export_formats() 函数返回的 DataFrame,这个 DataFrame 包含了所有支持的导出格式的信息。 i 是索引, name 是导出格式的名称, f 是文件名, suffix 是文件后缀, gpu 表示该格式是否支持 GPU。for i, (name, f, suffix, gpu) in export.export_formats().iterrows():  # index, (name, file, suffix, gpu-capable)# 开始一个 try 块,用于捕获在测试过程中可能发生的异常。try:#  如果当前格式 f 是 '-' ,则直接使用原始权重 weights 。 否则,调用 export.run 函数来导出权重文件到指定格式,并获取导出的权重文件。w = weights if f == '-' else \export.run(weights=weights, imgsz=[imgsz], include=[f], device=device, half=half)[-1]  # weights# 断言导出的权重文件 w 的字符串表示中包含预期的文件后缀 suffix 。如果 suffix 不在 w 的字符串表示中,抛出异常,表示导出失败。assert suffix in str(w), 'export failed'    # 导出失败。# 如果导出成功,将格式名称 name 和成功标志 True 添加到结果列表 y 中。y.append([name, True])# 捕获任何异常。except Exception:# 如果捕获到异常,将格式名称 name 和失败标志 False 添加到结果列表 y 中,表示该格式的导出测试未通过。y.append([name, False])  # mAP, t_inference# 这段代码的目的是测试模型权重文件能否成功导出到不同的格式,并记录每种格式的测试结果。通过这种方式,可以快速检查模型的导出功能是否正常工作,确保模型可以在不同的环境和框架中使用。# 这段代码是 test 函数的最后一部分,它负责汇总和打印模型权重文件导出测试的结果。# Print results    表明接下来的代码块用于打印测试结果。# 使用日志记录器 LOGGER 打印一个换行符,以便在日志输出中创建一个空行。LOGGER.info('\n')# 调用 parse_opt 函数,这个函数可能用于解析命令行选项或配置。这个步骤在打印结果之前执行,可能是为了确保所有的选项都被正确处理。parse_opt()# 调用 notebook_init 函数,这个函数可能用于初始化 Jupyter Notebook 环境或打印系统信息。这有助于在输出结果之前提供上下文信息,比如正在运行的系统环境。notebook_init()  # print system info# 将之前收集的测试结果 y 转换为 Pandas DataFrame py ,并指定列名为 'Format' 和 'Export'。这样,结果可以以表格的形式呈现,便于阅读和分析。py = pd.DataFrame(y, columns=['Format', 'Export'])# 记录导出测试完成的信息,并打印测试耗时。这里使用 time.time() 函数获取当前时间,并减去之前记录的时间 t ,得到整个测试过程的耗时。LOGGER.info(f'\nExports complete ({time.time() - t:.2f}s)')    # 导出完成({time.time() - t:.2f}s) 。# 将 DataFrame py 转换为字符串,并使用日志记录器 LOGGER 打印出来。这样,测试结果就会被输出到日志中。LOGGER.info(str(py))# 函数返回包含导出测试结果的 DataFrame py 。这允许调用者进一步处理或分析测试结果。return py# 这段代码的目的是汇总测试结果,并以表格的形式打印出来,同时返回结果以便进一步使用。这个过程有助于快速了解模型权重文件在不同导出格式下的测试情况。
# test 函数用于测试 YOLO 模型权重文件在不同导出格式下的导出功能是否成功,并返回一个包含测试结果的 DataFrame。这个函数不涉及模型性能的测试,只关注导出功能是否正常工作。

4.def parse_opt(): 

# 这段代码定义了一个名为 parse_opt 的函数,它使用 Python 的 argparse 模块来解析命令行参数。这个函数创建了一个参数解析器,定义了一系列的命令行选项,并解析这些选项。
# 定义了一个名为 parse_opt 的函数,没有参数。
def parse_opt():# 创建一个新的参数解析器对象。parser = argparse.ArgumentParser()# 添加一个命令行参数 -weights ,用于 指定模型权重文件的路径 。如果用户没有提供这个参数,它将默认为 ROOT / 'yolo.pt' 。parser.add_argument('--weights', type=str, default=ROOT / 'yolo.pt', help='weights path')# 添加一个命令行参数 -imgsz (或 -img 或 -img-size ),用于 指定推理时的图像尺寸(像素) 。默认值为 640。parser.add_argument('--imgsz', '--img', '--img-size', type=int, default=640, help='inference size (pixels)')# 添加一个命令行参数 --batch-size ,用于 指定批量大小 。默认值为 1。parser.add_argument('--batch-size', type=int, default=1, help='batch size')# 添加一个命令行参数 --data ,用于 指定数据集配置文件的路径 。默认值为 ROOT / 'data/coco128.yaml' 。parser.add_argument('--data', type=str, default=ROOT / 'data/coco128.yaml', help='dataset.yaml path')# 添加一个命令行参数 --device ,用于 指定使用的设备(如 CPU 或 GPU) 。默认为空字符串,意味着将自动选择设备。parser.add_argument('--device', default='', help='cuda device, i.e. 0 or 0,1,2,3 or cpu')# 添加一个命令行参数 --half ,用于 指定是否使用半精度(FP16)推理 。如果提供了这个参数,将启用半精度推理。parser.add_argument('--half', action='store_true', help='use FP16 half-precision inference')# 添加一个命令行参数 --test ,用于 指定是否仅测试模型的导出功能 。parser.add_argument('--test', action='store_true', help='test exports only')# 添加一个命令行参数 --pt-only ,用于 指定是否仅测试 PyTorch 格式的模型 。parser.add_argument('--pt-only', action='store_true', help='test PyTorch only')# 添加一个命令行参数 --hard-fail ,用于 指定在发生错误或性能指标低于最小值时是否抛出异常 。parser.add_argument('--hard-fail', nargs='?', const=True, default=False, help='Exception on error or < min metric')# 解析命令行参数,并将解析结果存储在 opt 变量中。opt = parser.parse_args()# 检查 opt.data 参数指定的 YAML 文件是否存在且有效。# def check_yaml(file, suffix=('.yaml', '.yml')):# -> 检查一个 YAML 文件是否存在,如果不存在且文件是一个网址,则下载该文件。这个函数还检查文件名后缀是否符合 YAML 文件的标准后缀。调用 check_file 函数,并传入 file 和 suffix 参数。 check_file 函数会检查文件是否存在,如果不存在且是一个网址,则下载文件,并确保文件后缀符合传入的 suffix 参数。# -> return check_file(file, suffix)opt.data = check_yaml(opt.data)  # check YAML# vars(object)# vars() 函数在 Python 中用于获取对象的属性字典。这个字典包含了对象的大部分属性,但不包括方法和其他一些特殊的属性。对于用户自定义的对象, vars() 返回的字典包含了对象的 __dict__ 属性,这是一个包含对象所有属性的字典。# 参数说明 :# object :要获取属性字典的对象。# 返回值 :# 返回指定对象的属性字典。# 注意事项 :# vars() 对于内置类型(如 int 、 float 、 list 等)返回的是一个包含魔术方法和特殊属性的字典,这些属性通常是不可访问的。# 对于自定义对象, vars() 返回的是对象的 __dict__ 属性,如果对象没有定义 __dict__ ,则可能返回一个空字典或者抛出 TypeError 。# 在 Python 3 中, vars() 也可以用于获取内置函数的全局变量字典。# vars() 函数是一个内置函数,通常用于调试和访问对象的内部状态,但在处理复杂对象时应该谨慎使用,因为直接修改对象的属性可能会导致不可预测的行为。# 打印所有解析后的命令行参数。# def print_args(args: Optional[dict] = None, show_file=True, show_func=False): -> 打印函数的参数。这个函数可以显示当前函数的参数,或者如果提供了参数字典,也可以显示任意函数的参数。print_args(vars(opt))# 返回包含所有命令行参数的对象 opt 。return opt
# parse_opt 函数是一个参数解析函数,它定义了一组命令行参数,并解析用户提供的参数值。如果用户没有提供某个参数的值,将使用默认值。这个函数还检查了数据集配置文件的有效性,并打印了所有解析后的参数,最后返回这些参数,以便在程序的其他部分使用。

5.def main(opt): 

# 这段代码定义了一个名为 main 的函数,它根据传入的参数 opt 决定是调用 test 函数还是 run 函数。
# 定义了一个名为 main 的函数,它接受一个名为 1.opt 的参数。
def main(opt):# 一个条件表达式,根据 opt.test 的值决定执行哪个函数。# **vars(opt) : vars(opt) 将 opt 对象转换为一个字典, ** 操作符用于将这个字典解包为关键字参数。# if opt.test :如果 opt.test 为 True ,则调用 test 函数,并将 opt 对象中的所有属性作为参数传递给 test 函数。# else run(**vars(opt)) :如果 opt.test 为 False ,则调用 run 函数,并将 opt 对象中的所有属性作为参数传递给 run 函数。test(**vars(opt)) if opt.test else run(**vars(opt))
# main 函数是一个简单的分发函数,它根据 opt.test 参数的值来决定执行 test 函数还是 run 函数,并将命令行解析得到的参数传递给相应的函数。这种方式使得程序的入口点更加简洁,并且可以根据用户的选择执行不同的逻辑流程。

6.if __name__ == "__main__": 

# 这段代码是 Python 脚本中常见的模式,用于判断当前脚本是否作为主程序运行,而不是作为模块被其他脚本导入。
# 一个条件判断语句。 __name__ 是一个内置变量,当 Python 文件作为脚本直接运行时, __name__ 的值为 "__main__" 。如果文件是被导入的,那么 __name__ 的值将是文件名(不含 .py 扩展名)。
if __name__ == "__main__":# 如果当前脚本是作为主程序运行的,那么调用 parse_opt 函数来解析命令行参数,并将返回的选项对象存储在变量 opt 中。opt = parse_opt()# 接着,调用 main 函数,并将 opt 作为参数传递给它。 main 函数将根据 opt 中的参数决定执行哪个功能函数( test 或 run )。main(opt)
# 这段代码的作用是确保当 Python 文件被直接执行时,会执行一些操作(在这里是解析命令行参数并根据这些参数调用 main 函数)。如果文件是被其他 Python 脚本作为模块导入的,那么这些操作将不会被执行,这有助于避免不必要的代码执行和潜在的变量污染。这是一种良好的编程实践,使得代码更加模块化,易于测试和维护。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/495960.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Edge Scdn是用来干什么的?

酷盾安全Edge Scdn&#xff0c;即边缘式高防御内容分发网络&#xff0c;主要是通过分布在不同地理位置的多个节点&#xff0c;使用户能够更快地访问网站内容。同时&#xff0c;Edge Scdn通过先进的技术手段&#xff0c;提高了网上内容传输的安全性&#xff0c;防止各种网络攻击…

牛客周赛73B:JAVA

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 题目描述 \hspace{15pt}小红拿到了正整数 xxx &#xff0c;她希望你找到一个长度为 kkk 的区间&#xff0c;满足区间内恰好有 nnn 个数是 xxx 的倍数。你能帮帮她吗&#xff1f; 输入描述: …

微信小程序中遇到过的问题

记录微信小程序中遇到的问题&#xff08;持续更新ing&#xff09; 问题描述&#xff1a;1. WXML中无法直接调用JavaScript方法。2. css中无法直接引用背景图片。3. 关于右上角胶囊按钮。4. 数据绑定问题。5. 事件处理问题。 问题描述&#xff1a; 1. WXML中无法直接调用JavaSc…

Docker 安装mysql ,redis,nacos

一、Mysql 一、Docker安装Mysql 1、启动Docker 启动&#xff1a;sudo systemctl start dockerservice docker start 停止&#xff1a;systemctl stop docker 重启&#xff1a;systemctl restart docker 2、查询mysql docker search mysql 3、安装mysql 3.1.默认拉取最新版…

Leecode刷题C语言之字符串及其反转中是否存在同一子字符串

执行结果:通过 执行用时和内存消耗如下&#xff1a; bool isSubstringPresent(char* s) {int i,lenstrlen(s),end;for(i0;i<len-1;i){if(s[i]s[i1]) return true;for(endlen-1;end>1;end--){if(s[i]s[end]&&s[i1]s[end-1]) return true;}}return false; }解…

uniapp登录

第一步整登录 先整个appid APPID和APPSecret https://developers.weixin.qq.com/community/develop/article/doc/000ca4601b8f70e379febac985b413 一个账号只能整一个小程序 正确流程 调用uni.login https://juejin.cn/post/7126553599445827621 https://www.jb51.net/a…

【开源免费】基于SpringBoot+Vue.JS安康旅游网站(JAVA毕业设计)

本文项目编号 T 098 &#xff0c;文末自助获取源码 \color{red}{T098&#xff0c;文末自助获取源码} T098&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…

AIGC:生成图像动力学

文章目录 前言一、介绍二、方法2.1、运动预测模块运动纹理 2.2、图像渲染模块 三、数据集实验总结 前言 让静态的风景图能够动起来真的很有意思&#xff0c;不得不说CVPR2024 best paper实质名归&#xff0c;创意十足的一篇文章&#xff01;&#xff01;&#xff01; paper&a…

cesium入门学习二

之前学习了cesium的一些基本操作&#xff0c;现在学习cesium怎么加载模型&#xff0c;以及一些其他操作。 1.学习汇总目录 第一篇&#xff1a;cesium入门学习一-CSDN博客 2.cesium效果显示以及代码 2.1 加载模型并显示 效果&#xff1a; js代码&#xff1a; // 创建 Ces…

路由策略

控制层流量 --- 路由协议传递路由信息时产生的流量 数据层流量 --- 设备访问目标地址时产生的流量 所谓的路由策略----在控制层面转发流量的过程中&#xff0c;截取流量&#xff0c;之后修改流量再转发或不转发的技术&#xff0c;最终达到影响路由器路由表的生成&#xff0c…

网络安全 - Cross-site scripting

1.1.1 摘要 在本系列的第一篇博文中&#xff0c;我向大家介绍了SQL Injection常用的攻击和防范的技术。这个漏洞可以导致一些非常严重的后果&#xff0c;但幸运的是我们可以通过限制用户数据库的权限、使用参数化的SQL语句或使用ORM等技术来防范SQL Injection的发生&#xff0c…

一、Hadoop概述

文章目录 一、Hadoop是什么二、Hadoop发展历史三、Hadoop三大发行版本1. Apache Hadoop2. Cloudera Hadoop3. Hortonworks Hadoop四、Hadoop优势1. 高可靠性2. 高扩展性3. 高效性4. 高容错性五、Hadoop 组成1. Hadoop1.x、2.x、3.x区别2. HDFS 架构概述3. YARN 架构概述4. MapR…

信息安全管理与评估赛题第9套

全国职业院校技能大赛 高等职业教育组 信息安全管理与评估 赛题九 模块一 网络平台搭建与设备安全防护 1 赛项时间 共计180分钟。 2 赛项信息 竞赛阶段 任务阶段 竞赛任务 竞赛时间 分值 第一阶段 网络平台搭建与设备安全防护 任务1 网络平台搭建 XX:XX- XX:XX 50 任务2…

低代码开发中 DDD 领域驱动的页面权限控制

在低代码开发的领域中&#xff0c;应用安全与灵活性是两大关键考量因素。领域驱动设计&#xff08;DDD&#xff09;作为一种在软件设计领域广泛应用且颇具影响力的方法论&#xff0c;正逐渐在低代码开发的页面权限控制方面展现出其独特的价值与潜力。本文旨在客观地探讨如何借助…

目录jangow-01-1.0.1靶机

靶机 ip&#xff1a;192.168.152.155 把靶机的网络模式调成和攻击机kali一样的网络模式&#xff0c;我的kali是NAT模式, 在系统启动时(长按shift键)直到显示以下界面 ,我们选第二个&#xff0c;按回车。 继续选择第二个&#xff0c;这次按 e 进入编辑页面 接下来&#xff0c;…

微信小程序 不同角色进入不同页面、呈现不同底部导航栏

遇到这个需求之前一直使用的小程序默认底部导航栏&#xff0c;且小程序默认入口页面为pages/index/index&#xff0c;要使不同角色呈现不同底部导航栏&#xff0c;必须要在不同页面引用不同的自定义导航栏。本篇将结合分包&#xff08;subPackages&#xff09;展开以下三步叙述…

【GeekBand】C++设计模式笔记15_Proxy_代理模式

1. “接口隔离” 模式 在组件构建过程中&#xff0c;某些接口之间直接的依赖常常会带来很多问题&#xff0c;甚至根本无法实现。采用添加一层间接&#xff08;稳定&#xff09;接口&#xff0c;来隔离本来互相紧密关联的接口是一种常见的解决方案。典型模式 FacadeProxyAdapte…

网络安全之接入控制

身份鉴别 ​ 定义:验证主题真实身份与其所声称的身份是否符合的过程&#xff0c;主体可以是用户、进程、主机。同时也可实现防重放&#xff0c;防假冒。 ​ 分类:单向鉴别、双向鉴别、三向鉴别。 ​ 主题身份标识信息:密钥、用户名和口令、证书和私钥 Internet接入控制过程 …

UE5 崩溃问题汇总!!!

Using bundled DotNet SDK version: 6.0.302 ERROR: UnrealBuildTool.dll not found in "..\..\Engine\Binaries\DotNET\UnrealBuildTool\UnrealBuildTool.dll" 在你遇到这种极奇崩溃的BUG &#xff0c;难以解决的时候。 尝试了N种方法&#xff0c;都不行的解决方法。…

docker 搭建集群

准备3台机器&#xff1a; #dockermaster 192.168.31.150 sudo hostnamectl set-hostname dockermaster #初始化主节点 docker swarm init --advertise-addr 192.168.31.150 #查看集群是否搭建成功 docker node ls #dockernode1 192.168.31.151 sudo hostnamectl set-hostname …