YOLOv12_ultralytics-8.3.145_2025_5_27部分代碼閱讀筆記-augment.py

augment.py

ultralytics\data\augment.py

目錄

augment.py

1.所需的庫和模塊

2.class BaseTransform:?

3.class Compose:?

4.class BaseMixTransform:?

5.class CutMix(BaseMixTransform):?

6.class CopyPaste(BaseMixTransform):?

7.def v8_transforms(dataset, imgsz, hyp, stretch=False):?

8.class ToTensor:?


1.所需的庫和模塊

# Ultralytics 🚀 AGPL-3.0 License - https://ultralytics.com/licenseimport math
import random
from copy import deepcopy
from typing import List, Tuple, Unionimport cv2
import numpy as np
import torch
from PIL import Image
from torch.nn import functional as Ffrom ultralytics.data.utils import polygons2masks, polygons2masks_overlap
from ultralytics.utils import LOGGER, colorstr
from ultralytics.utils.checks import check_version
from ultralytics.utils.instance import Instances
from ultralytics.utils.metrics import bbox_ioa
from ultralytics.utils.ops import segment2box, xywh2xyxy, xyxyxyxy2xywhr
from ultralytics.utils.torch_utils import TORCHVISION_0_10, TORCHVISION_0_11, TORCHVISION_0_13DEFAULT_MEAN = (0.0, 0.0, 0.0)
DEFAULT_STD = (1.0, 1.0, 1.0)

2.class BaseTransform:?

# 這段代碼定義了一個名為 BaseTransform 的類,它是一個基礎的變換類,用于對圖像及其相關標簽(如實例分割和語義分割)進行一系列的變換操作。
# 定義了一個名為 BaseTransform 的類。這個類可以作為其他具體變換類的基類,提供了一個通用的框架,用于對圖像及其相關標簽進行變換。
class BaseTransform:# Ultralytics 庫中圖像轉換的基類。# 此類是實現各種圖像處理操作的基礎,旨在兼容分類和語義分割任務。# 方法:# apply_image:將圖像轉換應用于標簽。# apply_instances:將轉換應用于標簽中的對象實例。# apply_semantic:將語義分割應用于圖像。# __call__:將所有標簽轉換應用于圖像、實例和語義蒙版。"""Base class for image transformations in the Ultralytics library.This class serves as a foundation for implementing various image processing operations, designed to becompatible with both classification and semantic segmentation tasks.Methods:apply_image: Apply image transformations to labels.apply_instances: Apply transformations to object instances in labels.apply_semantic: Apply semantic segmentation to an image.__call__: Apply all label transformations to an image, instances, and semantic masks.Examples:>>> transform = BaseTransform()>>> labels = {"image": np.array(...), "instances": [...], "semantic": np.array(...)}>>> transformed_labels = transform(labels)"""# 定義了類的初始化方法 __init__ 。這個方法在創建類的實例時被調用。# -> None 表示這個方法沒有返回值。# 這里 pass 表示初始化方法目前什么也不做。在實際使用中,可以根據需要在這個方法中初始化一些屬性或參數。def __init__(self) -> None:# 初始化 BaseTransform 對象。# 此構造函數設置基礎轉換對象,該對象可針對特定圖像處理任務進行擴展。它旨在兼容分類和語義分割。"""Initialize the BaseTransform object.This constructor sets up the base transformation object, which can be extended for specific imageprocessing tasks. It is designed to be compatible with both classification and semantic segmentation.Examples:>>> transform = BaseTransform()"""pass# 定義了一個名為 apply_image 的方法,用于對圖像進行變換。# 參數 1.labels 可能是一個包含圖像數據及其標簽的結構,但具體含義需要根據實際使用場景來確定。# 這里 pass 表示這個方法目前什么也不做。在實際使用中,可以根據需要在這個方法中實現具體的圖像變換邏輯,如裁剪、縮放、旋轉等。def apply_image(self, labels):# 將圖像轉換應用于標簽。# 此方法旨在被子類重寫,以實現特定的圖像轉換邏輯。在其基本形式中,它返回未更改的輸入標簽。"""Apply image transformations to labels.This method is intended to be overridden by subclasses to implement specific image transformationlogic. In its base form, it returns the input labels unchanged.Args:labels (Any): The input labels to be transformed. The exact type and structure of labels mayvary depending on the specific implementation.Returns:(Any): The transformed labels. In the base implementation, this is identical to the input.Examples:>>> transform = BaseTransform()>>> original_labels = [1, 2, 3]>>> transformed_labels = transform.apply_image(original_labels)>>> print(transformed_labels)[1, 2, 3]"""pass# 定義了一個名為 apply_instances 的方法,用于對實例分割標簽進行變換。# 參數 1.labels 可能是一個包含實例分割標簽的數據結構,但具體含義需要根據實際使用場景來確定。# 這里 pass 表示這個方法目前什么也不做。在實際使用中,可以根據需要在這個方法中實現具體的實例分割標簽變換邏輯,如調整邊界框、掩碼等。def apply_instances(self, labels):# 對標簽中的對象實例應用變換。# 此方法負責對給定標簽中的對象實例應用各種變換。它旨在被子類重寫,以實現特定的實例變換邏輯。"""Apply transformations to object instances in labels.This method is responsible for applying various transformations to object instances within the givenlabels. It is designed to be overridden by subclasses to implement specific instance transformationlogic.Args:labels (dict): A dictionary containing label information, including object instances.Returns:(dict): The modified labels dictionary with transformed object instances.Examples:>>> transform = BaseTransform()>>> labels = {"instances": Instances(xyxy=torch.rand(5, 4), cls=torch.randint(0, 80, (5,)))}>>> transformed_labels = transform.apply_instances(labels)"""pass# 定義了一個名為 apply_semantic 的方法,用于對語義分割標簽進行變換。# 參數 1.labels 可能是一個包含語義分割標簽的數據結構,但具體含義需要根據實際使用場景來確定。# 這里 pass 表示這個方法目前什么也不做。在實際使用中,可以根據需要在這個方法中實現具體的語義分割標簽變換邏輯,如調整像素標簽等。def apply_semantic(self, labels):# 對圖像應用語義分割轉換。# 此方法旨在被子類重寫,以實現特定的語義分割轉換。其基本形式不執行任何操作。"""Apply semantic segmentation transformations to an image.This method is intended to be overridden by subclasses to implement specific semantic segmentationtransformations. In its base form, it does not perform any operations.Args:labels (Any): The input labels or semantic segmentation mask to be transformed.Returns:(Any): The transformed semantic segmentation mask or labels.Examples:>>> transform = BaseTransform()>>> semantic_mask = np.zeros((100, 100), dtype=np.uint8)>>> transformed_mask = transform.apply_semantic(semantic_mask)"""pass# 定義了一個名為 __call__ 的方法,使得類的實例可以像函數一樣被調用。# 參數 1.labels 是一個包含圖像及其標簽的數據結構。# 在這個方法中,依次調用了 apply_image 、 apply_instances 和 apply_semantic 方法,對圖像及其標簽進行一系列的變換操作。def __call__(self, labels):# 將所有標簽轉換應用于圖像、實例和語義蒙版。# 此方法協調將 BaseTransform 類中定義的各種轉換應用于輸入標簽。它依次調用 apply_image 和 apply_instances 方法分別處理圖像和對象實例。# 參數:# labels (dict):包含圖像數據和注釋的字典。預期鍵包括“img”(表示圖像數據)和“instances”(表示對象實例)。# 返回:# (dict):包含轉換后圖像和實例的輸入標簽字典。"""Apply all label transformations to an image, instances, and semantic masks.This method orchestrates the application of various transformations defined in the BaseTransform classto the input labels. It sequentially calls the apply_image and apply_instances methods to process theimage and object instances, respectively.Args:labels (dict): A dictionary containing image data and annotations. Expected keys include 'img' forthe image data, and 'instances' for object instances.Returns:(dict): The input labels dictionary with transformed image and instances.Examples:>>> transform = BaseTransform()>>> labels = {"img": np.random.rand(640, 640, 3), "instances": []}>>> transformed_labels = transform(labels)"""# 這三行代碼分別調用了 apply_image 、 apply_instances 和 apply_semantic 方法,對輸入的 labels 進行相應的變換操作。# 這種設計使得 BaseTransform 類可以作為一個通用的變換框架,通過在子類中實現具體的變換邏輯,來實現不同的變換操作。self.apply_image(labels)self.apply_instances(labels)self.apply_semantic(labels)
# 這段代碼定義了一個名為 BaseTransform 的基礎變換類,它提供了一個通用的框架,用于對圖像及其相關標簽(如實例分割和語義分割)進行一系列的變換操作。通過定義 apply_image 、 apply_instances 和 apply_semantic 方法,類可以分別對圖像、實例分割標簽和語義分割標簽進行變換。而 __call__ 方法則使得類的實例可以像函數一樣被調用,并依次執行這些變換操作。這種設計使得 BaseTransform 類可以方便地被擴展和復用,適用于各種圖像處理和計算機視覺任務。

3.class Compose:?

