YOLOv10-1.1部分代码阅读笔记-build.py
build.py
ultralytics\data\build.py
目录
build.py
1.所需的库和模块
2.class InfiniteDataLoader(dataloader.DataLoader):
3.class _RepeatSampler:
4.def seed_worker(worker_id):
5.def build_yolo_dataset(cfg, img_path, batch, data, mode="train", rect=False, stride=32):
6.def build_dataloader(dataset, batch, workers, shuffle=True, rank=-1):
7.def check_source(source):
8.def load_inference_source(source=None, batch=1, vid_stride=1, buffer=False):
1.所需的库和模块
# Ultralytics YOLO 🚀, AGPL-3.0 licenseimport os
import random
from pathlib import Pathimport numpy as np
import torch
from PIL import Image
from torch.utils.data import dataloader, distributedfrom ultralytics.data.loaders import (LOADERS,LoadImagesAndVideos,LoadPilAndNumpy,LoadScreenshots,LoadStreams,LoadTensor,SourceTypes,autocast_list,
)
from ultralytics.data.utils import IMG_FORMATS, VID_FORMATS
from ultralytics.utils import RANK, colorstr
from ultralytics.utils.checks import check_file
from .dataset import YOLODataset
from .utils import PIN_MEMORY
2.class InfiniteDataLoader(dataloader.DataLoader):
# 这段代码定义了一个名为 InfiniteDataLoader 的类,它继承自PyTorch的 DataLoader 类。这个类的目的是创建一个可以无限迭代的数据加载器,即使数据集中的数据有限。这在某些训练场景中非常有用,例如当需要进行长时间的训练并且不希望在每个epoch结束时停止训练时。
# 定义类 InfiniteDataLoader ,继承自 DataLoader 。
class InfiniteDataLoader(dataloader.DataLoader):# 重用工作器的数据加载器。# 使用与原始数据加载器相同的语法。"""Dataloader that reuses workers.Uses same syntax as vanilla DataLoader."""# 定义初始化方法,接收任意数量的位置参数 *args 和关键字参数 **kwargs ,这些参数将传递给父类 DataLoader 的初始化方法。def __init__(self, *args, **kwargs):# 无限循环使用 worker 的 Dataloader,继承自 DataLoader。"""Dataloader that infinitely recycles workers, inherits from DataLoader."""# 调用父类 DataLoader 的初始化方法,初始化数据加载器。super().__init__(*args, **kwargs)# object.__setattr__(name, value)# 在Python中, object.__setattr__() 是一个特殊方法,用于设置对象的属性。它是 object 类的一个方法,而 object 是Python中所有类的基类。 __setattr__() 方法在设置对象属性时被自动调用,但也可以在子类中被重写以自定义属性赋值的行为。# 参数 :# name :要设置的属性的名称。# value :属性的值。# 行为 :# 当对一个对象的属性进行赋值操作时,例如 obj.attr = value ,Python会自动调用该对象的 __setattr__() 方法。这个方法的默认实现会设置一个名为 name 的属性,其值为 value 。# 为什么使用 object.__setattr__ :# 在某些情况下,你可能需要直接调用 __setattr__() 方法,特别是当你需要绕过属性赋值的默认行为时。例如,你可能想要在设置属性之前执行一些额外的检查或操作。# 注意事项 :# 使用 object.__setattr__() 时,应该谨慎,因为它会绕过属性的正常赋值机制,包括可能的属性监视器或装饰器。# 在大多数情况下,直接使用 obj.attr = value 就足够了,除非有特殊需求需要自定义属性赋值的行为。# 使用 object.__setattr__ 方法设置 batch_sampler 属性,将其替换为 _RepeatSampler 实例。 _RepeatSampler 是一个自定义的采样器,用于重复采样,使得数据加载器可以无限迭代。object.__setattr__(self, "batch_sampler", _RepeatSampler(self.batch_sampler))# 创建一个 迭代器 self.iterator ,用于 迭代数据加载器 。self.iterator = super().__iter__()# 定义 __len__ 方法,返回数据加载器的长度。def __len__(self):# 返回批量采样器的采样器的长度。"""Returns the length of the batch sampler's sampler."""# 返回 batch_sampler 中的 sampler 的长度,即 数据集的大小 。return len(self.batch_sampler.sampler)# 定义 __iter__ 方法,用于迭代数据加载器。def __iter__(self):# 创建一个无限重复的采样器。"""Creates a sampler that repeats indefinitely."""# 在 __iter__ 方法中,使用一个循环迭代 len(self) 次,每次调用 next(self.iterator) 获取下一个批次的数据,并使用 yield 关键字返回。这使得数据加载器可以无限迭代,即使数据集中的数据有限。for _ in range(len(self)):yield next(self.iterator)# 定义 reset 方法,用于重置数据加载器。def reset(self):# 重置迭代器。# 当我们想要在训练时修改数据集的设置时,这很有用。"""Reset iterator.This is useful when we want to modify settings of dataset while training."""# 调用 self._get_iterator() 方法重新创建一个迭代器,重置数据加载器的迭代状态。self.iterator = self._get_iterator()
# InfiniteDataLoader 类通过继承 DataLoader 并修改其行为,实现了无限迭代的功能。这在需要长时间训练且不希望在每个epoch结束时停止训练的场景中非常有用。通过使用 _RepeatSampler 采样器,数据加载器可以在数据集结束时重新开始,从而实现无限迭代。 reset 方法允许用户在需要时重置数据加载器的迭代状态。
3.class _RepeatSampler:
# 这段代码定义了一个名为 _RepeatSampler 的类,其目的是创建一个可以无限重复的采样器,用于与 InfiniteDataLoader 类结合,实现数据加载器的无限迭代功能。
# 定义类 _RepeatSampler 。
class _RepeatSampler:# 永远重复的采样器。"""Sampler that repeats forever.Args:sampler (Dataset.sampler): The sampler to repeat."""# 定义初始化方法,接收一个参数。# 1.sampler :这是一个采样器对象,通常用于 DataLoader 中以决定数据的加载顺序。def __init__(self, sampler):# 初始化一个无限重复给定采样器的对象。"""Initializes an object that repeats a given sampler indefinitely."""# 将传入的 sampler 对象存储为实例属性,以便在后续的迭代中使用。self.sampler = sampler# 定义 __iter__ 方法,这是 Python 迭代器协议的一部分,用于使类的实例能够被迭代。def __iter__(self):# 迭代‘采样器’并产生其内容。"""Iterates over the 'sampler' and yields its contents."""# 使用一个无限循环 while True ,确保迭代过程可以无限进行。在每次循环中,使用 yield from 语句来委托迭代过程给 self.sampler 。 iter(self.sampler) 会获取 sampler 的迭代器, yield from 则会从这个迭代器中逐个产生元素,直到迭代器耗尽。由于 while True 的存在,一旦 sampler 的迭代器耗尽,循环会重新开始,从而实现无限重复。while True:yield from iter(self.sampler)
# _RepeatSampler 类通过简单的迭代器委托和无限循环,实现了采样器的无限重复功能。当与 InfiniteDataLoader 结合使用时,它允许数据加载器在数据集结束时自动重新开始,从而实现无限迭代,这对于某些需要长时间持续训练的机器学习任务非常有用。
4.def seed_worker(worker_id):
# 这段代码定义了一个名为 seed_worker 的函数,其目的是为 PyTorch 数据加载器的每个工作进程设置随机种子。这有助于确保在多进程数据加载时,每个工作进程生成的随机数序列是可重现的,从而提高实验的可重复性。
# 定义函数 seed_worker ,接收一个参数。 # noqa 是一个注释,用于告诉代码检查工具忽略这一行的检查。
# 1.worker_id :这是工作进程的唯一标识符。
def seed_worker(worker_id): # noqa# 设置数据加载器工作器种子 https://pytorch.org/docs/stable/notes/randomness.html#dataloader。"""Set dataloader worker seed https://pytorch.org/docs/stable/notes/randomness.html#dataloader."""# torch.initial_seed() -> int# torch.initial_seed() 函数返回用于生成随机数的初始种子,类型为 Python 的 long 整数。这个函数通常用于获取当前随机数生成器的初始种子值,以便在需要时可以重现相同的随机数序列。# 返回值 :# 返回一个 long 整数,表示当前随机数生成器的初始种子。# 使用场景 :# 多进程数据加载 :在使用 DataLoader 的多进程数据加载时,每个工作进程需要设置不同的随机种子,以确保每个进程生成的随机数序列是不同的。 torch.initial_seed() 可以用于获取当前工作进程的初始种子,并在此基础上设置其他随机数生成器的种子。# 调试和重现 :在调试和重现实验结果时,获取和设置初始种子可以帮助确保每次运行的随机数序列是相同的。# 注意事项 :# torch.initial_seed() 返回的是当前随机数生成器的初始种子,这个值在每次调用 torch.manual_seed() 时会被设置。# 在多进程环境中,每个工作进程的初始种子是不同的,通常是由主进程的初始种子加上工作进程的 ID 计算得到的。# 在子进程中运行 torch.initial_seed() ,返回的就是 torch 当前的随机数种子,即 base_seed + worker_id 。# 因为每个 epoch 开始时,主进程都会重新生成一个 base_seed,所以 base_seed 是随 epoch 变化而变化的随机数。 # 此外,torch.initial_seed() 返回的是 long int 类型,而Numpy只接受 uint 类型([0, 2**32 - 1]),所以需要对 2**32 取模。# 使用 torch.initial_seed() 获取当前工作进程的初始随机种子。 torch.initial_seed() 返回一个长整型数,通常是一个非常大的数。为了确保种子值在 32 位整数范围内,使用模运算 % 2**32 将其限制在 0 到 2^32-1 之间。worker_seed = torch.initial_seed() % 2**32# numpy.random.seed(seed=None)# np.random.seed() 是 NumPy 库中的一个函数,用于设置随机数生成器的种子。通过设置种子,可以确保每次运行代码时生成的随机数序列是相同的,这对于调试和重现实验结果非常有用。# 参数 :# seed : int, array_like, or None 种子值。可以是一个整数、一个数组或 None 。如果为 None ,则从操作系统提供的随机源中获取种子值。# 使用场景 :# 调试 :在调试过程中,设置固定的随机种子可以确保每次运行代码时生成的随机数序列相同,便于定位和修复问题。# 重现实验结果 :在科学研究和机器学习实验中,设置固定的随机种子可以确保实验结果的可重现性。# 多进程数据加载 :在多进程环境中,每个工作进程需要设置不同的随机种子,以确保每个进程生成的随机数序列是不同的。这可以通过结合工作进程的 ID 和主进程的种子值来实现。# 注意事项 :# np.random.seed() 只影响 NumPy 的随机数生成器,不影响 Python 标准库 random 模块的随机数生成器。# 在多进程环境中,每个工作进程应独立设置随机种子,以避免生成相同的随机数序列。# 使用 np.random.seed(worker_seed) 设置 NumPy 的随机种子为 worker_seed 。这确保了在该工作进程中,所有使用 NumPy 生成的随机数都是可重现的。np.random.seed(worker_seed)# random.seed(a=None, version=2)# random.seed() 是 Python 标准库 random 模块中的一个函数,用于初始化随机数生成器的种子。这个函数确保了随机数生成器产生的随机数序列是可重复的,即在相同的种子下,每次运行程序时产生的随机数序列都是相同的。# 参数 :# a :种子值,可以是任何 hashable(可哈希)对象。如果为 None ,则使用当前时间作为种子。# version :随机数生成器的版本,可以是 1 或 2。默认为 2。版本 2 在 Python 3.2.3 和 3.3.0 中引入,提供了更好的随机性。# 作用 :# 当你提供一个特定的种子值时, random.seed() 会重置随机数生成器的状态,使得随后的随机数生成可以预测。# 如果不提供种子值(或为 None ),则随机数生成器将使用一个不可预测的值(通常是当前时间)作为种子,这使得每次程序运行时产生的随机数序列都是不同的。# 使用 random.seed(worker_seed) 设置 Python 标准库 random 模块的随机种子为 worker_seed 。这确保了在该工作进程中,所有使用 random 模块生成的随机数也是可重现的。random.seed(worker_seed)
# seed_worker 函数通过为每个工作进程设置相同的随机种子,确保了在多进程数据加载时,每个工作进程生成的随机数序列是可重现的。这对于需要使用随机性(如数据增强、随机采样等)的机器学习任务非常有用,特别是在多进程环境中,可以显著提高实验的可重复性。通常,这个函数会在创建 DataLoader 时通过 worker_init_fn 参数传递,以确保每个工作进程在启动时正确设置随机种子。
5.def build_yolo_dataset(cfg, img_path, batch, data, mode="train", rect=False, stride=32):
# 这段代码定义了一个名为 build_yolo_dataset 的函数,其目的是根据给定的配置和参数构建一个用于 YOLO 模型训练或验证的 YOLODataset 实例。这个函数封装了 YOLODataset 的创建过程,使得数据集的构建更加灵活和方便。
# 定义函数 build_yolo_dataset ,接收以下参数 :
# 1.cfg :配置对象,包含多种配置参数。
# 2.img_path :图像路径,可以是单个文件路径或包含多个文件路径的列表。
# 3.batch :批量大小。
# 4.data :数据配置,通常包含数据集的路径和其他相关信息。
# 5.mode :模式,可以是 "train" 或 "val" ,默认为 "train" 。
# 6.rect :是否使用矩形批次, 默认为 False 。
# 7.stride :模型的步长,默认为 32。
def build_yolo_dataset(cfg, img_path, batch, data, mode="train", rect=False, stride=32):# 构建 YOLO 数据集。"""Build YOLO Dataset."""# 返回一个 YOLODataset 实例,配置如下。# class YOLODataset(BaseDataset):# -> 用于处理YOLO模型的数据集。# -> def __init__(self, *args, data=None, task="detect", **kwargs):return YOLODataset(# 图像路径,可以是单个文件路径或包含多个文件路径的列表。img_path=img_path,# 图像大小,从 cfg 中获取。imgsz=cfg.imgsz,# 批量大小,从 batch 参数中获取。batch_size=batch,# 是否进行数据增强,仅在训练模式下为 True 。augment=mode == "train", # augmentation# 超参数配置,直接使用 cfg 。hyp=cfg, # TODO: probably add a get_hyps_from_cfg function# 是否使用矩形批次,从 cfg.rect 或 rect 参数中获取。rect=cfg.rect or rect, # rectangular batches# 缓存设置,从 cfg.cache 中获取,如果未设置则为 None 。cache=cfg.cache or None,# 是否为单类别训练,从 cfg.single_cls 中获取,如果未设置则为 False 。single_cls=cfg.single_cls or False,# 模型的步长,从 stride 参数中获取并转换为整数。stride=int(stride),# 填充比例,训练模式下为 0.0 ,验证模式下为 0.5 。pad=0.0 if mode == "train" else 0.5,# 日志前缀,使用 colorstr 函数添加颜色,显示模式信息。prefix=colorstr(f"{mode}: "),# 任务类型,从 cfg.task 中获取。task=cfg.task,# 类别信息,从 cfg.classes 中获取。classes=cfg.classes,# 数据配置,包含数据集的路径和其他相关信息。data=data,# 数据集的使用比例,训练模式下从 cfg.fraction 中获取,验证模式下为 1.0 。fraction=cfg.fraction if mode == "train" else 1.0,)
# build_yolo_dataset 函数通过封装 YOLODataset 的创建过程,提供了一个灵活且方便的方式来构建 YOLO 模型的训练或验证数据集。通过传入不同的参数,可以轻松地调整数据集的配置,适用于不同的训练和验证场景。这个函数特别适用于需要动态构建数据集的场景,如超参数调优、不同数据集的实验等。
6.def build_dataloader(dataset, batch, workers, shuffle=True, rank=-1):
# 这段代码定义了一个名为 build_dataloader 的函数,其目的是根据给定的参数构建一个用于训练或验证的数据加载器( DataLoader )。这个函数可以返回一个 InfiniteDataLoader 或 DataLoader ,具体取决于是否需要无限迭代数据集。这个函数特别适用于分布式训练和多进程数据加载的场景。
# 定义函数 build_dataloader ,接收以下参数 :
# 1.dataset :数据集对象,继承自 torch.utils.data.Dataset 。
# 2.batch :批量大小。
# 3.workers :工作进程数。
# 4.shuffle :是否打乱数据,默认为 True 。
# 5.rank :分布式训练中的进程排名,默认为 -1 ,表示非分布式训练。
def build_dataloader(dataset, batch, workers, shuffle=True, rank=-1):# 返回用于训练或验证集的 InfiniteDataLoader 或 DataLoader。"""Return an InfiniteDataLoader or DataLoader for training or validation set."""# 将批量大小 batch 限制为 数据集长度的最小值 ,确保批量大小不会超过数据集的大小。batch = min(batch, len(dataset))# 获取可用的 CUDA 设备数量。nd = torch.cuda.device_count() # number of CUDA devices# 计算 实际使用的工作进程数 nw ,确保不超过系统可用的 CPU 核心数除以 CUDA 设备数量(至少为1),并且不超过用户指定的工作进程数 workers 。nw = min([os.cpu_count() // max(nd, 1), workers]) # number of workers# torch.utils.data.distributed.DistributedSampler(dataset, num_replicas=None, rank=None, shuffle=True, seed=0, drop_last=False)# torch.utils.data.distributed.DistributedSampler 类的构造函数用于创建一个新的分布式采样器实例,它主要用于分布式训练环境中,以确保每个进程只处理数据集的一部分,从而实现数据的均匀分配。# 参数 :# dataset ( Dataset ) :要采样的数据集对象。# num_replicas ( int ,可选) :分布式环境中的总副本(进程)数量。默认值为 None ,在这种情况下,它会尝试从当前的分布式环境变量中获取 world_size 。# rank ( int ,可选) :当前进程的排名或ID。默认值为 None ,在这种情况下,它会尝试从当前的分布式环境变量中获取 rank 。# shuffle ( bool ) :是否在每个epoch开始时打乱数据集的采样顺序。默认值为 True 。# seed ( int ) :用于打乱数据集的随机种子。确保在所有进程中使用相同的种子以获得一致的打乱结果。默认值为 0 。# drop_last ( bool ) :如果为 True ,则在数据集不能被均匀分配时,丢弃最后一部分数据以确保每个进程处理相同数量的数据。如果为 False ,则可能有些进程会处理更多的数据。默认值为 False 。# 返回值 :# 返回一个新的 DistributedSampler 实例。# DistributedSampler 类在 PyTorch 中用于分布式训练,以下是它的一些常用属性和方法 :# 属性 :# dataset : 返回与采样器关联的数据集。# num_replicas : 返回分布式环境中的总副本(进程)数量。# rank : 返回当前进程的排名或ID。# epoch : 返回当前的epoch数。这个属性在每个epoch开始时通过调用 set_epoch() 方法更新。# 方法 :# set_epoch(epoch) : 设置当前的epoch数。这对于确保在每个epoch中数据被打乱是必要的,特别是在 shuffle=True 时。# __iter__() : 返回一个迭代器,该迭代器产生当前epoch中被采样器选中的数据集索引。# __len__() : 返回当前epoch中被采样器选中的数据集索引的数量。# update() : 更新采样器的状态,这个方法在 PyTorch 的某些版本中存在,用于重新配置采样器的参数。# DistributedSampler 的主要作用是确保在分布式训练中,每个进程都能够处理数据集的不同部分,从而提高数据加载的效率和训练的可扩展性。通过在每个epoch开始时调用 set_epoch() 方法,可以确保数据在每个epoch中都被重新打乱,这对于模型的训练是非常重要的。# 如果 rank 为 -1 ,表示非分布式训练, sampler 为 None 。否则,使用 DistributedSampler 进行分布式采样,确保每个进程处理不同的数据子集。sampler = None if rank == -1 else distributed.DistributedSampler(dataset, shuffle=shuffle)# torch.Generator(device='cpu')# 在PyTorch中, torch.Generator 是一个用于生成随机数的伪随机数生成器(PRNG)的类。它主要用于生成与特定种子或设备相关的随机数,以确保实验的可重复性。# 参数 :# device : 指定生成器所在的设备,可以是'cpu'或'cuda'设备。# 主要方法 :# manual_seed(seed) : 设置生成器的种子。 seed : 一个整数,用于初始化生成器。# seed() : 自动设置生成器的种子。 这将生成一个随机种子,确保每次运行代码时生成的随机数不同。# get_state() : 返回生成器的当前状态。# set_state(state) : 设置生成器的状态。 state : 一个张量,表示生成器的状态。# initial_seed() : 返回生成器的初始种子。# 注意事项 :# 当使用多个设备(如CPU和GPU)时,需要为每个设备创建一个独立的 Generator 实例,并设置不同的种子,以确保随机数的生成是独立的。# 在分布式训练或多线程环境中,正确管理生成器的状态非常重要,以避免随机数生成的冲突。# torch.Generator 提供了一种灵活的方式来控制随机数的生成,使得实验和模型训练更加可重复和可控。# 创建一个 torch.Generator 对象,并设置一个固定的随机种子,确保每个工作进程生成的随机数序列是可重现的。 RANK 是一个全局变量,表示当前进程的排名。generator = torch.Generator()generator.manual_seed(6148914691236517205 + RANK)# 返回一个 InfiniteDataLoader 实例,配置如下。return InfiniteDataLoader(# 数据集对象。dataset=dataset,# 批量大小。batch_size=batch,# 是否打乱数据,仅在 sampler 为 None 时生效。shuffle=shuffle and sampler is None,# 工作进程数。num_workers=nw,# 采样器对象,用于分布式训练。sampler=sampler,# 是否使用 pinned memory,提高数据传输效率。pin_memory=PIN_MEMORY,# 数据批处理函数,从数据集对象中获取。collate_fn=getattr(dataset, "collate_fn", None),# 工作进程初始化函数,用于设置每个工作进程的随机种子。worker_init_fn=seed_worker,# 随机数生成器,用于生成可重现的随机数序列。generator=generator,)
# build_dataloader 函数通过封装 InfiniteDataLoader 的创建过程,提供了一个灵活且方便的方式来构建数据加载器。这个函数特别适用于分布式训练和多进程数据加载的场景,确保每个工作进程生成的随机数序列是可重现的,并且可以灵活地配置数据加载器的各种参数。通过这个函数,可以轻松地构建适用于训练和验证的数据加载器,提高代码的复用性和灵活性。
7.def check_source(source):
# 这段代码定义了一个名为 check_source 的函数,其目的是检查和处理输入的图像或视频源,并确定其类型。这个函数返回处理后的源以及一些标志,这些标志指示源的类型,如是否为摄像头、屏幕截图、内存中的图像、文件路径或PyTorch张量。
# 定义函数 check_source ,接收一个参数。
# 1.source :它可以是多种类型,包括字符串、整数、路径、列表、元组、PIL图像对象、NumPy数组或PyTorch张量。
def check_source(source):# 检查源类型并返回相应的标志值。"""Check source type and return corresponding flag values."""# 初始化几个布尔标志,用于表示源的类型。webcam, screenshot, from_img, in_memory, tensor = False, False, False, False, False# 如果 source 是字符串、整数或路径。if isinstance(source, (str, int, Path)): # int for local usb camera# 将 source 转换为字符串。source = str(source)# 检查 source 是否为文件路径,通过检查文件扩展名是否在支持的图像或视频格式中。is_file = Path(source).suffix[1:] in (IMG_FORMATS | VID_FORMATS)# 检查 source 是否为URL,通过检查是否以特定协议开头。is_url = source.lower().startswith(("https://", "http://", "rtsp://", "rtmp://", "tcp://"))# 如果 source 是数字、以 .streams 结尾或是一个URL但不是文件,则认为它是摄像头源。webcam = source.isnumeric() or source.endswith(".streams") or (is_url and not is_file)# 如果 source 是 "screen" ,则认为它是屏幕截图源。screenshot = source.lower() == "screen"# 如果 source 是URL且是文件,则下载文件。if is_url and is_file:# def check_file(file, suffix="", download=True, hard=True):# -> 用于检查文件的存在性,并根据需要下载或搜索文件。如果满足上述条件之一,则返回文件名。返回下载后的文件名。根据搜索结果返回文件名或抛出错误。# -> return file / return file / return files[0] if len(files) else [] if hard else file # return filesource = check_file(source) # download# 如果 source 是 LOADERS 类型之一,认为它是内存中的图像源。# LOADERS = (LoadStreams, LoadPilAndNumpy, LoadImagesAndVideos, LoadScreenshots)elif isinstance(source, LOADERS):in_memory = True# 如果 source 是列表或元组,调用 autocast_list 函数将所有元素转换为PIL图像对象或NumPy数组,并设置 from_img 标志。elif isinstance(source, (list, tuple)):# def autocast_list(source): -> 将一个包含不同类型的图像源的列表转换为一个统一的图像对象列表,这些图像对象可以是PIL图像或NumPy数组,以便进行后续的图像处理或分析。返回 转换后的图像对象列表 files 。 -> return filessource = autocast_list(source) # convert all list elements to PIL or np arraysfrom_img = True# 如果 source 是PIL图像对象或NumPy数组,设置 from_img 标志。elif isinstance(source, (Image.Image, np.ndarray)):from_img = True# 如果 source 是PyTorch张量,设置 tensor 标志。elif isinstance(source, torch.Tensor):tensor = True# 如果 source 的类型不匹配上述任何一种,抛出 TypeError 异常,提示不支持的图像类型。else:raise TypeError("Unsupported image type. For supported types see https://docs.ultralytics.com/modes/predict") # 不支持的图像类型。有关支持的类型,请参阅 https://docs.ultralytics.com/modes/predict。# 返回处理后的 source 以及几个布尔标志(webcam摄像头, screenshot屏幕截图, from_img, in_memory, tensor),这些标志指示源的类型。return source, webcam, screenshot, from_img, in_memory, tensor
# check_source 函数通过检查输入的 source ,确定其类型,并返回处理后的源和相应的类型标志。这使得函数能够灵活地处理多种类型的图像或视频源,包括文件路径、URL、摄像头、屏幕截图、内存中的图像和PyTorch张量。通过这个函数,可以轻松地在应用程序中集成多种数据源的处理逻辑,提高代码的复用性和灵活性。
8.def load_inference_source(source=None, batch=1, vid_stride=1, buffer=False):
# 这段代码定义了一个名为 load_inference_source 的函数,其目的是根据给定的输入源 source 加载相应的数据集,并返回一个数据加载器。这个函数通过调用 check_source 函数来确定输入源的类型,并根据类型选择合适的加载器类来处理数据。
# 定义函数 load_inference_source ,接收以下参数 :
# 1.source :输入源,可以是多种类型,如字符串、路径、列表、元组、PIL图像对象、NumPy数组或PyTorch张量。
# 2.batch :批量大小,默认为1。
# 3.vid_stride :视频帧率步长,默认为1。
# 4.buffer :是否使用缓冲区,默认为 False 。
def load_inference_source(source=None, batch=1, vid_stride=1, buffer=False):# 加载用于对象检测的推理源并应用必要的转换。"""Loads an inference source for object detection and applies necessary transformations.Args:source (str, Path, Tensor, PIL.Image, np.ndarray): The input source for inference.batch (int, optional): Batch size for dataloaders. Default is 1.vid_stride (int, optional): The frame interval for video sources. Default is 1.buffer (bool, optional): Determined whether stream frames will be buffered. Default is False.Returns:dataset (Dataset): A dataset object for the specified input source."""# 调用 check_source 函数,检查输入源 source 并返回处理后的源以及多个布尔标志,这些标志指示源的类型。source, stream, screenshot, from_img, in_memory, tensor = check_source(source)# 根据 in_memory 标志,确定 source_type 。如果 in_memory 为 True ,则从 source 中获取 source_type ;否则,使用 SourceTypes 枚举类创建 source_type 。# class SourceTypes:# -> 用于表示预测输入源的各种类型。 dataclass 装饰器可以自动生成特殊方法,如 __init__ 、 __repr__ 和 __eq__ ,使得类的定义更加简洁和易于维护。source_type = source.source_type if in_memory else SourceTypes(stream, screenshot, from_img, tensor)# 根据输入源的类型,选择合适的加载器类来处理数据。# Dataloader# 如果 tensor 为 True ,使用 LoadTensor 类。if tensor:dataset = LoadTensor(source)# 如果 in_memory 为 True ,直接使用 source 作为数据集。elif in_memory:dataset = source# 如果 stream 为 True ,使用 LoadStreams 类。elif stream:dataset = LoadStreams(source, vid_stride=vid_stride, buffer=buffer)# 如果 screenshot 为 True ,使用 LoadScreenshots 类。elif screenshot:dataset = LoadScreenshots(source)# 如果 from_img 为 True ,使用 LoadPilAndNumpy 类。elif from_img:dataset = LoadPilAndNumpy(source)# 其他情况下,使用 LoadImagesAndVideos 类。else:dataset = LoadImagesAndVideos(source, batch=batch, vid_stride=vid_stride)# Attach source types to the dataset# 将 source_type 附加到数据集对象上,以便后续使用。setattr(dataset, "source_type", source_type)# 返回构建好的数据集对象 dataset 。return dataset
# load_inference_source 函数通过调用 check_source 函数确定输入源的类型,并根据类型选择合适的加载器类来处理数据。这个函数提供了一个灵活且方便的方式来加载多种类型的输入源,适用于不同的推理场景。通过这个函数,可以轻松地构建适用于训练和验证的数据加载器,提高代码的复用性和灵活性。
相关文章:
YOLOv10-1.1部分代码阅读笔记-build.py
build.py ultralytics\data\build.py 目录 build.py 1.所需的库和模块 2.class InfiniteDataLoader(dataloader.DataLoader): 3.class _RepeatSampler: 4.def seed_worker(worker_id): 5.def build_yolo_dataset(cfg, img_path, batch, data, mode"train"…...
c++ 中的容器 vector、deque 和 list 的区别
表格汇总: 容器存储结构随机访问性能中间插入/删除性能两端插入/删除性能内存管理特点迭代器类型适用场景vector连续存储的动态数组 O ( 1 ) O(1) O(1) O ( n ) O(n) O(n)(需要移动元素)末尾: O ( 1 ) O(1) O(1),头部…...
如何有效学习PyTorch:从基础到实践的全面指南
随着人工智能和深度学习技术的飞速发展,PyTorch作为当前最流行的深度学习框架之一,凭借其动态计算图、灵活的编程模型以及强大的社区支持,在学术界和工业界均得到了广泛应用。本文旨在为初学者和有一定基础的读者提供一套系统、全面的PyTorch…...
大模型WebUI:Gradio全解11——Chatbots:融合大模型的多模态聊天机器人(3)
大模型WebUI:Gradio全解11——Chatbot:融合大模型的多模态聊天机器人(3) 前言本篇摘要11. Chatbot:融合大模型的多模态聊天机器人11.3 组件Chatbot及ChatMessage11.3.1 Chatbot:聊天机器人组件1. API参数2.…...
MTK6768 Android13 亮度条均匀调节实现
文章目录 需求:问题现象:需求实现疑难问题点:相关资源修改的文件调试技巧具体需求实现去除亮度弹框设置去掉跳转逻辑SystemUI亮度条长按跳转屏蔽 实现亮度均匀调节PhoneWindowManager.javaBrightnessUtils convertLinearToGammaFloatBrightne…...
力扣560和为K的数组
给你一个整数数组 nums 和一个整数 k ,请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1: 输入:nums [1,1,1], k 2 输出:2示例 2: 输入:nums [1,2,3], …...
【MVCC过程中会加锁吗?】
MVCC过程中会加锁吗? 一、MVCC的工作原理二、MVCC的并发控制三、MVCC中的加锁情况在MVCC(Multi-Version Concurrency Control,多版本并发控制)过程中, 通常不需要加锁来控制并发访问。 MVCC是一种数据并发控制技术,它允许在不同的事务中对同一数据进行并发访问,而不需要…...
LeetCode100之搜索二维矩阵(46)--Java
1.问题描述 给你一个满足下述两条属性的 m x n 整数矩阵: 每行中的整数从左到右按非严格递增顺序排列。每行的第一个整数大于前一行的最后一个整数。 给你一个整数 target ,如果 target 在矩阵中,返回 true ;否则,返回…...
Android BottomNavigationView不加icon使text垂直居中,完美解决。
这个问题网上千篇一律的设置iconsize为0,labale固定什么的,都没有效果。我的这个基本上所有人用都会有效果。 问题解决之前的效果:垂直方向,文本不居中,看着很难受 问题解决之后:舒服多了 其实很简单&…...
cmake + vscode + mingw 开发环境配置
1.软件准备 准备如下软件: mingw64(安装完成之后检测是否有环境变量,如果没有需要配置) cmake(安装完成之后检测是否有环境变量,如果没有需要配置) vscode(安装CMake插件࿰…...
【GPON实战】ONT和OLT的vlan处理机制(一)
引言 ONT和OLT支持多种vlan配置,包括单层tag vlan,默认vlan(PVID),vlan转换,vlan翻译,双层vlan等等。那ONT和OLT是如何处理的呢?本文将介绍ONT和OLT对vlan的处理机制,第一篇介绍单层vlan场景ONT和OLT如何打vlan和剥离vlan,第二篇将介绍OLT是如何通过omci消息将vlan的…...
Qt模块概览(核心模块、GUI模块等)
Qt 模块概览 Qt 是一个跨平台的应用程序开发框架,广泛用于开发图形用户界面(GUI)程序,在前面的章节中,我们已经介绍了许多控件、布局的用法,这些都属于QT的GUI模块,当然QT也支持非 GUI 程序的开发,也就是核心模块。 Qt 框架由多个模块组成,每个模块提供特定的功能。…...
七大排序算法
文章目录 排序的概念及引用1.插入排序2.希尔排序(缩小增量排序)3.选择排序4.堆排序5.冒泡排序6.快速排序7.归并排序8.代码排序部分的测试9.代码加效果大致测试时间(仅供参考) 排序的概念及引用 排序:将数据按照特定的规律排成递增或递减的操作 稳定性:…...
代理模式实现
一、概念:代理模式属于结构型设计模式。客户端不能直接访问一个对象,可以通过代理的第三者来间接访问该对象,代理对象控制着对于原对象的访问,并允许在客户端访问对象的前后进行一些扩展和处理;这种设置模式称为代理模…...
国产linux系统(银河麒麟,统信uos)使用 PageOffice 实现后台批量生成PDF文档
PageOffice 国产版 :支持信创系统,支持银河麒麟V10和统信UOS,支持X86(intel、兆芯、海光等)、ARM(飞腾、鲲鹏、麒麟等)、龙芯(LoogArch)芯片架构。 PageOffice 版本&…...
基于若依的脚手架,扩展了flowable、mybatisPlus、lombok、前端美化
前言 若依框架可以说是非常优秀的框架,奈何前端一直有点丑,而且集成的东西比较少,我就基于若依,做了一个轻美化版本,主要集成了工作流、mybatisPlus、lombok等工具。 因为我也在用这个框架为公司做系统,所…...
LeetCode 热题 100 | 矩阵
矩阵基础 使用哈希数组来标记当前行或者列是否出现0按层模拟 73. 矩阵置零 题目讲解:LeetCode 重点: 使用标记数组:用两个标记数组分别记录每一行和每一列是否有零出现。使用两个标记变量:用矩阵的第一行和第一列代替两个标记数组…...
(经过验证)在 Ubuntu 系统中为 VSCode、PyCharm 终端及 Jupyter Notebook 配置代理的完整方案
文章目录 1. 通过系统环境变量配置代理步骤一:打开终端步骤二:编辑 ~/.bashrc 文件步骤三:添加代理环境变量步骤四:保存并关闭文件步骤五:使配置生效步骤六:重启相关应用步骤七:使用代理函数 2.…...
【Linux】sed编辑器二
一、处理多行命令 sed编辑器有3种可用于处理多行文本的特殊命令。 N:加入数据流中的下一行,创建一个多行组进行处理;D:删除多行组中的一行;P:打印多行组中的一行。 1、next命令:N 单行next命…...
STM32 FreeRTOS移植
目录 FreeRTOS源码结构介绍 获取源码 1、 官网下载 2、 Github下载 源码结构介绍 源码整体结构 FreeRTOS文件夹结构 Source文件夹结构如下 portable文件夹结构 RVDS文件夹 MemMang文件夹 FreeRTOS在基于寄存器项目中移植步骤 目录添加源码文件 工程添加源码文件 …...
python 寻找数据拐点
import numpy as np import cv2 from scipy.signal import find_peaks# 示例数据 y_data [365.63258786, 318.34824281, 258.28434505, 228.8913738, 190.87220447, 158.28434505, 129.53035144, 111.95846645, 111.95846645, 120.26517572, 140.71246006, 161.79872204, 180.…...
Windows 蓝牙驱动开发-蓝牙设备栈
蓝牙设备栈 蓝牙驱动程序堆栈包含 Microsoft 为蓝牙协议提供支持的核心部分。 有了这个堆栈,已启用蓝牙的设备可以彼此定位并建立连接。 在此类连接中,设备可以通过各种应用程序交换数据并彼此交互。 下图显示了蓝牙驱动程序堆栈中的模块,以…...
css hover样式调试
调试 hover后才出现的元素如何调试 打开开发者工具,鼠标放在hover时才出现的元素上,然后点击右键不要选中任何选项,将鼠标移动到开发者工具的调试面板中按下N键,此时悬浮的元素不会消失,定位成功 调试元素悬浮样式 …...
【Unity】unity3D 调用LoadSceneAsync 场景切换后比较暗 部门材质丢失
解决方法:两个场景使用同样灯光 现象 直接进入第二个场景是可以正常显示 调用LoadSceneAsync来切换后,第二个场景出现比较暗的情况 解决方法:两个场景使用同样灯光,在loading 的场景中加入灯光。 Light—Directional Light 如果…...
代码随想录二刷|字符串总结
代码随想录二刷|字符串 反转数字 题干 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。 不要给另外的数组分配额外的空间,你必须**原地修改输入数组**、使用 O(1) 的额外空间解决这一问题。 思路 class Soluti…...
Linux浅谈——管道、网络配置和客户端软件的使用
目录 一、管道 1、管道符 2、过滤功能 3、特殊功能 4、扩展处理 5、xargs命令扩展 二、网络配置 1、ifconfig查看网络信息 2、配置文件详解 网卡配置文件位置 3、systemctl查看网卡状态 4、systemctl启动/重启/停止网卡 三、客户端软件 1、什么是SSH 2、常用SSH终…...
HBASE学习(一)
1.HBASE基础架构, 1.1 参考: HBase集群架构与读写优化:理解核心机制与性能提升-CSDN博客 1.2问题: 1.FLUSH对hbase的影响 2. HLog和memstore的区别 hlog中存储的是操作记录,比如写、删除。而memstor中存储的是写入…...
深入解析 Linux 内核中的 IPoIB 驱动:ipoib.h 文件分析
引言 InfiniBand 是一种高性能、低延迟的网络互联技术,广泛应用于高性能计算(HPC)和数据中心。为了在 InfiniBand 网络上运行传统的 IP 协议栈,Linux 内核提供了 IP over InfiniBand (IPoIB) 驱动。ipoib.h 是 IPoIB 驱动的核心头文件,定义了驱动所需的数据结构、常量、宏…...
2025-01-16 思考-人生下半场的归途-那温和的良夜
摘要: 转眼已经不再年轻,生命赠与的礼物,也可以说开始陷入归途。不再被外界推着走之后,发现可以有更多的精力和时间可以用来内视,不被外界种种束缚。 在人生的下半场,其实更多的是接受失去,正如人生上半场…...
【C++篇】红黑树的实现
目录 前言: 一,红黑树的概念 1.1,红黑树的规则 1.2,红黑树的最长路径 1.3,红黑树的效率分析 二,红黑树的实现 2.1,红黑树的结构 2.2,红黑树的插入 2.2.1,大致过程…...
Linux的常用命令(一)
目录 一、文件处理命令 1.文件处理命令ls 2.文件处理命令cd 3.文件处理命令pwd 4.文件处理命令touch 5.文件处理命令mkdir 6.文件处理命令cp 7.文件处理命令mv 8.文件处理命令rm 9.文件处理命令cat 10.文件处理命令more 11.文件处理命令head 12.文件处理命令tail …...
小米vela系统(基于开源nuttx内核)——如何使用信号量进行PV操作
如何使用信号量进行PV操作 前言信号量1. 信号量简介2. NuttX中信号量的创建与使用2.1 Nuttx信号量的初始化和销毁2.2 信号量的等待和发布 3. 信号量的实际应用:下载任务示例3.1 实际代码3.2 代码说明3.3 执行说明 4. 信号量的优势与应用场景5. 常见应用场景…...
(01)STM32—GPIO
1. GPIO简介 GPIO(General Purpose Input Output)通用输入输出端口。可配置为8种输入输出模式。引脚电平:0V~3.3V,部分引脚可容忍5V。输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时…...
浏览器输入http形式网址后自动跳转https解决方法
一、问题描述 使用浏览器 网上冲浪 时会遇到一个情况: 在浏览器中输入“http域名”后会自动变成“https 域名”的形式,此时“https 域名”的网站可能已停止对外提供服务了,这时会出现如下不友好的网页提示: 二、处理方法&#x…...
mybatis的多对一、一对多的用法
目录 1、使用VO聚合对象(可以解决这两种情况) 多对一: 一对多: 2、非聚合的多对一做法: 3、非聚合的一对多做法: 1、使用VO聚合对象(可以解决这两种情况) 当我需要多对一、一对…...
生产管理看板助力节能科技公司实现数据自动化管理
在节能科技公司的生产过程中,数据管理的自动化是提高生产效率和产品质量的关键。然而,许多公司在数据记录、展示、对比和存档方面仍面临诸多痛点,如产品检测数据无法自动记录、缺乏直观的产线状态展示、检测数据对比繁琐耗时,以及…...
网络科技有限公司网络设计
网络科技有限公司网络设计 摘要:伴随着信息科技发展,上网变得一件必不可少的事情,当然网络安全对我们也是越来越重要。像我们的传统网结构是无法为我们的上网提供一个安全的网络环境。锐雯网络科技有限公司就是以网络安全为基本的对网络惊醒…...
C++没有Y Combinator?使用 C++ 实现 Y Combinator(中英双语)
C 中并没有直接内置的 Y Combinator,但通过现代 C 特性(如 lambda 表达式 和 std::function),我们可以实现一个类似 Y Combinator 的功能。 下面我们来详细讲解如何在 C 中实现 Y Combinator。 使用 C 实现 Y Combinator 目标 …...
YOLOv10-1.1部分代码阅读笔记-loaders.py
loaders.py ultralytics\data\loaders.py 目录 loaders.py 1.所需的库和模块 2.class SourceTypes: 3.class LoadStreams: 4.class LoadScreenshots: 5.class LoadImagesAndVideos: 6.class LoadPilAndNumpy: 7.class LoadTensor: 8.def autocast_list(source…...
《戴森球计划》异地远程联机攻略
文章目录 前言1. 下载MOD2.配置cpolar内网穿透3. 主机开启联机3.1 玩家加入游戏 4. 配置固定的TCP端口5. 游玩体验 前言 《戴森球计划》不仅是一款融合了科幻冒险与经营管理元素的游戏,更是一个让玩家在浩瀚宇宙中尽情探索和创造的平台。在这个游戏中,你…...
【Linux跬步积累】—— 线程
🌏博客主页:PH_modest的博客主页 🚩当前专栏:Linux跬步积累 💌其他专栏: 🔴 每日一题 🟡 C跬步积累 🟢 C语言跬步积累 🌈座右铭:广积粮࿰…...
计算机网络 (46)简单网络管理协议SNMP
前言 简单网络管理协议(SNMP,Simple Network Management Protocol)是一种用于在计算机网络中管理网络节点的标准协议。 一、概述 SNMP是基于TCP/IP五层协议中的应用层协议,它使网络管理员能够管理网络效能,发现并解决网…...
模型 前景理论
系列文章 分享模型,了解更多👉 模型_思维模型目录。面对得失,人们更怕失,参考点定输赢。 1 前景理论的应用 1.1 前景理论在投资决策中的应用案例 假设一位投资者面临两个投资方案的选择: 方案A:投资一只…...
Android ScrollView嵌套X5WebView大片空白问题
scrollview嵌套后webview的高度不可控。留有大片空白。 注:官方不建议scrollview嵌套webview 最好让webview自身滚动 解决方案: act_news_detail_wv.setWebViewClient(new WebViewClient() {Overridepublic void onPageFinished(WebView webView, Str…...
频域增强通道注意力机制EFCAM模型详解及代码复现
背景与动机 在深度学习领域,如何有效处理时间序列数据一直是一个重要的研究方向。近年来, 频域分析技术 在时间序列处理中展现出了巨大潜力,特别是离散余弦变换(DCT)因其能够高效捕捉低频信息并避免高频噪声干扰而受到广泛关注。 FECAM模型的开发正是基于这一背景,旨在…...
[计算机网络]一. 计算机网络概论第一部分
作者申明:作者所有文章借助了各个渠道的图片视频以及资料,在此致谢。作者所有文章不用于盈利,只是用于个人学习。 1.0推荐动画 【网络】半小时看懂<计算机网络>_哔哩哔哩_bilibili 1.1计算机网络在信息时代的作用 在当今信息时代&…...
第十三章:数据库技术
文章目录: 一:基础 1.概念 2.特点 3.常见数据库品牌 4.数据库应⽤系统 4.1 C/S 4.2 B/S 5.数据模型的分类 6.名词解析 7.关系运算 二:Access 1.基础 2.操作 2.1 建立表 2.2 维护表 2.3 创建查询 2.4 创建窗体 2.5 创建报表…...
中等难度——python实现电子宠物和截图工具
import io # 文件处理 import nt # windows nt 库直接获取对应的磁盘空间 import time # 时间 import zlib # 加解密 import ctypes # 调用 import struct # 处理字节二进制 import base64 # 编解码 import threading # 线程 import tkinter as tk # tk from datetime…...
构建优雅、高效的 Nodejs 命令行工具 - Archons
目录 项目简介安装基本用法样例创建一个简单的命令行工具使用archons上下文创建进度条 最后 项目地址: https://github.com/noctisynth/archons Bug反馈或功能请求:https://github.com/noctisynth/archons/issues 项目简介 Archons意思是“执政官”,我使…...
源码编译安装httpd 2.4,提供系统服务管理脚本并测试
1.安装httpd wget https://downloads.apache.org/httpd/httpd-2.4.62.tar.gzbmcv tar -zxvf httpd-2.4.62.tar.gz cd httpd-2.4.62 2.安装依赖包 sudo yum install -y gcc make apr-devel apr-util-devel pcre-devel sudo yum groupinstall "Development Tools"…...