# 這段代碼定義了一個名為 Compose 的類,用于將多個變換操作組合起來,形成一個可調用的變換序列。
# 定義了一個名為 Compose 的類,用于組合多個變換操作。
class Compose:# 用于組合多個圖像變換的類。# 屬性:# transforms (List[Callable]):按順序應用的變換函數列表。# 方法:# __call__:對輸入數據應用一系列變換。# append:將新的變換附加到現有的變換列表中。# insert:在變換列表中的指定索引處插入新的變換。# __getitem__:使用索引檢索特定變換或一組變換。# __setitem__:使用索引設置特定變換或一組變換。# tolist:將變換列表轉換為標準 Python 列表。"""A class for composing multiple image transformations.Attributes:transforms (List[Callable]): A list of transformation functions to be applied sequentially.Methods:__call__: Apply a series of transformations to input data.append: Append a new transform to the existing list of transforms.insert: Insert a new transform at a specified index in the list of transforms.__getitem__: Retrieve a specific transform or a set of transforms using indexing.__setitem__: Set a specific transform or a set of transforms using indexing.tolist: Convert the list of transforms to a standard Python list.Examples:>>> transforms = [RandomFlip(), RandomPerspective(30)]>>> compose = Compose(transforms)>>> transformed_data = compose(data)>>> compose.append(CenterCrop((224, 224)))>>> compose.insert(0, RandomFlip())"""# 定義了類的初始化方法 __init__ ,接收一個參數 1.transforms ,它是一個變換操作的列表或單個變換操作。 self.transforms 用于存儲變換操作的列表。def __init__(self, transforms):# 使用轉換列表初始化 Compose 對象。"""Initialize the Compose object with a list of transforms.Args:transforms (List[Callable]): A list of callable transform objects to be applied sequentially.Examples:>>> from ultralytics.data.augment import Compose, RandomHSV, RandomFlip>>> transforms = [RandomHSV(), RandomFlip()]>>> compose = Compose(transforms)"""# 如果 transforms 是一個列表,則直接賦值給 self.transforms 。# 如果 transforms 不是列表,則將其封裝成一個列表,確保 self.transforms 始終是一個列表。self.transforms = transforms if isinstance(transforms, list) else [transforms]# 定義了類的 __call__ 方法,使得類的實例可以像函數一樣被調用。 參數 1.data 是需要被變換的數據。def __call__(self, data):# 對輸入數據應用一系列轉換。# 此方法按順序將 Compose 對象轉換中的每個轉換應用于輸入數據。"""Apply a series of transformations to input data.This method sequentially applies each transformation in the Compose object's transforms to the input data.Args:data (Any): The input data to be transformed. This can be of any type, depending on thetransformations in the list.Returns:(Any): The transformed data after applying all transformations in sequence.Examples:>>> transforms = [Transform1(), Transform2(), Transform3()]>>> compose = Compose(transforms)>>> transformed_data = compose(input_data)"""# 遍歷 self.transforms 中的每個變換操作 t ,并將 data 依次傳遞給每個變換操作。# 最終返回經過所有變換操作后的 data 。for t in self.transforms:data = t(data)return data# 定義了一個 append 方法,用于向變換操作列表中添加一個新的變換操作。 參數 1.transform 是一個變換操作。def append(self, transform):# 將新的變換附加到現有的變換列表中。"""Append a new transform to the existing list of transforms.Args:transform (BaseTransform): The transformation to be added to the composition.Examples:>>> compose = Compose([RandomFlip(), RandomPerspective()])>>> compose.append(RandomHSV())"""# 使用列表的 append 方法將新的變換操作添加到 self.transforms 中。self.transforms.append(transform)# 定義了一個 insert 方法,用于在指定位置插入一個新的變換操作。 參數 1.index 是插入的位置, transform 是新的變換操作。def insert(self, index, transform):# 在現有變換列表中的指定索引處插入新的變換。"""Insert a new transform at a specified index in the existing list of transforms.Args:index (int): The index at which to insert the new transform.transform (BaseTransform): The transform object to be inserted.Examples:>>> compose = Compose([Transform1(), Transform2()])>>> compose.insert(1, Transform3())>>> len(compose.transforms)3"""# 使用列表的 insert 方法將新的變換操作插入到指定位置。self.transforms.insert(index, transform)# 定義了 __getitem__ 方法,用于通過索引獲取子變換序列。 參數 1.index 可以是一個整數或整數列表,表示需要獲取的變換操作的索引。def __getitem__(self, index: Union[list, int]) -> "Compose":# 使用索引檢索特定變換或一組變換。# 參數:# index (int | List[int]):要檢索的變換的索引或索引列表。# 返回:# (Compose):一個包含所選變換的新 Compose 對象。# 引發:# AssertionError:如果索引不是 int 或 list 類型。"""Retrieve a specific transform or a set of transforms using indexing.Args:index (int | List[int]): Index or list of indices of the transforms to retrieve.Returns:(Compose): A new Compose object containing the selected transform(s).Raises:AssertionError: If the index is not of type int or list.Examples:>>> transforms = [RandomFlip(), RandomPerspective(10), RandomHSV(0.5, 0.5, 0.5)]>>> compose = Compose(transforms)>>> single_transform = compose[1]  # Returns a Compose object with only RandomPerspective>>> multiple_transforms = compose[0:2]  # Returns a Compose object with RandomFlip and RandomPerspective"""# 首先檢查 index 是否為整數或整數列表,如果不是則拋出異常。assert isinstance(index, (int, list)), f"The indices should be either list or int type but got {type(index)}"    # 索引應該是列表或 int 類型,但得到的是 {type(index)} 。# 如果 index 是整數,則將其轉換為列表。index = [index] if isinstance(index, int) else index# 使用列表推導式從 self.transforms 中提取指定索引的變換操作,并返回一個新的 Compose 實例。return Compose([self.transforms[i] for i in index])# 這段代碼定義了 Compose 類的 __setitem__ 方法,用于設置指定索引處的變換操作。# 定義了 __setitem__ 方法,該方法允許通過索引設置 self.transforms 中的變換操作。# 參數 1.index 可以是一個整數或整數列表,表示需要設置的索引位置。# 參數 2.value 可以是一個變換操作或變換操作列表,表示要設置的新值。# 返回值為 None ,表示該方法不返回任何值。def __setitem__(self, index: Union[list, int], value: Union[list, int]) -> None:# 使用索引在組合中設置一個或多個變換。# 參數:# index (int | List[int]):要設置變換的索引或索引列表。# value (Any | List[Any]):要在指定索引處設置的變換或變換列表。# 引發:# AssertionError:如果索引類型無效、值類型與索引類型不匹配或索引超出范圍。"""Set one or more transforms in the composition using indexing.Args:index (int | List[int]): Index or list of indices to set transforms at.value (Any | List[Any]): Transform or list of transforms to set at the specified index(es).Raises:AssertionError: If index type is invalid, value type doesn't match index type, or index is out of range.Examples:>>> compose = Compose([Transform1(), Transform2(), Transform3()])>>> compose[1] = NewTransform()  # Replace second transform>>> compose[0:2] = [NewTransform1(), NewTransform2()]  # Replace first two transforms"""# 使用 assert 語句檢查 index 是否為整數或整數列表。 如果 index 既不是整數也不是列表,拋出一個 AssertionError ,并提供錯誤信息。assert isinstance(index, (int, list)), f"The indices should be either list or int type but got {type(index)}"    # 索引應該是列表或 int 類型,但得到的是 {type(index)} 。# 如果 index 是一個列表,使用 assert 語句檢查 value 是否也是一個列表。 如果 value 不是列表,拋出一個 AssertionError ,并提供錯誤信息。if isinstance(index, list):assert isinstance(value, list), (f"The indices should be the same type as values, but got {type(index)} and {type(value)}"    # 索引應與值的類型相同,但得到的是 {type(index)} 和 {type(value)} 。)# 如果 index 是一個整數,將其轉換為一個包含該整數的列表。 同時,將 value 也轉換為一個包含該值的列表。 這樣可以統一處理單個索引和多個索引的情況。if isinstance(index, int):index, value = [index], [value]# 使用 zip 函數將 index 和 value 配對,形成一個迭代器。 遍歷這個迭代器,每次迭代中, i 是索引, v 是對應的值。for i, v in zip(index, value):# 使用 assert 語句檢查索引 i 是否在 self.transforms  的有效范圍內。 如果索引超出范圍,拋出一個 AssertionError ,并提供錯誤信息。assert i < len(self.transforms), f"list index {i} out of range {len(self.transforms)}."    # 列表索引 {i} 超出范圍 {len(self.transforms)}。# 將 self.transforms 中索引為 i 的變換操作設置為新的值 v 。self.transforms[i] = v# 這段代碼定義了 Compose 類的 __setitem__ 方法,用于設置指定索引處的變換操作。該方法支持單個索引和多個索引的設置,并且在設置過程中進行了嚴格的類型檢查和范圍檢查,確保操作的正確性和安全性。通過這種方式, Compose 類可以靈活地管理和修改變換操作列表,適用于各種數據預處理和增強任務。# 定義了一個 tolist 方法,用于將變換操作列表轉換為普通列表。def tolist(self):# 將變換列表轉換為標準 Python 列表。"""Convert the list of transforms to a standard Python list.Returns:(list): A list containing all the transform objects in the Compose instance.Examples:>>> transforms = [RandomFlip(), RandomPerspective(10), CenterCrop()]>>> compose = Compose(transforms)>>> transform_list = compose.tolist()>>> print(len(transform_list))3"""# 直接返回 self.transforms 。return self.transforms# 定義了 __repr__ 方法,用于返回類的字符串表示。def __repr__(self):# 返回 Compose 對象的字符串表示形式。"""Return a string representation of the Compose object.Returns:(str): A string representation of the Compose object, including the list of transforms.Examples:>>> transforms = [RandomFlip(), RandomPerspective(degrees=10, translate=0.1, scale=0.1)]>>> compose = Compose(transforms)>>> print(compose)Compose([RandomFlip(),RandomPerspective(degrees=10, translate=0.1, scale=0.1)])"""# 使用字符串格式化方法返回類的名稱和變換操作列表的字符串表示。return f"{self.__class__.__name__}({', '.join([f'{t}' for t in self.transforms])})"
# 這段代碼定義了一個名為 Compose 的類,用于將多個變換操作組合起來,形成一個可調用的變換序列。通過 __call__ 方法,可以依次執行所有變換操作。此外,類還提供了 append 、 insert 、 __getitem__ 、 __setitem__ 、 tolist 和 __repr__ 等方法,用于方便地管理變換操作列表。這種設計使得 Compose 類可以靈活地組合和管理多個變換操作,適用于各種數據預處理和增強任務。

4.class BaseMixTransform:?

# 這段代碼定義了一個名為 BaseMixTransform 的類,它是一個基礎的混合變換類,用于實現如Mosaic、CutMix或MixUp等數據增強技術。這些技術通過混合多個圖像及其標簽來生成新的訓練樣本,從而提高模型的泛化能力。
class BaseMixTransform:# Cutmix、MixUp 和 Mosaic 等混合變換的基類。# 此類為在數據集上實現混合變換提供了基礎。它處理基于概率的變換應用,并管理多幅圖像和標簽的混合。# 方法:# __call__:將混合變換應用于輸入標簽。# _mix_transform:由子類實現的抽象方法,用于特定的混合操作。# get_indexes:獲取待混合圖像索引的抽象方法。# _update_label_text:更新混合圖像的標簽文本。"""Base class for mix transformations like Cutmix, MixUp and Mosaic.This class provides a foundation for implementing mix transformations on datasets. It handles theprobability-based application of transforms and manages the mixing of multiple images and labels.Attributes:dataset (Any): The dataset object containing images and labels.pre_transform (Callable | None): Optional transform to apply before mixing.p (float): Probability of applying the mix transformation.Methods:__call__: Apply the mix transformation to the input labels._mix_transform: Abstract method to be implemented by subclasses for specific mix operations.get_indexes: Abstract method to get indexes of images to be mixed._update_label_text: Update label text for mixed images.Examples:>>> class CustomMixTransform(BaseMixTransform):...     def _mix_transform(self, labels):...         # Implement custom mix logic here...         return labels......     def get_indexes(self):...         return [random.randint(0, len(self.dataset) - 1) for _ in range(3)]>>> dataset = YourDataset()>>> transform = CustomMixTransform(dataset, p=0.5)>>> mixed_labels = transform(original_labels)"""# 定義了類的初始化方法 __init__ ,接收三個參數:# 1.dataset :數據集對象,用于獲取圖像及其標簽。# 2.pre_transform :可選的預變換操作,用于在混合之前對圖像進行預處理。# 3.p :混合變換的概率,默認為0.0,表示不進行混合變換。def __init__(self, dataset, pre_transform=None, p=0.0) -> None:# 初始化 BaseMixTransform 對象,用于 CutMix、MixUp 和 Mosaic 等混合變換。# 此類是圖像處理流程中實現混合變換的基礎。"""Initialize the BaseMixTransform object for mix transformations like CutMix, MixUp and Mosaic.This class serves as a base for implementing mix transformations in image processing pipelines.Args:dataset (Any): The dataset object containing images and labels for mixing.pre_transform (Callable | None): Optional transform to apply before mixing.p (float): Probability of applying the mix transformation. Should be in the range [0.0, 1.0].Examples:>>> dataset = YOLODataset("path/to/data")>>> pre_transform = Compose([RandomFlip(), RandomPerspective()])>>> mix_transform = BaseMixTransform(dataset, pre_transform, p=0.5)"""# 將傳入的參數分別賦值給類的屬性 self.dataset 、 self.pre_transform 和 self.p 。self.dataset = datasetself.pre_transform = pre_transformself.p = p# 這段代碼定義了 BaseMixTransform 類的 __call__ 方法,它實現了混合變換操作的核心邏輯。# 定義了 BaseMixTransform 類的 __call__ 方法,使得類的實例可以像函數一樣被調用。 參數 1.labels 是一個包含圖像及其標簽的數據結構,通常是一個字典。def __call__(self, labels):# 對標簽數據應用預處理變換以及 CutMix/Mixup/Mosaic 變換。# 此方法根據概率因子確定是否應用混合變換。如果應用,它將選擇其他圖像,應用預變換(如果指定),然后執行混合變換。"""Apply pre-processing transforms and cutmix/mixup/mosaic transforms to labels data.This method determines whether to apply the mix transform based on a probability factor. If applied, itselects additional images, applies pre-transforms if specified, and then performs the mix transform.Args:labels (dict): A dictionary containing label data for an image.Returns:(dict): The transformed labels dictionary, which may include mixed data from other images.Examples:>>> transform = BaseMixTransform(dataset, pre_transform=None, p=0.5)>>> result = transform({"image": img, "bboxes": boxes, "cls": classes})"""# 使用 random.uniform(0, 1) 生成一個0到1之間的隨機數。# 如果隨機數大于 self.p (混合變換的概率),則直接返回原始的 labels ,不進行混合變換。# 這一步確保了混合變換操作以指定的概率 self.p 發生。if random.uniform(0, 1) > self.p:return labels# Get index of one or three other images# 調用 self.get_indexes() 方法獲取一個或多個其他圖像的索引。indexes = self.get_indexes()# 如果返回的 indexes 是一個整數,則將其轉換為一個包含該整數的列表。 這樣可以統一處理單個索引和多個索引的情況。if isinstance(indexes, int):indexes = [indexes]# Get images information will be used for Mosaic, CutMix or MixUp# 使用列表推導式,通過 self.dataset.get_image_and_label(i) 方法獲取每個索引對應的圖像及其標簽,存儲在 mix_labels 列表中。 self.dataset.get_image_and_label(i) 方法通常返回一個包含圖像和標簽的數據結構。mix_labels = [self.dataset.get_image_and_label(i) for i in indexes]# 如果 self.pre_transform 不為 None ,則對 mix_labels 中的每個圖像及其標簽應用預變換操作。 預變換操作可以在混合之前對圖像進行一些處理,如歸一化、裁剪等。if self.pre_transform is not None:for i, data in enumerate(mix_labels):mix_labels[i] = self.pre_transform(data)# 將 mix_labels 添加到 labels 字典中,鍵為 "mix_labels" 。 這樣可以在后續的混合變換操作中訪問這些混合標簽。labels["mix_labels"] = mix_labels# Update cls and texts# 調用 self._update_label_text(labels) 方法,更新 labels 中的類別和文本標簽。 這個方法通常會處理類別ID和文本標簽的映射,確保混合后的標簽一致。labels = self._update_label_text(labels)# Mosaic, CutMix or MixUp# 調用 self._mix_transform(labels) 方法,執行具體的混合變換操作(如Mosaic、CutMix或MixUp)。 這個方法需要在子類中被具體實現,因為不同的混合變換技術有不同的實現邏輯。labels = self._mix_transform(labels)# 從 labels 字典中移除 "mix_labels" 鍵,避免后續處理中出現不必要的數據。 使用 pop 方法時,如果鍵不存在,不會拋出異常,而是返回 None 。labels.pop("mix_labels", None)# 返回經過混合變換后的 labels 。return labels# 這段代碼定義了 BaseMixTransform 類的 __call__ 方法,實現了混合變換操作的核心邏輯。該方法的主要步驟包括: 根據給定的概率決定是否進行混合變換。 隨機選擇一個或多個其他圖像及其標簽。 對這些圖像及其標簽應用預變換操作(如果提供了預變換操作)。 更新類別和文本標簽,確保類別ID與混合后的文本標簽一致。 調用具體的混合變換方法(如Mosaic、CutMix或MixUp)。 移除混合標簽,返回最終的標簽。這種設計使得 BaseMixTransform 類可以作為各種混合變換技術的基礎框架,通過在子類中實現具體的混合變換邏輯,可以方便地擴展和復用。# 定義了一個抽象方法 _mix_transform ,用于實現具體的混合變換邏輯。 這個方法在子類中需要被具體實現。def _mix_transform(self, labels):# 將 CutMix、MixUp 或 Mosaic 增強應用于標簽字典。# 此方法應由子類實現,以執行特定的混合轉換,例如 CutMix、MixUp 或 Mosaic。它會使用增強數據就地修改輸入標簽字典。"""Apply CutMix, MixUp or Mosaic augmentation to the label dictionary.This method should be implemented by subclasses to perform specific mix transformations like CutMix, MixUp orMosaic. It modifies the input label dictionary in-place with the augmented data.Args:labels (dict): A dictionary containing image and label data. Expected to have a 'mix_labels' keywith a list of additional image and label data for mixing.Returns:(dict): The modified labels dictionary with augmented data after applying the mix transform.Examples:>>> transform = BaseMixTransform(dataset)>>> labels = {"image": img, "bboxes": boxes, "mix_labels": [{"image": img2, "bboxes": boxes2}]}>>> augmented_labels = transform._mix_transform(labels)"""# 拋出一個 NotImplementedError ,表示這個方法需要在子類中被實現。raise NotImplementedError# 定義了一個方法 get_indexes ,用于獲取一個或多個其他圖像的索引。def get_indexes(self):# 獲取用于馬賽克增強的混洗索引列表。"""Get a list of shuffled indexes for mosaic augmentation.Returns:(List[int]): A list of shuffled indexes from the dataset.Examples:>>> transform = BaseMixTransform(dataset)>>> indexes = transform.get_indexes()>>> print(indexes)  # [3, 18, 7, 2]"""# 使用 random.randint 生成一個隨機索引,范圍從0到 len(self.dataset) - 1 。return random.randint(0, len(self.dataset) - 1)# 這段代碼定義了 BaseMixTransform 類中的一個靜態方法 _update_label_text ,用于更新類別和文本標簽,確保混合后的標簽一致。# 使用 @staticmethod 裝飾器定義了一個靜態方法 _update_label_text 。@staticmethod# 靜態方法不需要訪問類或實例的屬性,因此不接收 self 參數。# 參數 1.labels 是一個包含圖像及其標簽的數據結構,通常是一個字典。def _update_label_text(labels):# 更新圖像增廣中混合標簽的標簽文本和類別 ID。# 此方法處理輸入標簽字典和任何混合標簽的“texts”和“cls”字段,創建一組統一的文本標簽并相應地更新類別 ID。# 參數:# labels (dict):包含標簽信息的字典,包括“texts”和“cls”字段,以及可選的“mix_labels”字段,其中包含其他標簽字典。# 返回:# (dict):更新后的標簽字典,包含統一的文本標簽和更新的類別 ID。"""Update label text and class IDs for mixed labels in image augmentation.This method processes the 'texts' and 'cls' fields of the input labels dictionary and any mixed labels,creating a unified set of text labels and updating class IDs accordingly.Args:labels (dict): A dictionary containing label information, including 'texts' and 'cls' fields,and optionally a 'mix_labels' field with additional label dictionaries.Returns:(dict): The updated labels dictionary with unified text labels and updated class IDs.Examples:>>> labels = {...     "texts": [["cat"], ["dog"]],...     "cls": torch.tensor([[0], [1]]),...     "mix_labels": [{"texts": [["bird"], ["fish"]], "cls": torch.tensor([[0], [1]])}],... }>>> updated_labels = self._update_label_text(labels)>>> print(updated_labels["texts"])[['cat'], ['dog'], ['bird'], ['fish']]>>> print(updated_labels["cls"])tensor([[0],[1]])>>> print(updated_labels["mix_labels"][0]["cls"])tensor([[2],[3]])"""# 檢查 labels 字典中是否包含 "texts" 鍵。 如果不包含 "texts" 鍵,直接返回原始的 labels ,不進行任何處理。if "texts" not in labels:return labels# 使用列表推導式,將 labels["texts"] 和 labels["mix_labels"] 中每個混合標簽的 "texts" 合并成一個列表。 sum 函數用于將這些列表合并成一個大列表。mix_texts = sum([labels["texts"]] + [x["texts"] for x in labels["mix_labels"]], [])# 使用集合去重,確保 mix_texts 中的文本標簽是唯一的。 將每個文本標簽轉換為元組(因為列表不可哈希,不能直接作為集合的元素),然后轉換回列表。mix_texts = list({tuple(x) for x in mix_texts})# 創建一個從文本標簽到唯一ID的映射 text2id 。 使用 enumerate 函數遍歷 mix_texts ,為每個文本標簽分配一個唯一的ID。text2id = {text: i for i, text in enumerate(mix_texts)}# 遍歷 labels 和 labels["mix_labels"] 中的每個標簽。for label in [labels] + labels["mix_labels"]:# 對于每個標簽,遍歷其類別ID列表 label["cls"] :# 使用 label["cls"].squeeze(-1).tolist() 將類別ID張量轉換為列表。# 對于每個類別ID,通過 label["texts"][int(cls)] 獲取對應的文本標簽。# 使用 text2id[tuple(text)] 將文本標簽映射為新的類別ID,并更新 label["cls"] 。# 將去重后的 mix_texts 賦值給每個標簽的 "texts" 鍵。for i, cls in enumerate(label["cls"].squeeze(-1).tolist()):text = label["texts"][int(cls)]label["cls"][i] = text2id[tuple(text)]label["texts"] = mix_texts# 返回更新后的 labels 字典。return labels# 這段代碼定義了一個靜態方法 _update_label_text ,用于更新類別和文本標簽,確保混合后的標簽一致。具體步驟包括: 檢查 labels 中是否包含 "texts" 鍵,如果不包含則直接返回。 合并 labels["texts"] 和 labels["mix_labels"] 中的文本標簽。 使用集合去重,確保文本標簽是唯一的。 創建一個從文本標簽到唯一ID的映射。 遍歷 labels 和 labels["mix_labels"] ,更新每個標簽的類別ID,確保類別ID與去重后的文本標簽一致。 將去重后的文本標簽賦值給每個標簽的 "texts" 鍵。 返回更新后的 labels 。這種設計確保了在混合變換操作中,類別ID和文本標簽的一致性和唯一性,適用于各種數據增強任務。
# 這段代碼定義了一個名為 BaseMixTransform 的類,用于實現混合變換操作,如Mosaic、CutMix或MixUp。該類通過以下步驟實現混合變換: 根據給定的概率決定是否進行混合變換。 隨機選擇一個或多個其他圖像及其標簽。 對這些圖像及其標簽應用預變換操作(如果提供了預變換操作)。 更新類別和文本標簽,確保類別ID與混合后的文本標簽一致。 調用具體的混合變換方法(如Mosaic、CutMix或MixUp)。 移除混合標簽,返回最終的標簽。這種設計使得 BaseMixTransform 類可以作為各種混合變換技術的基礎框架,通過在子類中實現具體的混合變換邏輯,可以方便地擴展和復用。

5.class CutMix(BaseMixTransform):?

# 這段代碼定義了一個名為 CutMix 的類,它繼承自 BaseMixTransform ,用于實現CutMix數據增強技術。CutMix通過將一張圖像的某個區域替換為另一張圖像的相應區域,來生成新的訓練樣本。
# 定義了一個名為 CutMix 的類,繼承自 BaseMixTransform 。
class CutMix(BaseMixTransform):# 按照論文 https://arxiv.org/abs/1905.04899 中的說明,將 CutMix 增強應用于圖像數據集。# CutMix 通過將一幅圖像中的隨機矩形區域替換為另一幅圖像中的相應區域來合并兩幅圖像,并根據混合區域的面積按比例調整標簽。# 方法:# _mix_transform:將 CutMix 增強應用于輸入標簽。# _rand_bbox:為剪切區域生成隨機邊界框坐標。"""Apply CutMix augmentation to image datasets as described in the paper https://arxiv.org/abs/1905.04899.CutMix combines two images by replacing a random rectangular region of one image with the corresponding region from another image,and adjusts the labels proportionally to the area of the mixed region.Attributes:dataset (Any): The dataset to which CutMix augmentation will be applied.pre_transform (Callable | None): Optional transform to apply before CutMix.p (float): Probability of applying CutMix augmentation.beta (float): Beta distribution parameter for sampling the mixing ratio.num_areas (int): Number of areas to try to cut and mix.Methods:_mix_transform: Apply CutMix augmentation to the input labels._rand_bbox: Generate random bounding box coordinates for the cut region.Examples:>>> from ultralytics.data.augment import CutMix>>> dataset = YourDataset(...)  # Your image dataset>>> cutmix = CutMix(dataset, p=0.5)>>> augmented_labels = cutmix(original_labels)"""# 定義了 CutMix 類的初始化方法 __init__ ,接收以下參數:# 1.dataset :數據集對象,用于獲取圖像及其標簽。# 2.pre_transform :可選的預變換操作,用于在混合之前對圖像進行預處理。# 3.p :混合變換的概率,默認為0.0。# 4.beta :Beta分布的參數,用于控制CutMix區域的大小。# 5.num_areas :嘗試生成的CutMix區域數量。def __init__(self, dataset, pre_transform=None, p=0.0, beta=1.0, num_areas=3) -> None:# 初始化 CutMix 增強對象。"""Initialize the CutMix augmentation object.Args:dataset (Any): The dataset to which CutMix augmentation will be applied.pre_transform (Callable | None): Optional transform to apply before CutMix.p (float): Probability of applying CutMix augmentation.beta (float): Beta distribution parameter for sampling the mixing ratio.num_areas (int): Number of areas to try to cut and mix."""# 調用父類 BaseMixTransform 的初始化方法,初始化 dataset 、 pre_transform 和 p 。super().__init__(dataset=dataset, pre_transform=pre_transform, p=p)# 初始化 self.beta 和 self.num_areas 。self.beta = betaself.num_areas = num_areas# 這段代碼定義了 CutMix 類中的一個方法 _rand_bbox ,用于生成隨機的CutMix邊界框。# 定義了一個名為 _rand_bbox 的方法,用于生成隨機的CutMix邊界框。 參數 1.width 和 2.height 分別表示圖像的寬度和高度。def _rand_bbox(self, width, height):# 為剪切區域生成隨機邊界框坐標。"""Generate random bounding box coordinates for the cut region.Args:width (int): Width of the image.height (int): Height of the image.Returns:(tuple): (x1, y1, x2, y2) coordinates of the bounding box."""# Sample mixing ratio from Beta distribution# 使用 np.random.beta 從Beta分布中采樣一個混合比例 lam 。 Beta分布的參數為 self.beta ,這決定了CutMix區域的大小分布。 通常,Beta分布的參數 alpha 和 beta 相等,表示對稱分布。lam = np.random.beta(self.beta, self.beta)# 計算CutMix區域的大小比例 cut_ratio ,取 1.0 - lam 的平方根。cut_ratio = np.sqrt(1.0 - lam)# 根據 cut_ratio 計算CutMix區域的寬度 cut_w 和高度 cut_h 。 使用 int 函數將寬度和高度轉換為整數。cut_w = int(width * cut_ratio)cut_h = int(height * cut_ratio)# Random center# 使用 np.random.randint 隨機選擇CutMix區域的中心點 cx 和 cy 。 cx 的范圍是 [0, width) , cy 的范圍是 [0, height) 。cx = np.random.randint(width)cy = np.random.randint(height)# Bounding box coordinates# 計算CutMix區域的邊界框坐標 x1 、 y1 、 x2 和 y2 。# x1 和 y1 分別是邊界框的左上角坐標, x2 和 y2 分別是邊界框的右下角坐標。# 使用 np.clip 確保邊界框坐標在圖像范圍內,即 x1 和 y1 不小于0, x2 和 y2 不大于圖像的寬度和高度。x1 = np.clip(cx - cut_w // 2, 0, width)y1 = np.clip(cy - cut_h // 2, 0, height)x2 = np.clip(cx + cut_w // 2, 0, width)y2 = np.clip(cy + cut_h // 2, 0, height)# 返回計算得到的邊界框坐標 x1 、 y1 、 x2 和 y2 。return x1, y1, x2, y2# 這段代碼定義了一個方法 _rand_bbox ,用于生成隨機的CutMix邊界框。具體步驟包括: 從Beta分布中采樣一個混合比例 lam 。 根據混合比例計算CutMix區域的大小比例 cut_ratio 。 根據 cut_ratio 計算CutMix區域的寬度 cut_w 和高度 cut_h 。 隨機選擇CutMix區域的中心點 cx 和 cy 。 計算CutMix區域的邊界框坐標 x1 、 y1 、 x2 和 y2 ,并確保這些坐標在圖像范圍內。 返回計算得到的邊界框坐標。這種方法確保了CutMix區域的大小和位置是隨機的,從而增加了數據增強的多樣性,有助于提高模型的泛化能力。# 這段代碼定義了 CutMix 類中的 _mix_transform 方法,用于實現CutMix混合變換邏輯。CutMix通過將一張圖像的某個區域替換為另一張圖像的相應區域,來生成新的訓練樣本。# 定義了 _mix_transform 方法,用于實現CutMix混合變換邏輯。 參數 1.labels 是一個包含圖像及其標簽的數據結構,通常是一個字典。def _mix_transform(self, labels):# 對輸入標簽應用 CutMix 增強。"""Apply CutMix augmentation to the input labels.Args:labels (dict): A dictionary containing the original image and label information.Returns:(dict): A dictionary containing the mixed image and adjusted labels.Examples:>>> cutter = CutMix(dataset)>>> mixed_labels = cutter._mix_transform(labels)"""# Get a random second image# 獲取圖像的高度 h 和寬度 w 。h, w = labels["img"].shape[:2]# 使用列表推導式,調用 self._rand_bbox(w, h) 生成 self.num_areas 個CutMix區域。 將這些區域存儲在 cut_areas 數組中,數據類型為 np.float32 。cut_areas = np.asarray([self._rand_bbox(w, h) for _ in range(self.num_areas)], dtype=np.float32)# 使用 bbox_ioa 函數計算每個CutMix區域與目標邊界框的交并比(IOA)。 ioa1 的形狀為 (self.num_areas, num_boxes) ,表示每個CutMix區域與每個目標邊界框的交并比。ioa1 = bbox_ioa(cut_areas, labels["instances"].bboxes)  # (self.num_areas, num_boxes)# 使用 np.nonzero 選擇那些與目標邊界框不重疊的CutMix區域(即交并比之和為0的區域)。idx = np.nonzero(ioa1.sum(axis=1) <= 0)[0]# 如果沒有找到這樣的區域,則直接返回原始的 labels 。if len(idx) == 0:return labels# 從 labels 中獲取混合圖像及其標簽,存儲在 labels2 中。 使用 pop 方法移除 labels["mix_labels"] ,避免后續處理中出現不必要的數據。labels2 = labels.pop("mix_labels")[0]# 從不與目標邊界框重疊的區域中隨機選擇一個CutMix區域。area = cut_areas[np.random.choice(idx)]  # randomly select one# 使用 bbox_ioa 函數計算選定的CutMix區域與混合圖像的邊界框的交并比。 area[None] 將 area 擴展為一個二維數組,以便與 labels2["instances"].bboxes 進行計算。 使用 squeeze(0) 將結果壓縮為一維數組。ioa2 = bbox_ioa(area[None], labels2["instances"].bboxes).squeeze(0)# 選擇那些與CutMix區域有足夠重疊的實例(交并比大于等于0.01或0.1)。indexes2 = np.nonzero(ioa2 >= (0.01 if len(labels["instances"].segments) else 0.1))[0]# 如果沒有找到這樣的實例,則直接返回原始的 labels 。if len(indexes2) == 0:return labels# 提取混合圖像中與CutMix區域有足夠重疊的實例。instances2 = labels2["instances"][indexes2]# 將實例的邊界框轉換為 xyxy 格式,并反歸一化到原始圖像尺寸。instances2.convert_bbox("xyxy")instances2.denormalize(w, h)# Apply CutMix# 將混合圖像的CutMix區域替換到目標圖像的相應區域。# 使用 astype(np.int32) 將邊界框坐標轉換為整數。x1, y1, x2, y2 = area.astype(np.int32)labels["img"][y1:y2, x1:x2] = labels2["img"][y1:y2, x1:x2]# Restrain instances2 to the random bounding border# 調整混合實例的邊界框,使其適應CutMix區域。# 使用 add_padding 方法將實例的邊界框平移到CutMix區域的局部坐標系。# 使用 clip 方法將實例的邊界框裁剪到CutMix區域的范圍內。# 再次使用 add_padding 方法將實例的邊界框平移到目標圖像的全局坐標系。instances2.add_padding(-x1, -y1)instances2.clip(x2 - x1, y2 - y1)instances2.add_padding(x1, y1)# 更新目標標簽,將混合實例的類別和實例信息添加到目標標簽中。# 使用 np.concatenate 將類別ID合并。# 使用 Instances.concatenate 將實例信息合并。labels["cls"] = np.concatenate([labels["cls"], labels2["cls"][indexes2]], axis=0)labels["instances"] = Instances.concatenate([labels["instances"], instances2], axis=0)# 返回更新后的 labels 。return labels# 這段代碼定義了 CutMix 類中的 _mix_transform 方法,用于實現CutMix混合變換邏輯。CutMix通過將一張圖像的某個區域替換為另一張圖像的相應區域,來生成新的訓練樣本。該方法的主要步驟包括: 生成多個CutMix區域。 選擇與目標邊界框不重疊的CutMix區域。 選擇與混合邊界框有足夠重疊的實例。 將混合圖像的CutMix區域替換到目標圖像的相應區域。 調整混合實例的邊界框,使其適應CutMix區域。 更新目標標簽,將混合實例的類別和實例信息添加到目標標簽中。這種設計使得 CutMix 類可以方便地實現CutMix數據增強技術,適用于各種計算機視覺任務,有助于提高模型的泛化能力。
# 這段代碼定義了一個名為 CutMix 的類,用于實現CutMix數據增強技術。CutMix通過將一張圖像的某個區域替換為另一張圖像的相應區域,來生成新的訓練樣本。該類的主要步驟包括: 生成隨機的CutMix區域。 選擇與目標邊界框不重疊的CutMix區域。 選擇與混合邊界框有足夠重疊的實例。 將混合圖像的CutMix區域替換到目標圖像的相應區域。 更新目標標簽,將混合實例的類別和實例信息添加到目標標簽中。這種設計使得 CutMix 類可以方便地實現CutMix數據增強技術,適用于各種計算機視覺任務。

6.class CopyPaste(BaseMixTransform):?

# 這段代碼定義了一個名為 CopyPaste 的類,它繼承自 BaseMixTransform ,用于實現Copy-Paste數據增強技術。Copy-Paste通過將一張圖像中的某些實例復制到另一張圖像中,來生成新的訓練樣本。
# 定義了一個名為 CopyPaste 的類,繼承自 BaseMixTransform 。
class CopyPaste(BaseMixTransform):# 用于將復制粘貼增強應用于圖像數據集的 CopyPaste 類。# 該類實現了論文“簡單的復制粘貼是一種強大的實例分割數據增強方法”(https://arxiv.org/abs/2012.07177) 中描述的復制粘貼增強技術。它將來自不同圖像的對象組合起來以創建新的訓練樣本。# 方法:# _mix_transform:將復制粘貼增強應用于輸入標簽。# __call__:將復制粘貼轉換應用于圖像和注釋。"""CopyPaste class for applying Copy-Paste augmentation to image datasets.This class implements the Copy-Paste augmentation technique as described in the paper "Simple Copy-Paste is a StrongData Augmentation Method for Instance Segmentation" (https://arxiv.org/abs/2012.07177). It combines objects fromdifferent images to create new training samples.Attributes:dataset (Any): The dataset to which Copy-Paste augmentation will be applied.pre_transform (Callable | None): Optional transform to apply before Copy-Paste.p (float): Probability of applying Copy-Paste augmentation.Methods:_mix_transform: Apply Copy-Paste augmentation to the input labels.__call__: Apply the Copy-Paste transformation to images and annotations.Examples:>>> from ultralytics.data.augment import CopyPaste>>> dataset = YourDataset(...)  # Your image dataset>>> copypaste = CopyPaste(dataset, p=0.5)>>> augmented_labels = copypaste(original_labels)"""# 定義了 CopyPaste 類的初始化方法 __init__ ,接收以下參數:# 1.dataset :數據集對象,用于獲取圖像及其標簽。# 2.pre_transform :可選的預變換操作,用于在混合之前對圖像進行預處理。# 3.p :混合變換的概率,默認為0.5。# 4.mode :Copy-Paste的模式,可以是 "flip" 或 "mixup" 。def __init__(self, dataset=None, pre_transform=None, p=0.5, mode="flip") -> None:# 使用數據集、pre_transform 和應用 MixUp 的概率初始化 CopyPaste 對象。"""Initialize CopyPaste object with dataset, pre_transform, and probability of applying MixUp."""# 調用父類 BaseMixTransform 的初始化方法,初始化 dataset 、 pre_transform 和 p 。super().__init__(dataset=dataset, pre_transform=pre_transform, p=p)# 使用 assert 語句檢查 mode 是否為 "flip" 或 "mixup" ,如果不是則拋出異常。assert mode in {"flip", "mixup"}, f"Expected `mode` to be `flip` or `mixup`, but got {mode}."    # 預期“模式”為“翻轉”或“混合”,但得到的是{mode}。# 初始化 self.mode 。self.mode = mode# 定義了 _mix_transform 方法,用于實現Copy-Paste混合變換邏輯。def _mix_transform(self, labels):# 應用復制粘貼增強功能將另一幅圖像中的對象組合到當前圖像中。"""Apply Copy-Paste augmentation to combine objects from another image into the current image."""# 從 labels 中獲取混合圖像及其標簽,存儲在 labels2 中。labels2 = labels["mix_labels"][0]# 調用 self._transform(labels, labels2) 方法,執行具體的Copy-Paste變換邏輯。return self._transform(labels, labels2)# 這段代碼定義了 CopyPaste 類的 __call__ 方法,使得類的實例可以像函數一樣被調用。這個方法實現了Copy-Paste數據增強技術的主邏輯,根據指定的模式( mode )選擇不同的處理方式。# 定義了 CopyPaste 類的 __call__ 方法,使得類的實例可以像函數一樣被調用。 參數 1.labels 是一個包含圖像及其標簽的數據結構,通常是一個字典。def __call__(self, labels):# 對圖像及其標簽應用復制粘貼增強功能。"""Apply Copy-Paste augmentation to an image and its labels."""# 如果目標圖像中沒有實例( labels["instances"].segments 為空)或者混合變換的概率 self.p 為0,則直接返回原始的 labels ,不進行任何處理。if len(labels["instances"].segments) == 0 or self.p == 0:return labels# 如果 self.mode 為 "flip" ,則調用 self._transform(labels) 方法,直接對目標圖像進行Copy-Paste變換。 這種模式下,混合圖像使用目標圖像的水平翻轉版本。if self.mode == "flip":return self._transform(labels)# Get index of one or three other images# 調用 self.get_indexes() 方法獲取一個或多個其他圖像的索引。indexes = self.get_indexes()# 如果返回的 indexes 是一個整數,則將其轉換為一個包含該整數的列表,以統一處理。if isinstance(indexes, int):indexes = [indexes]# Get images information will be used for Mosaic or MixUp# 使用列表推導式,通過 self.dataset.get_image_and_label(i) 方法獲取每個索引對應的圖像及其標簽,存儲在 mix_labels 列表中。mix_labels = [self.dataset.get_image_and_label(i) for i in indexes]# 如果 self.pre_transform 不為 None ,則對 mix_labels 中的每個圖像及其標簽應用預變換操作。預變換操作可以在混合之前對圖像進行一些處理,如歸一化、裁剪等。if self.pre_transform is not None:for i, data in enumerate(mix_labels):mix_labels[i] = self.pre_transform(data)# 將 mix_labels 添加到 labels 字典中,鍵為 "mix_labels" 。 這樣可以在后續的混合變換操作中訪問這些混合標簽。labels["mix_labels"] = mix_labels# Update cls and texts# 調用 self._update_label_text(labels) 方法,更新 labels 中的類別和文本標簽。 這個方法通常會處理類別ID和文本標簽的映射,確保混合后的標簽一致。labels = self._update_label_text(labels)# Mosaic or MixUp# 調用 self._mix_transform(labels) 方法,執行具體的混合變換操作。 在 CopyPaste 類中, _mix_transform 方法會調用 _transform 方法來完成Copy-Paste變換。labels = self._mix_transform(labels)# 從 labels 字典中移除 "mix_labels" 鍵,避免后續處理中出現不必要的數據。 使用 pop 方法時,如果鍵不存在,不會拋出異常,而是返回 None 。labels.pop("mix_labels", None)# 返回更新后的 labels ,包含新的圖像及其標簽。return labels# 這段代碼定義了 CopyPaste 類的 __call__ 方法,實現了Copy-Paste數據增強技術的主邏輯。具體步驟包括: 檢查是否跳過處理,如果目標圖像中沒有實例或混合變換的概率為0,則直接返回原始的 labels 。 根據 mode 參數選擇不同的處理方式: 如果 mode 為 "flip" ,則直接對目標圖像進行Copy-Paste變換。 如果 mode 為 "mixup" ,則從數據集中獲取其他圖像及其標簽,進行混合變換。 獲取其他圖像的索引,并獲取這些圖像及其標簽。 對這些圖像及其標簽應用預變換操作(如果提供了預變換操作)。 將混合標簽添加到原始標簽中,并更新類別和文本標簽。 執行混合變換操作,將選擇的實例從混合圖像復制到目標圖像中。 移除混合標簽,返回更新后的標簽。這種設計使得 CopyPaste 類可以靈活地實現Copy-Paste數據增強技術,適用于各種計算機視覺任務,有助于提高模型的泛化能力。# 這段代碼定義了 CopyPaste 類中的 _transform 方法,用于實現Copy-Paste數據增強技術的核心邏輯。Copy-Paste通過將一張圖像中的某些實例復制到另一張圖像中,來生成新的訓練樣本。# 定義了 _transform 方法,用于實現Copy-Paste變換邏輯。 參數 1.labels1 是目標圖像及其標簽, 2.labels2 是混合圖像及其標簽(默認為空字典)。def _transform(self, labels1, labels2={}):# 應用復制粘貼增強功能將另一幅圖像中的對象組合到當前圖像中。"""Apply Copy-Paste augmentation to combine objects from another image into the current image."""# 從 labels1 字典中提取目標圖像 im 。 im 是一個NumPy數組,表示圖像的像素數據。im = labels1["img"]# 從 labels1 字典中提取類別信息 cls 。 cls 是一個NumPy數組,表示每個實例的類別ID。cls = labels1["cls"]# 獲取目標圖像的高度 h 和寬度 w 。 im.shape[:2] 返回圖像的前兩個維度,即高度和寬度。h, w = im.shape[:2]# 從 labels1 字典中提取實例信息 instances 。 使用 pop 方法移除 labels1["instances"] ,避免后續處理中出現不必要的數據。 instances 是一個包含實例信息的對象,通常包含邊界框、分割掩碼等。instances = labels1.pop("instances")# 調用 instances.convert_bbox 方法,將邊界框的格式轉換為 xyxy 格式。 xyxy 格式表示邊界框的左上角坐標 (x1, y1) 和右下角坐標 (x2, y2) 。instances.convert_bbox(format="xyxy")# 調用 instances.denormalize 方法,將邊界框的坐標從歸一化坐標轉換為絕對坐標。 w 和 h 分別是圖像的寬度和高度,用于將歸一化坐標轉換為像素坐標。instances.denormalize(w, h)# 創建一個新的圖像 im_new ,其形狀與目標圖像 im 相同,但所有像素值為0。 使用 np.uint8 數據類型,確保圖像數據的類型一致。im_new = np.zeros(im.shape, np.uint8)# 從 labels2 字典中提取混合圖像的實例信息 instances2 。 使用 pop 方法移除 labels2["instances"] ,避免后續處理中出現不必要的數據。 如果 labels2 中沒有 "instances" 鍵,則 instances2 為 None 。instances2 = labels2.pop("instances", None)# 如果 instances2 為空,則創建一個目標實例 instances 的副本,并將其水平翻轉。if instances2 is None:# 使用 deepcopy 確保創建的是一個獨立的副本,避免修改原始實例。instances2 = deepcopy(instances)# 調用 instances2.fliplr(w) 方法,將實例的邊界框和分割掩碼水平翻轉。instances2.fliplr(w)# 使用 bbox_ioa 函數計算混合實例 instances2 與目標實例 instances 的交并比(IOA)。 ioa 的形狀為 (N, M) ,表示每個混合實例與每個目標實例的交并比。ioa = bbox_ioa(instances2.bboxes, instances.bboxes)  # intersection over area, (N, M)# 使用 np.nonzero 選擇那些與目標實例不重疊(交并比小于0.30)的混合實例。 (ioa < 0.30).all(1) 確保每個混合實例與所有目標實例的交并比都小于0.30。 np.nonzero 返回滿足條件的實例索引。indexes = np.nonzero((ioa < 0.30).all(1))[0]  # (N, )# 獲取選擇的實例數量 n 。n = len(indexes)# 對選擇的實例進行排序,確保交并比最小的實例優先。# ioa.max(1) 計算每個混合實例與目標實例的最大交并比。# np.argsort 返回排序后的索引。# 使用排序后的索引重新排列 indexes   。sorted_idx = np.argsort(ioa.max(1)[indexes])indexes = indexes[sorted_idx]# 遍歷選擇的實例索引 indexes ,但只處理前 round(self.p * n) 個實例。 self.p 是復制實例的概率, n 是選擇的實例數量。 round(self.p * n) 確保根據概率 self.p 選擇一定數量的實例。for j in indexes[: round(self.p * n)]:# 將選擇的實例 j 的類別信息添加到目標圖像的類別信息 cls 中。# labels2.get("cls", cls) 從 labels2 中獲取類別信息,如果 labels2 中沒有 "cls" 鍵,則使用目標圖像的類別信息 cls 。# 使用 [[j]] 獲取第 j 個實例的類別信息,并使用 np.concatenate 將其添加到 cls 中。cls = np.concatenate((cls, labels2.get("cls", cls)[[j]]), axis=0)# 將選擇的實例 j 的實例信息添加到目標圖像的實例信息 instances 中。 instances2[[j]] 獲取第 j 個實例的信息。 使用 Instances.concatenate 將實例信息合并。instances = Instances.concatenate((instances, instances2[[j]]), axis=0)# 使用 cv2.drawContours 將選擇的實例 j 的分割掩碼繪制到 im_new 中。# instances2.segments[[j]] 獲取第 j 個實例的分割掩碼。# 使用 astype(np.int32) 將分割掩碼轉換為整數類型,因為 cv2.drawContours 需要整數類型的輪廓。# (1, 1, 1) 是繪制的顏色,這里使用白色。# cv2.FILLED 表示填充輪廓。cv2.drawContours(im_new, instances2.segments[[j]].astype(np.int32), -1, (1, 1, 1), cv2.FILLED)# 從 labels2 字典中獲取混合圖像 labels2["img"] 。 如果 labels2 中沒有 "img" 鍵,則使用目標圖像 im 的水平翻轉版本 cv2.flip(im, 1) 。 這一步是為了提供更多的數據增強選項,例如通過翻轉圖像來增加多樣性。result = labels2.get("img", cv2.flip(im, 1))  # augment segments# 檢查 result 的維度。如果 result 是二維的(即灰度圖像),則添加一個維度,使其成為三維數組。 這是因為 cv2.flip 操作會移除灰度圖像的最后一個維度,而后續操作需要三維數組。if result.ndim == 2:  # cv2.flip would eliminate the last dimension for grayscale imagesresult = result[..., None]# 將 im_new 轉換為布爾掩碼 i 。 im_new 是一個掩碼圖像,其中選擇的實例的區域被標記為1,其他區域為0。 使用 astype(bool) 將 im_new 轉換為布爾類型,方便后續的索引操作。i = im_new.astype(bool)# 使用布爾掩碼 i 將 result 中對應區域的像素值復制到目標圖像 im 中。 這一步實現了將混合圖像中的實例復制到目標圖像中。im[i] = result[i]# 更新目標圖像 labels1["img"] 為最終的圖像 im 。labels1["img"] = im# 更新目標圖像的類別信息 labels1["cls"] 為合并后的類別信息 cls 。labels1["cls"] = cls# 更新目標圖像的實例信息 labels1["instances"] 為合并后的實例信息 instances 。labels1["instances"] = instances# 返回更新后的 labels1 ,包含新的圖像及其標簽。return labels1# 這段代碼定義了 CopyPaste 類中的 _transform 方法,用于實現Copy-Paste數據增強技術的核心邏輯。Copy-Paste通過將一張圖像中的某些實例復制到另一張圖像中,來生成新的訓練樣本。該方法的主要步驟包括: 提取目標圖像及其實例信息。 提取混合圖像及其實例信息(如果為空,則使用目標實例的翻轉版本)。 計算混合實例與目標實例的交并比,選擇不重疊的實例。 選擇部分實例,將它們的類別和實例信息添加到目標圖像中。 使用掩碼將混合圖像的相應部分復制到目標圖像中。 更新目標圖像及其標簽。這種設計使得 CopyPaste 類可以方便地實現Copy-Paste數據增強技術,適用于各種計算機視覺任務,有助于提高模型的泛化能力。
# CopyPaste 類是一個實現Copy-Paste數據增強技術的工具,它通過將一張圖像中的某些實例復制到另一張圖像中,生成新的訓練樣本。該類繼承自 BaseMixTransform ,并根據指定的模式(如水平翻轉或混合其他圖像)選擇不同的處理方式。在實現過程中,它首先檢查目標圖像中是否有實例以及混合變換的概率,然后根據模式選擇合適的混合圖像,提取其實例信息,并將這些實例復制到目標圖像中。此外,它還更新了目標圖像的類別和實例信息,確保新的訓練樣本在類別和實例標注上保持一致。這種數據增強方法可以增加訓練數據的多樣性,有助于提高模型對不同場景和實例組合的泛化能力。

7.def v8_transforms(dataset, imgsz, hyp, stretch=False):?

# 這段代碼定義了一個名為 v8_transforms 的函數,用于創建一個綜合的數據增強流程,適用于目標檢測和關鍵點檢測任務。這個函數根據傳入的參數和配置,組合了多種數據增強技術,以提高模型的泛化能力和魯棒性。
# 定義了一個函數 v8_transforms ,接收以下參數:
# 1.dataset :數據集對象,用于獲取圖像及其標簽。
# 2.imgsz :目標圖像的尺寸。
# 3.hyp :超參數對象,包含各種數據增強的配置。
# 4.stretch :布爾值,表示是否進行拉伸變換。
def v8_transforms(dataset, imgsz, hyp, stretch=False):# 應用一系列圖像變換進行訓練。# 此函數創建一組圖像增強技術組合,用于準備用于 YOLO 訓練的圖像。它包含馬賽克、復制粘貼、隨機透視、混合以及各種顏色調整等操作。# 返回:# (Compose):要應用于數據集的圖像變換組合。"""Apply a series of image transformations for training.This function creates a composition of image augmentation techniques to prepare images for YOLO training.It includes operations such as mosaic, copy-paste, random perspective, mixup, and various color adjustments.Args:dataset (Dataset): The dataset object containing image data and annotations.imgsz (int): The target image size for resizing.hyp (Namespace): A dictionary of hyperparameters controlling various aspects of the transformations.stretch (bool): If True, applies stretching to the image. If False, uses LetterBox resizing.Returns:(Compose): A composition of image transformations to be applied to the dataset.Examples:>>> from ultralytics.data.dataset import YOLODataset>>> from ultralytics.utils import IterableSimpleNamespace>>> dataset = YOLODataset(img_path="path/to/images", imgsz=640)>>> hyp = IterableSimpleNamespace(mosaic=1.0, copy_paste=0.5, degrees=10.0, translate=0.2, scale=0.9)>>> transforms = v8_transforms(dataset, imgsz=640, hyp=hyp)>>> augmented_data = transforms(dataset[0])"""# 創建一個 Mosaic 變換對象,用于將多張圖像拼接成一張大圖像。 dataset 是數據集對象, imgsz 是目標圖像的尺寸, p 是Mosaic變換的概率。mosaic = Mosaic(dataset, imgsz=imgsz, p=hyp.mosaic)# 創建一個 RandomPerspective 變換對象,用于對圖像進行隨機透視變換。# 參數包括旋轉角度 degrees 、平移比例 translate 、縮放比例 scale 、剪切角度 shear 和透視變換比例 perspective 。# 如果 stretch 為 False ,則在透視變換前應用 LetterBox 變換,將圖像調整為目標尺寸。affine = RandomPerspective(degrees=hyp.degrees,translate=hyp.translate,scale=hyp.scale,shear=hyp.shear,perspective=hyp.perspective,pre_transform=None if stretch else LetterBox(new_shape=(imgsz, imgsz)),)# 使用 Compose 將 Mosaic 和 RandomPerspective 變換組合成一個預變換流程。pre_transform = Compose([mosaic, affine])# 檢查 hyp.copy_paste_mode 是否為 "flip" 。 hyp.copy_paste_mode 是一個超參數,決定了Copy-Paste變換的模式。if hyp.copy_paste_mode == "flip":# 如果 hyp.copy_paste_mode 為 "flip" ,則在 pre_transform 的第1個位置插入一個 CopyPaste 變換。# CopyPaste(p=hyp.copy_paste, mode=hyp.copy_paste_mode) 創建一個 CopyPaste 對象,其中 p 是Copy-Paste變換的概率, mode 是變換模式。# 使用 insert 方法將 CopyPaste 對象插入到 pre_transform 的第1個位置。pre_transform.insert(1, CopyPaste(p=hyp.copy_paste, mode=hyp.copy_paste_mode))# 如果 hyp.copy_paste_mode 不是 "flip" ,則將 CopyPaste 變換添加到 pre_transform 的末尾。# 創建一個 CopyPaste 對象,其中:# dataset 是數據集對象。# pre_transform 是一個 Compose 對象,包含 Mosaic 和 RandomPerspective 變換。# p 是Copy-Paste變換的概率。# mode 是變換模式。# 使用 append 方法將 CopyPaste 對象添加到 pre_transform 的末尾。else:pre_transform.append(CopyPaste(dataset,pre_transform=Compose([Mosaic(dataset, imgsz=imgsz, p=hyp.mosaic), affine]),p=hyp.copy_paste,mode=hyp.copy_paste_mode,))# 從數據集的配置中獲取 flip_idx ,這是一個用于關鍵點翻轉的索引數組。 如果 flip_idx 不存在,則默認為空列表 [] 。 flip_idx 用于定義在水平翻轉圖像時,關鍵點如何重新映射。flip_idx = dataset.data.get("flip_idx", [])  # for keypoints augmentation# 檢查數據集是否使用關鍵點檢測。如果使用關鍵點檢測,則需要進一步檢查 flip_idx 的配置。if dataset.use_keypoints:# 從數據集的配置中獲取 kpt_shape ,這是關鍵點的形狀信息。 如果 kpt_shape 不存在,則默認為 None 。kpt_shape = dataset.data.get("kpt_shape", None)# 如果 flip_idx 為空且 hyp.fliplr (水平翻轉的概率)大于0,則將 hyp.fliplr 設置為0。# 這是因為沒有定義 flip_idx 時,無法正確處理關鍵點的水平翻轉。# 使用 LOGGER.warning 記錄警告信息,提示用戶 flip_idx 未定義,因此禁用了水平翻轉增強。if len(flip_idx) == 0 and hyp.fliplr > 0.0:hyp.fliplr = 0.0LOGGER.warning("No 'flip_idx' array defined in data.yaml, setting augmentation 'fliplr=0.0'")    # data.yaml 中未定義“flip_idx”數組,設置增強“fliplr=0.0”。# 如果 flip_idx 不為空,但其長度與 kpt_shape[0] (關鍵點的數量)不匹配,則拋出 ValueError 。# 這是因為 flip_idx 的長度必須與關鍵點的數量一致,以確保每個關鍵點都有對應的翻轉索引。# 錯誤信息中包含了 flip_idx 和 kpt_shape[0] 的值,方便用戶調試。elif flip_idx and (len(flip_idx) != kpt_shape[0]):raise ValueError(f"data.yaml flip_idx={flip_idx} length must be equal to kpt_shape[0]={kpt_shape[0]}")    # data.yaml flip_idx={flip_idx} 長度必須等于 kpt_shape[0]={kpt_shape[0]}。# 使用 Compose 類將多個變換方法組合成一個完整的變換流程。 Compose 類允許將多個變換方法按順序應用到輸入數據上。return Compose([# 將之前定義的 pre_transform (包含 Mosaic 和 RandomPerspective 等變換)作為第一個變換方法。 pre_transform 已經包含了如Mosaic混合、隨機透視變換等操作。pre_transform,# 添加 MixUp 變換,它通過混合兩張圖像及其標簽來生成新的訓練樣本。 dataset 是數據集對象, pre_transform 是應用在混合圖像之前的變換流程, p 是MixUp變換的概率。MixUp(dataset, pre_transform=pre_transform, p=hyp.mixup),# 添加 CutMix 變換,它通過將一張圖像的某個區域替換為另一張圖像的相應區域來生成新的訓練樣本。 dataset 是數據集對象, pre_transform 是應用在混合圖像之前的變換流程, p 是CutMix變換的概率。CutMix(dataset, pre_transform=pre_transform, p=hyp.cutmix),# 添加 Albumentations 變換,這是一個強大的圖像增強庫,可以應用多種復雜的圖像變換。 p=1.0 表示這些變換總是被應用。Albumentations(p=1.0),# 添加 RandomHSV 變換,用于隨機調整圖像的色調(H)、飽和度(S)和明度(V)。 hgain 、 sgain 和 vgain 分別控制色調、飽和度和明度的調整范圍。RandomHSV(hgain=hyp.hsv_h, sgain=hyp.hsv_s, vgain=hyp.hsv_v),# 添加 RandomFlip 變換,用于隨機垂直翻轉圖像。 direction="vertical" 指定翻轉方向為垂直, p 是垂直翻轉的概率。RandomFlip(direction="vertical", p=hyp.flipud),# 添加 RandomFlip 變換,用于隨機水平翻轉圖像。 direction="horizontal" 指定翻轉方向為水平, p 是水平翻轉的概率。 flip_idx 是關鍵點翻轉索引,用于在水平翻轉時正確調整關鍵點的位置。RandomFlip(direction="horizontal", p=hyp.fliplr, flip_idx=flip_idx),]# 關閉 Compose 的括號,表示變換流程定義完成。 注釋 # transforms 說明這是一個變換流程。)  # transforms
# 這段代碼定義了一個名為 v8_transforms 的函數,用于創建一個綜合的數據增強流程。該流程結合了多種數據增強技術,如Mosaic、MixUp、CutMix、隨機透視變換、HSV調整和隨機翻轉等,以提高模型的泛化能力和魯棒性。函數根據傳入的參數和配置動態構建變換流程,適用于目標檢測和關鍵點檢測任務。

8.class ToTensor:?

# NOTE: keep this class for backward compatibility    注意:保留此類是為了向后兼容。
# 這段代碼定義了一個名為 ToTensor 的類,用于將圖像從NumPy數組轉換為PyTorch張量,并進行一些預處理操作,如改變數據類型和歸一化。
# 定義了一個名為 ToTensor 的類,用于將圖像從NumPy數組轉換為PyTorch張量。
class ToTensor:# 將圖像從 NumPy 數組轉換為 PyTorch 張量。# 此類旨在作為轉換流程的一部分,例如 T.Compose([LetterBox(size), ToTensor()])。# 方法:# __call__:將張量轉換應用于輸入圖像。# 備注:# 輸入圖像預計為 BGR 格式,形狀為 (H, W, C)。# 輸出張量將為 RGB 格式,形狀為 (C, H, W),并歸一化到 [0, 1]。"""Convert an image from a numpy array to a PyTorch tensor.This class is designed to be part of a transformation pipeline, e.g., T.Compose([LetterBox(size), ToTensor()]).Attributes:half (bool): If True, converts the image to half precision (float16).Methods:__call__: Apply the tensor conversion to an input image.Examples:>>> transform = ToTensor(half=True)>>> img = np.random.randint(0, 255, (640, 640, 3), dtype=np.uint8)>>> tensor_img = transform(img)>>> print(tensor_img.shape, tensor_img.dtype)torch.Size([3, 640, 640]) torch.float16Notes:The input image is expected to be in BGR format with shape (H, W, C).The output tensor will be in RGB format with shape (C, H, W), normalized to [0, 1]."""# 定義了類的初始化方法 __init__ ,接收一個參數 1.half ,默認值為 False 。 half 參數用于指定是否將圖像數據轉換為半精度浮點數( torch.float16 )。def __init__(self, half=False):# 初始化 ToTensor 對象,用于將圖像轉換為 PyTorch 張量。# 此類旨在用作 Ultralytics YOLO 框架中圖像預處理的轉換流程的一部分。它將 NumPy 數組或 PIL 圖像轉換為 PyTorch 張量,并可選擇進行半精度 (float16) 轉換。"""Initialize the ToTensor object for converting images to PyTorch tensors.This class is designed to be used as part of a transformation pipeline for image preprocessing in theUltralytics YOLO framework. It converts numpy arrays or PIL Images to PyTorch tensors, with an optionfor half-precision (float16) conversion.Args:half (bool): If True, converts the tensor to half precision (float16).Examples:>>> transform = ToTensor(half=True)>>> img = np.random.rand(640, 640, 3)>>> tensor_img = transform(img)>>> print(tensor_img.dtype)torch.float16"""# 調用父類的初始化方法(雖然這里沒有顯式繼承父類,但這是Python類的常規寫法)。super().__init__()# 將 half 參數賦值給類的屬性 self.half 。self.half = half# 定義了類的 __call__ 方法,使得類的實例可以像函數一樣被調用。 參數 1.im 是一個NumPy數組,表示圖像數據。def __call__(self, im):# 將圖像從 NumPy 數組轉換為 PyTorch 張量。# 此方法將輸入圖像從 NumPy 數組轉換為 PyTorch 張量,并應用可選的半精度轉換和歸一化。圖像從 HWC 格式轉置為 CHW 格式,顏色通道從 BGR 反轉為 RGB。# 參數:# im (numpy.ndarray):輸入圖像為 NumPy 數組,形狀為 (H, W, C),按 BGR 順序排列。# 返回:# (torch.Tensor):轉換后的圖像為 float32 或 float16 類型的 PyTorch 張量,歸一化到 [0, 1] 區間,形狀為 (C, H, W),按 RGB 順序排列。"""Transform an image from a numpy array to a PyTorch tensor.This method converts the input image from a numpy array to a PyTorch tensor, applying optionalhalf-precision conversion and normalization. The image is transposed from HWC to CHW format andthe color channels are reversed from BGR to RGB.Args:im (numpy.ndarray): Input image as a numpy array with shape (H, W, C) in BGR order.Returns:(torch.Tensor): The transformed image as a PyTorch tensor in float32 or float16, normalizedto [0, 1] with shape (C, H, W) in RGB order.Examples:>>> transform = ToTensor(half=True)>>> img = np.random.randint(0, 255, (640, 640, 3), dtype=np.uint8)>>> tensor_img = transform(img)>>> print(tensor_img.shape, tensor_img.dtype)torch.Size([3, 640, 640]) torch.float16"""# 使用 im.transpose((2, 0, 1)) 將圖像從HWC(高度、寬度、通道)格式轉換為CHW(通道、高度、寬度)格式。 使用 [::-1] 將BGR格式的圖像轉換為RGB格式。 使用 np.ascontiguousarray 確保數組在內存中是連續的,這對于后續的張量操作是有益的。im = np.ascontiguousarray(im.transpose((2, 0, 1))[::-1])  # HWC to CHW -> BGR to RGB -> contiguous# 使用 torch.from_numpy 將NumPy數組轉換為PyTorch張量。im = torch.from_numpy(im)  # to torch# 如果 self.half 為 True ,則將張量的數據類型轉換為半精度浮點數( torch.float16 )。 否則,將張量的數據類型轉換為單精度浮點數( torch.float32 )。im = im.half() if self.half else im.float()  # uint8 to fp16/32# 將圖像數據歸一化到0.0到1.0的范圍,通過將每個像素值除以255.0。im /= 255.0  # 0-255 to 0.0-1.0# 返回轉換后的PyTorch張量。return im
# 這段代碼定義了一個名為 ToTensor 的類,用于將圖像從NumPy數組轉換為PyTorch張量,并進行以下預處理操作: 將圖像從HWC格式轉換為CHW格式。 將BGR格式的圖像轉換為RGB格式。 確保數組在內存中是連續的。 將NumPy數組轉換為PyTorch張量。 根據 half 參數,將張量的數據類型轉換為半精度或單精度浮點數。 將圖像數據歸一化到0.0到1.0的范圍。這種設計使得 ToTensor 類可以方便地集成到數據預處理流程中,適用于各種深度學習任務,特別是在使用PyTorch框架時。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/87106.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/87106.shtml
英文地址,請注明出處:http://en.pswp.cn/web/87106.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

跨芯片 AI 算子庫 FlagGems 正式加入PyTorch 基金會生態項目體系

2025年北京智源大會 PyTorch Day China 論壇上&#xff0c;PyTorch 基金會執行董事 Matt White 宣布高性能通用 AI 算子庫 FlagGems 項目獲得批準&#xff0c;正式加入 PyTorch 生態項目體系。Pytorch基金會于6月26日在推特上進行了官方宣布。 作為唯一支持多種AI芯片架構的算…

vue + vue-router寫登陸驗證的同步方法和異步方法,及頁面組件的分離和后端代碼

先寫一個用vue cdn寫一個登陸驗證的小示例后端代碼 前端719.html <div id"app"><div id"loginForm">//路由層&#xff0c;登陸頁和后臺主頁<router-link to"/">Login</router-link><router-link to"/home&quo…

.netcore 一個mvc到靜態html實現

一、新建Mvc項目 Program.cs添加攔截 二、添加一個集成測試 將頁面轉為html到wwwroot下面 UnitGenHtml.cs using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Mvc.Testing; using Microsoft.VisualStudio.TestPlatform.TestHost;namespace SaaS.OfficialWeb…

實現Taro小程序+nut-ui左滑刪除效果

Taro小程序開發中&#xff0c;使用nut-ui組件&#xff0c;實現左滑刪除卡片效果&#xff08;自定義刪除按鈕樣式&#xff09; html代碼部分 <nut-swipe class"carBox" v-for"(item, index) in carList" :key"item" :ref"(el) > se…

LLM 系列(五):模型訓練篇

一個面向 Java 開發者的 Sring-Ai 示例工程項目&#xff0c;該項目是一個 Spring AI 快速入門的樣例工程項目&#xff0c;旨在通過一些小的案例展示 Spring AI 框架的核心功能和使用方法。 項目采用模塊化設計&#xff0c;每個模塊都專注于特定的功能領域&#xff0c;便于學習和…

Oracle LogMiner分析日志的三種方法示例

Oracle LogMiner分析日志的三種方法示例 方法一:Online Catalog作為日志挖掘字典自動獲取日志模式手動獲取日志模式方法二:Redo Log作為日志挖掘字典自動獲取日志模式手動獲取日志模式方法三:Flat File作為日志挖掘字典自動獲取日志模式手動獲取日志模式?? Oracle LogMine…

Java 中 List.stream() 的全面使用指南(含完整示例)

標簽&#xff1a;Java8, Stream API, 函數式編程, 集合操作 一、前言 隨著 Java 8 的推出&#xff0c;Stream API 成為了處理集合數據的一種高效方式。List.stream() 是 Java Stream API 的入口方法之一&#xff0c;它允許開發者將集合轉換為流&#xff0c;并通過鏈式調用實現…

香港 8C 站群服務器買來可以做哪些業務?

香港8C站群服務器&#xff08;即提供8個不同C段IP地址的服務器&#xff09;憑借多IP獨立分配、低延遲網絡及免備案優勢&#xff0c;適用于以下關鍵業務場景&#xff1a; 一、SEO優化與搜索引擎運營 SEO站群搭建&#xff1a;為 80-100 個網站分配 8 個不同 C 段 IP &#xff0…

UI前端與數字孿生融合新趨勢:智慧醫療的可視化診斷輔助

hello寶子們...我們是艾斯視覺擅長ui設計、前端開發、數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩! 一、引言&#xff1a;數字孿生重塑智慧醫療診斷范式 在醫療數字化轉型的浪潮中&#xff0c;數…

OpenBayes 一周速覽丨Nanonets-OCR-s深度語義理解,精準結構化轉換;HLE人類問題推理基準上線,含2.5k題目,助力封閉式評估體系構建

公共資源速遞 5 個公共數據集&#xff1a; * Brain Tumor 腦腫瘤數據集 * HLE 人類問題推理基準數據集 * OpenThoughts3-1.2M 推理數據集 * Nemotron-Personas 人物角色數據集 * OpenMathReasoning 數學推理數據集 14 個公共教程&#xff1a; 音頻生成 * 2 視頻生成 *…

ABB CH-3185 3 bhl 000986 p 1006 ab ability 800 xa自動化系統

安全性總結(續) 操作環境 在AC 800M控制器系統上線之前&#xff0c;調查哪些環境條件適用。請特別注意以下幾點: 控制器不得暴露在超過相關技術規范中給定值的條件下。 控制器不得在暴露于強電氣干擾的環境中使用。電機可能產生超過設備允許水平的干擾&#xff0c;例如在維…

【算法】動態規劃 斐波那契類型:1137. 第 N 個泰波那契數

1137. 第 N 個泰波那契數 簡單 相關標簽 premium lock icon 相關企業 提示 泰波那契序列 Tn 定義如下&#xff1a; T0 0, T1 1, T2 1, 且在 n > 0 的條件下 Tn3 Tn Tn1 Tn2 給你整數 n&#xff0c;請返回第 n 個泰波那契數 Tn 的值。 示例 1&#xff1a; 輸入&am…

圖像編輯新變革 !ComfyUI-Kontext-fp8本地部署教程,120B參數對標閉源巨頭

一、介紹 ComfyUI 是一個強大的、模塊化的 Stable Diffusion 界面與后端項目。該用戶界面將允許用戶使用基于圖形/節點/流程圖的界面設計和執行高級穩定的擴散管道。 關于 FLUX.1 Kontext Dev FLUX.1 Kontext 是 Black Forest Labs 最新推出的突破性多模態圖像編輯模型&#…

軟件安裝——下載安裝ollama

一、下載&#xff08;模型管理工具&#xff09;&#xff1a; 下載地址&#xff1a;Ollama 二、自定義安裝&#xff1a; 1.令行安裝方式如下&#xff1a; 在OllamaSetup.exe所在目錄打開cmd命令行&#xff0c;然后命令如下&#xff1a; OllamaSetup.exe /DIRE:\AllEdit\Ai…

springboot集成mqtt收發消息

在 Spring Boot 中使用 MQTT 可以通過集成 Eclipse Paho 或 HiveMQ 等客戶端庫實現。以下是完整的整合步驟&#xff0c;包括配置、發布和訂閱消息的示例。 1. 添加 MQTT 依賴 在 pom.xml 中添加 Paho MQTT 客戶端依賴&#xff1a; <dependency><groupId>org.spri…

Java 編程之備忘錄模式

前言 有時候&#xff0c;我們真希望人生能有“CtrlZ”。在日常生活中&#xff0c;我們經常使用“撤銷”功能&#xff0c;例如在寫 Word、畫圖、寫代碼時一不小心操作失誤&#xff0c;就希望能回到之前的狀態。這種**“狀態快照 恢復”**機制&#xff0c;在設計模式中就叫做&a…

yolov13+bytetrack的目標跟蹤實現

目錄 1. 介紹 2. 相關工作 (Related Works) 3. 方法 (Method) 4. 統計和結果 5. 技術實現 ByteTrack: Multi-Object Tracking by Associating Every Detection Box 1. Motivation 2. BYTE 3. ByteTrack 具體代碼 UI界面設計 歷史記錄 完整代碼實現UI界面 1. 介紹 …

GO類型轉換與斷言面試題及參考答案

Go 中類型轉換與類型斷言的區別是什么? 在Go語言里,類型轉換和類型斷言是兩個不同的概念,它們在應用場景、語法格式以及底層實現上都存在明顯差異。 類型轉換主要用于將一種數據類型轉變為另一種數據類型,一般適用于基本數據類型之間的轉換,像整數與浮點數、字符串與字節…

【力扣 中等 C】79. 單詞搜索

目錄 題目 解法一&#xff1a;回溯 題目 解法一&#xff1a;回溯 void swap(char* a, char* b) {char tmp *a;*a *b;*b tmp; }void reverse(char* str) {int start 0, end strlen(str) - 1;while (start < end) {swap(&str[start], &str[end--]);} }bool se…

【數據標注師】分類標注

目錄 一、 **分類標注的認知底層邏輯**1. **三大核心挑戰2. **四維評估標準** 二、 **五階成長體系**? **階段1&#xff1a;分類體系深度內化&#xff08;2-4周&#xff09;**? **階段2&#xff1a;標注決策流程固化**? **階段3&#xff1a;場景化標注策略**? **階段4&…