您的位置:首页 > 娱乐 > 明星 > 网站logo设计思路_大连旅顺网站制作_公司网站如何seo_百度极速版下载安装最新版

网站logo设计思路_大连旅顺网站制作_公司网站如何seo_百度极速版下载安装最新版

2024/12/24 22:02:35 来源:https://blog.csdn.net/m0_58169876/article/details/144159035  浏览:    关键词:网站logo设计思路_大连旅顺网站制作_公司网站如何seo_百度极速版下载安装最新版
网站logo设计思路_大连旅顺网站制作_公司网站如何seo_百度极速版下载安装最新版

metrics.py

ultralytics\utils\metrics.py

目录

metrics.py

1.所需的库和模块

2.def bbox_ioa(box1, box2, iou=False, eps=1e-7): 

3.def box_iou(box1, box2, eps=1e-7): 

4.def bbox_iou(box1, box2, xywh=True, GIoU=False, DIoU=False, CIoU=False, eps=1e-7): 

5.def mask_iou(mask1, mask2, eps=1e-7): 

6.def kpt_iou(kpt1, kpt2, area, sigma, eps=1e-7): 

7.def _get_covariance_matrix(boxes): 

8.def probiou(obb1, obb2, CIoU=False, eps=1e-7): 

9.def batch_probiou(obb1, obb2, eps=1e-7): 

10.def smooth_BCE(eps=0.1): 

11.class ConfusionMatrix: 

12.def smooth(y, f=0.05): 

13.def plot_pr_curve(px, py, ap, save_dir=Path("pr_curve.png"), names={}, on_plot=None): 

14.def plot_mc_curve(px, py, save_dir=Path("mc_curve.png"), names={}, xlabel="Confidence", ylabel="Metric", on_plot=None): 

15.def compute_ap(recall, precision): 

16.def ap_per_class(tp, conf, pred_cls, target_cls, plot=False, on_plot=None, save_dir=Path(), names={}, eps=1e-16, prefix=""):

17.class Metric(SimpleClass): 

18.class DetMetrics(SimpleClass): 

19.class SegmentMetrics(SimpleClass): 

20.class PoseMetrics(SegmentMetrics): 

21.class ClassifyMetrics(SimpleClass): 

22.class OBBMetrics(SimpleClass): 


1.所需的库和模块

# Ultralytics YOLO 🚀, AGPL-3.0 license
"""Model validation metrics."""import math
import warnings
from pathlib import Pathimport matplotlib.pyplot as plt
import numpy as np
import torchfrom ultralytics.utils import LOGGER, SimpleClass, TryExcept, plt_settings# 这段代码定义了一个名为 OKS_SIGMA 的常量,它是一个 NumPy 数组,包含了一组用于计算姿态估计中的关键点损失的 sigma 值。这些 sigma 值通常用于计算关键点的 OksSigmoid 损失(Object Keypoint Similarity),这是一种衡量预测关键点与真实关键点之间相似度的指标。
OKS_SIGMA = (# 这是一个包含16个浮点数的 NumPy 数组。这些数值代表了不同关键点的 sigma 值,它们用于调整每个关键点在损失计算中的 敏感度 。np.array([0.26, 0.25, 0.25, 0.35, 0.35, 0.79, 0.79, 0.72, 0.72, 0.62, 0.62, 1.07, 1.07, 0.87, 0.87, 0.89, 0.89])# / 10.0 这个操作将数组中的每个值除以10,对 sigma 值进行归一化。这种归一化可能是为了适应特定的数据集或模型尺度。/ 10.0
)
# OKS_SIGMA 数组中的每个值对应于人体姿态估计中一个特定关键点的 sigma 值。在姿态估计任务中,关键点通常包括头部、手腕、肩膀、肘部、膝盖等部位,每个部位的运动范围和重要性不同,因此需要不同的 sigma 值来反映这些差异。
# 在实际应用中,这些 sigma 值会被用来计算预测关键点与真实关键点之间的距离,然后通过一个类似于sigmoid函数的函数来计算损失,这样可以在关键点预测接近真实位置时减少损失,而在关键点预测偏离真实位置时增加损失。这种损失计算方式有助于模型在训练过程中更加关注关键点的精确定位。

2.def bbox_ioa(box1, box2, iou=False, eps=1e-7): 

# 这段代码是一个Python函数,用于计算两个边界框(bounding boxes)之间的交并比(Intersection over Area, IoA)。这个函数可以计算两个边界框的交集区域,并将其与第二个边界框的面积进行比较,以得到IoA值。如果设置 iou 参数为 True ,它还会计算两个边界框的并集,并返回交并比(Intersection over Union, IoU)。
# 定义了一个名为 bbox_ioa 的函数,它接受4个参数。
# 1.box1 (np.ndarray) :表示 n 个边界框的形状为 (n, 4) 的 numpy 数组。
# 2.box2 (np.ndarray) :表示 m 个边界框的形状为 (m, 4) 的 numpy 数组。
# 3.iou (bool) :如果为 True,则计算标准 IoU,否则返回 inter_area/box2_area。
# 4.eps (float,可选) :一个较小的值,以避免被零除。默认为 1e-7。
def bbox_ioa(box1, box2, iou=False, eps=1e-7):# 给定 box1 和 box2,计算 box2 区域的交集。框采用 x1y1x2y2 格式。"""Calculate the intersection over box2 area given box1 and box2. Boxes are in x1y1x2y2 format.Args:box1 (np.ndarray): A numpy array of shape (n, 4) representing n bounding boxes.box2 (np.ndarray): A numpy array of shape (m, 4) representing m bounding boxes.iou (bool): Calculate the standard IoU if True else return inter_area/box2_area.eps (float, optional): A small value to avoid division by zero. Defaults to 1e-7.Returns:(np.ndarray): A numpy array of shape (n, m) representing the intersection over box2 area."""# Get the coordinates of bounding boxes# 将 box1 的坐标分解为四个变量,分别代表边界框的 左上角 和 右下角 的x和y坐标。b1_x1, b1_y1, b1_x2, b1_y2 = box1.T# 同样地,将 box2 的坐标分解为四个变量。b2_x1, b2_y1, b2_x2, b2_y2 = box2.T# numpy.minimum(x1, x2, ..., out=None, where=True, casting='same_kind', order='K', dtype=None, subok=True[, signature, extobj])# np.minimum() 是 NumPy 库中的一个函数,它用于计算两个数组或者两个数组的每个对应元素之间的最小值。这个函数可以逐元素地比较两个数组,并返回一个新的数组,其中的每个元素都是输入数组中对应位置元素的最小值。# 参数说明 :# x1, x2, ... :一个或多个数组。 np.minimum() 可以比较两个或多个数组,或者数组与标量之间的元素。# out :一个可选的输出数组,用于存放结果。# where :一个布尔数组,用于指定在哪些位置比较元素。只有当 where 为 True 的位置,函数才会比较 x1 和 x2 的元素,否则 out 数组中对应的元素将保持不变。# casting :指定如何处理不同数据类型的输入。默认为 'same_kind' ,意味着输出数组的数据类型将与输入数组的数据类型相同或更宽松。# order :指定如何计算结果数组的内存布局。 'K' 表示保持输入数组的布局。# dtype :指定输出数组的数据类型。如果不指定,NumPy 将自动推断。# subok :布尔值,指定是否返回的数组可以是子类。# signature 和 extobj :这两个参数用于通用函数(ufunc)的进一步定制,通常不需要用户直接使用。# 返回值 :# 返回一个新的数组,包含输入数组对应元素的最小值。# numpy.maximum(x1, x2, ..., out=None, where=True, casting='same_kind', order='K', dtype=None, subok=True[, signature, extobj])# np.maximum() 是 NumPy 库中的一个函数,它用于计算两个数组或者两个数组的每个对应元素之间的最大值。这个函数可以逐元素地比较两个数组,并返回一个新的数组,其中的每个元素都是输入数组中对应位置元素的最大值。# 参数说明 :# x1, x2, ... :一个或多个数组。 np.maximum() 可以比较两个或多个数组,或者数组与标量之间的元素。# out :一个可选的输出数组,用于存放结果。# where :一个布尔数组,用于指定在哪些位置比较元素。只有当 where 为 True 的位置,函数才会比较 x1 和 x2 的元素,否则 out 数组中对应的元素将保持不变。# casting :指定如何处理不同数据类型的输入。默认为 'same_kind' ,意味着输出数组的数据类型将与输入数组的数据类型相同或更宽松。# order :指定如何计算结果数组的内存布局。 'K' 表示保持输入数组的布局。# dtype :指定输出数组的数据类型。如果不指定,NumPy 将自动推断。# subok :布尔值,指定是否返回的数组可以是子类。# signature 和 extobj :这两个参数用于通用函数(ufunc)的进一步定制,通常不需要用户直接使用。# 返回值 :# 返回一个新的数组,包含输入数组对应元素的最大值。# Intersection area# 计算两个边界框的交集区域。 np.minimum 和 np.maximum 分别找到两个边界框对应边的最小和最大坐标,以确定交集的边界。 .clip(0) 确保结果不会是负数。inter_area = (np.minimum(b1_x2[:, None], b2_x2) - np.maximum(b1_x1[:, None], b2_x1)).clip(0) * (np.minimum(b1_y2[:, None], b2_y2) - np.maximum(b1_y1[:, None], b2_y1)).clip(0)# Box2 area# 计算第二个边界框的面积。area = (b2_x2 - b2_x1) * (b2_y2 - b2_y1)# 如果 iou 参数为 True ,则计算IoU。if iou:# 计算第一个边界框的面积。box1_area = (b1_x2 - b1_x1) * (b1_y2 - b1_y1)# 计算两个边界框的并集面积。area = area + box1_area[:, None] - inter_area# Intersection over box2 area# 返回IoA或IoU值, eps 用于防止除以零。return inter_area / (area + eps)
# 请注意,这段代码假设 box1 和 box2 是NumPy数组,并且它们的转置( .T )能够正确地分解出边界框的坐标。

3.def box_iou(box1, box2, eps=1e-7): 

# 这段代码是用于计算两个边界框(bounding boxes)的交并比(Intersection over Union, IoU)的Python函数,它使用了PyTorch框架。交并比是计算机视觉中常用的一个指标,特别是在目标检测任务中,用于衡量预测的边界框与真实边界框之间的重叠程度。
# 定义了一个名为 box_iou 的函数,它接受两个边界框 box1 和 box2 ,以及一个用于数值稳定性的微小值 eps 。
# 1.box1 (torch.Tensor) :表示 N 个边界框的形状为 (N, 4) 的张量。
# 2.box2 (torch.Tensor) :表示 M 个边界框的形状为 (M, 4) 的张量。
# 3.eps (float,可选) :一个较小的值,以避免被零除。默认为 1e-7。
def box_iou(box1, box2, eps=1e-7):# 计算框的交并比 (IoU)。两组框的格式应为 (x1, y1, x2, y2)。基于 https://github.com/pytorch/vision/blob/master/torchvision/ops/boxes.py。"""Calculate intersection-over-union (IoU) of boxes. Both sets of boxes are expected to be in (x1, y1, x2, y2) format.Based on https://github.com/pytorch/vision/blob/master/torchvision/ops/boxes.py.Args:box1 (torch.Tensor): A tensor of shape (N, 4) representing N bounding boxes.box2 (torch.Tensor): A tensor of shape (M, 4) representing M bounding boxes.eps (float, optional): A small value to avoid division by zero. Defaults to 1e-7.Returns:(torch.Tensor): An NxM tensor containing the pairwise IoU values for every element in box1 and box2."""# NOTE: Need .float() to get accurate iou values    注意:需要 .float() 来获取准确的 iou 值# inter(N,M) = (rb(N,M,2) - lt(N,M,2)).clamp(0).prod(2)# 将两个边界框转换为浮点数,增加一个维度,并将其分割成两组,分别代表每个边界框的左上角 (a1, a2) 和右下角 (b1, b2) 。(a1, a2), (b1, b2) = box1.float().unsqueeze(1).chunk(2, 2), box2.float().unsqueeze(0).chunk(2, 2)# 计算两个边界框的交集区域。 torch.min 和 torch.max 分别计算两个边界框的最小和最大坐标,以确定交集的边界。 clamp_(0) 确保所有的值都是非负的, prod(2) 计算交集区域的面积。inter = (torch.min(a2, b2) - torch.max(a1, b1)).clamp_(0).prod(2)# IoU = inter / (area1 + area2 - inter)# 计算IoU值。首先计算两个边界框的面积,然后减去交集区域的面积,最后加上 eps 防止除以零。这个结果就是两个边界框的IoU值。return inter / ((a2 - a1).prod(2) + (b2 - b1).prod(2) - inter + eps)
# 这个函数可以用来比较两个边界框的重叠程度,IoU值越接近1,表示两个边界框的重叠程度越高。

4.def bbox_iou(box1, box2, xywh=True, GIoU=False, DIoU=False, CIoU=False, eps=1e-7): 

# 这段代码定义了一个名为 bbox_iou 的函数,它用于计算两个边界框(bounding boxes)之间的交并比(IoU),以及扩展的交并比变种,包括广义交并比(Generalized IoU, GIoU)、距离交并比(Distance IoU, DIoU)和完备交并比(Complete IoU, CIoU)。
# 1.box1 和 2.box2 :两个边界框,可以以 (x, y, w, h) (中心点坐标加宽高)或 (x1, y1, x2, y2) (两个对角点坐标)的形式表示。
# 3.xywh :布尔值,指示边界框的格式是否为 (x, y, w, h) 。如果为 False ,则格式为 (x1, y1, x2, y2) 。
# 4.GIoU 、 5.DIoU 、 6.CIoU :布尔值,分别指示是否计算 GIoU、DIoU 或 CIoU。
# 7.eps :一个小的常数,用于数值稳定性,防止除以零。
def bbox_iou(box1, box2, xywh=True, GIoU=False, DIoU=False, CIoU=False, eps=1e-7):# 计算 box1(1, 4) 和 box2(n, 4) 的并集交集 (IoU)。"""Calculate Intersection over Union (IoU) of box1(1, 4) to box2(n, 4).Args:box1 (torch.Tensor): A tensor representing a single bounding box with shape (1, 4).box2 (torch.Tensor): A tensor representing n bounding boxes with shape (n, 4).xywh (bool, optional): If True, input boxes are in (x, y, w, h) format. If False, input boxes are in(x1, y1, x2, y2) format. Defaults to True.GIoU (bool, optional): If True, calculate Generalized IoU. Defaults to False.DIoU (bool, optional): If True, calculate Distance IoU. Defaults to False.CIoU (bool, optional): If True, calculate Complete IoU. Defaults to False.eps (float, optional): A small value to avoid division by zero. Defaults to 1e-7.Returns:(torch.Tensor): IoU, GIoU, DIoU, or CIoU values depending on the specified flags."""# Get the coordinates of bounding boxes    获取边界框的坐标。# 边界框格式转换。如果 xywh 为 True ,则将边界框从 (x, y, w, h) 转换为 (x1, y1, x2, y2) 格式。if xywh:  # transform from xywh to xyxy(x1, y1, w1, h1), (x2, y2, w2, h2) = box1.chunk(4, -1), box2.chunk(4, -1)w1_, h1_, w2_, h2_ = w1 / 2, h1 / 2, w2 / 2, h2 / 2b1_x1, b1_x2, b1_y1, b1_y2 = x1 - w1_, x1 + w1_, y1 - h1_, y1 + h1_b2_x1, b2_x2, b2_y1, b2_y2 = x2 - w2_, x2 + w2_, y2 - h2_, y2 + h2_else:  # x1, y1, x2, y2 = box1b1_x1, b1_y1, b1_x2, b1_y2 = box1.chunk(4, -1)b2_x1, b2_y1, b2_x2, b2_y2 = box2.chunk(4, -1)w1, h1 = b1_x2 - b1_x1, b1_y2 - b1_y1 + epsw2, h2 = b2_x2 - b2_x1, b2_y2 - b2_y1 + eps# Intersection area# 算交集面积。使用 minimum 和 maximum 函数计算两个边界框的交集面积。inter = (b1_x2.minimum(b2_x2) - b1_x1.maximum(b2_x1)).clamp_(0) * (b1_y2.minimum(b2_y2) - b1_y1.maximum(b2_y1)).clamp_(0)# Union Area# 计算并集面积。计算两个边界框的并集面积,包括它们各自的面积减去交集面积。union = w1 * h1 + w2 * h2 - inter + eps# IoU# 计算 IoU。算交集面积除以并集面积,得到 IoU 值。iou = inter / union# 计算 GIoU、DIoU 和 CIoU。# 如果启用 GIoU、DIoU 或 CIoU,计算最小的外接矩形(convex box)的宽度和高度。if CIoU or DIoU or GIoU:cw = b1_x2.maximum(b2_x2) - b1_x1.minimum(b2_x1)  # convex (smallest enclosing box) widthch = b1_y2.maximum(b2_y2) - b1_y1.minimum(b2_y1)  # convex height# 对于 CIoU 和 DIoU,计算中心点距离的平方和宽高比的一致性。if CIoU or DIoU:  # Distance or Complete IoU https://arxiv.org/abs/1911.08287v1c2 = cw.pow(2) + ch.pow(2) + eps  # convex diagonal squaredrho2 = ((b2_x1 + b2_x2 - b1_x1 - b1_x2).pow(2) + (b2_y1 + b2_y2 - b1_y1 - b1_y2).pow(2)) / 4  # center dist**2# 对于 CIoU,计算一个额外的参数 alpha 并返回 CIoU 值。if CIoU:  # https://github.com/Zzh-tju/DIoU-SSD-pytorch/blob/master/utils/box/box_utils.py#L47v = (4 / math.pi**2) * ((w2 / h2).atan() - (w1 / h1).atan()).pow(2)with torch.no_grad():alpha = v / (v - iou + (1 + eps))return iou - (rho2 / c2 + v * alpha)  # CIoU# 对于 DIoU,返回 DIoU 值。return iou - rho2 / c2  # DIoUc_area = cw * ch + eps  # convex area# 对于 GIoU,计算 GIoU 值。return iou - (c_area - union) / c_area  # GIoU https://arxiv.org/pdf/1902.09630.pdfreturn iou  # IoU# 返回值。函数根据输入参数计算并返回 IoU、GIoU、DIoU 或 CIoU 的值。
# 这个函数是一个通用的边界框交并比计算工具,可以用于目标检测和图像分割任务中,以评估预测边界框与真实边界框之间的相似度。通过引入不同的交并比变种,可以更准确地衡量边界框的匹配程度,特别是在边界框不重叠或中心点距离较远的情况下。

5.def mask_iou(mask1, mask2, eps=1e-7): 

# 这段代码是用于计算两个掩码(masks)的交并比(Intersection over Union, IoU)的Python函数,它同样使用了PyTorch框架。在图像分割任务中,交并比是一个常用的指标,用于衡量预测的掩码与真实掩码之间的重叠程度。
# 定义了一个名为 mask_iou 的函数,它接受两个掩码 mask1 和 mask2 ,以及一个用于数值稳定性的微小值 eps 。
# mask1 (torch.Tensor) :形状为 (N, n) 的张量,其中 N 是真实对象的数量,n 是图像宽度和高度的乘积。
# mask2 (torch.Tensor) :形状为 (M, n) 的张量,其中 M 是预测对象的数量,n 是图像宽度和高度的乘积。
# eps (float,可选) :一个较小的值,以避免被零除。默认为 1e-7。
def mask_iou(mask1, mask2, eps=1e-7):# 计算 mask IoU。"""Calculate masks IoU.Args:mask1 (torch.Tensor): A tensor of shape (N, n) where N is the number of ground truth objects and n is theproduct of image width and height.mask2 (torch.Tensor): A tensor of shape (M, n) where M is the number of predicted objects and n is theproduct of image width and height.eps (float, optional): A small value to avoid division by zero. Defaults to 1e-7.Returns:(torch.Tensor): A tensor of shape (N, M) representing masks IoU."""# 计算两个掩码的交集。 torch.matmul 是矩阵乘法,它在这里用于计算两个掩码的点积,从而得到交集的大小。 clamp_(0) 确保所有的值都是非负的。intersection = torch.matmul(mask1, mask2.T).clamp_(0)# 计算两个掩码的并集。 mask1.sum(1) 和 mask2.sum(1) 分别计算两个掩码的面积,然后将它们相加并减去交集的大小,得到并集的大小。union = (mask1.sum(1)[:, None] + mask2.sum(1)[None]) - intersection  # (area1 + area2) - intersection# 计算IoU值。将交集的大小除以并集的大小加上 eps ,得到两个掩码的IoU值。return intersection / (union + eps)
# 这个函数可以用来比较两个掩码的重叠程度,IoU值越接近1,表示两个掩码的重叠程度越高。

6.def kpt_iou(kpt1, kpt2, area, sigma, eps=1e-7): 

# 这段代码是用于计算两个关键点集(keypoint sets)的交并比(Intersection over Union, IoU)的Python函数,它使用了PyTorch框架。在关键点检测任务中,交并比是一个常用的指标,用于衡量预测的关键点集与真实关键点集之间的重叠程度。
# 定义了一个名为 kpt_iou 的函数,它接受两个关键点集 kpt1 和 kpt2 ,区域面积 area ,方差 sigma ,以及一个用于数值稳定性的微小值 eps 。
# 1.kpt1 (torch.Tensor) :表示地面实况关键点的形状为 (N, 17, 3) 的张量。
# 2.kpt2 (torch.Tensor) :表示预测关键点的形状为 (M, 17, 3) 的张量。
# 3.area (torch.Tensor) :表示地面实况区域的形状为 (N,) 的张量。
# 4.sigma (列表) :包含 17 个表示关键点尺度的值的列表。
# 5.eps (浮点数,可选) :一个较小的值,以避免被零除。默认为 1e-7。
def kpt_iou(kpt1, kpt2, area, sigma, eps=1e-7):# 计算对象关键点相似度 (OKS)。"""Calculate Object Keypoint Similarity (OKS).Args:kpt1 (torch.Tensor): A tensor of shape (N, 17, 3) representing ground truth keypoints.kpt2 (torch.Tensor): A tensor of shape (M, 17, 3) representing predicted keypoints.area (torch.Tensor): A tensor of shape (N,) representing areas from ground truth.sigma (list): A list containing 17 values representing keypoint scales.eps (float, optional): A small value to avoid division by zero. Defaults to 1e-7.Returns:(torch.Tensor): A tensor of shape (N, M) representing keypoint similarities."""# 计算两个关键点集之间的欧氏距离的平方。d = (kpt1[:, None, :, 0] - kpt2[..., 0]).pow(2) + (kpt1[:, None, :, 1] - kpt2[..., 1]).pow(2)  # (N, M, 17)# 将方差 sigma 转换为与 kpt1 相同设备和数据类型的张量。sigma = torch.tensor(sigma, device=kpt1.device, dtype=kpt1.dtype)  # (17, )# 创建一个掩码,用于标记 kpt1 中非零的关键点。kpt_mask = kpt1[..., 2] != 0  # (N, 17)# 计算 关键点之间 的 距离 与 方差 和 区域面积 的比值,这个公式来源于COCO评估标准。e = d / ((2 * sigma).pow(2) * (area[:, None, None] + eps) * 2)  # from cocoeval# e = d / ((area[None, :, None] + eps) * sigma) ** 2 / 2  # from formula# 计算IoU值。首先计算指数函数 (-e).exp() ,然后乘以 关键点掩码 ,对最后一个维度求和,最后除以 关键点掩码的和 加上 eps 。return ((-e).exp() * kpt_mask[:, None]).sum(-1) / (kpt_mask.sum(-1)[:, None] + eps)
# 这个函数可以用来比较两个关键点集的重叠程度,IoU值越接近1,表示两个关键点集的重叠程度越高。

7.def _get_covariance_matrix(boxes): 

# 这段代码定义了一个名为 _get_covariance_matrix 的函数,它用于计算高斯边界框(Gaussian bounding boxes)的协方差矩阵元素。这个函数可能是用于旋转边界框的 IoU 计算的一部分。
# 1.boxes :边界框,形状为 (b, n_max_boxes, 5) 或其他形状,其中包含中心点坐标、宽度、高度和旋转角度。
def _get_covariance_matrix(boxes):# 从 obbs 生成协方差矩阵。"""Generating covariance matrix from obbs.Args:boxes (torch.Tensor): A tensor of shape (N, 5) representing rotated bounding boxes, with xywhr format.Returns:(torch.Tensor): Covariance matrices corresponding to original rotated bounding boxes."""# Gaussian bounding boxes, ignore the center points (the first two columns) because they are not needed here.    高斯边界框,忽略中心点(前两列),因为这里不需要它们。# 提取宽度、高度和旋转角度。从 boxes 中提取宽度和高度,将它们平方后除以 12(可能是为了将宽度和高度转换为高斯分布的标准差),然后与旋转角度( c )连接。gbbs = torch.cat((boxes[:, 2:4].pow(2) / 12, boxes[:, 4:]), dim=-1)# 分割宽度、高度和旋转角度。将连接后的张量分割成三个部分,分别对应宽度的平方除以 12、高度的平方除以 12 和旋转角度。a, b, c = gbbs.split(1, dim=-1)# 计算余弦和正弦。计算旋转角度的余弦和正弦值。cos = c.cos()sin = c.sin()# 计算协方差矩阵元素。计算余弦和正弦的平方。cos2 = cos.pow(2)sin2 = sin.pow(2)# a * cos2 + b * sin2 :计算协方差矩阵的第一个元素。# a * sin2 + b * cos2 :计算协方差矩阵的第二个元素。# (a - b) * cos * sin :计算协方差矩阵的第三个元素,这是交叉项。# 返回值。函数返回三个元素,分别对应协方差矩阵的三个元素: a * cos2 + b * sin2 、 a * sin2 + b * cos2 和 (a - b) * cos * sin 。return a * cos2 + b * sin2, a * sin2 + b * cos2, (a - b) * cos * sin
# 这三个元素可以用于计算旋转边界框的 IoU 或 CIoU,它们考虑了边界框的形状和方向。协方差矩阵在这里用于描述边界框的不确定性或分布,这在处理旋转边界框时特别有用。通过这种方式,可以更准确地捕捉边界框之间的重叠关系。

8.def probiou(obb1, obb2, CIoU=False, eps=1e-7): 

# 这段代码定义了一个名为 probiou 的函数,它用于计算两个旋转边界框(obb1 和 obb2)之间的交并比(IoU)。这个函数还提供了一个选项来计算完备交并比(Complete IoU, CIoU)。
# 1.obb1 和 2.obb2 :两个旋转边界框,形状为 (b, n_max_boxes, 5) 或 (b, h*w, 5) ,其中 5 表示边界框的格式为 (x, y, w, h, r) ,即中心点坐标加宽高和旋转角度。
# 3.CIoU :布尔值,指示是否计算完备交并比(CIoU)。CIoU 是一种改进的 IoU 计算方法,它考虑了边界框的宽高比和中心点距离。
# 4.eps :一个小的常数,用于数值稳定性,防止除以零。
def probiou(obb1, obb2, CIoU=False, eps=1e-7):# 计算旋转边界框之间的概率 IoU。"""Calculate probabilistic IoU between oriented bounding boxes.Implements the algorithm from https://arxiv.org/pdf/2106.06072v1.pdf.Args:obb1 (torch.Tensor): Ground truth OBBs, shape (N, 5), format xywhr.obb2 (torch.Tensor): Predicted OBBs, shape (N, 5), format xywhr.CIoU (bool, optional): If True, calculate CIoU. Defaults to False.eps (float, optional): Small value to avoid division by zero. Defaults to 1e-7.Returns:(torch.Tensor): OBB similarities, shape (N,).Note:OBB format: [center_x, center_y, width, height, rotation_angle].If CIoU is True, returns CIoU instead of IoU."""# 计算中心点坐标。# 从边界框中提取中心点坐标。x1, y1 = obb1[..., :2].split(1, dim=-1)x2, y2 = obb2[..., :2].split(1, dim=-1)# 计算协方差矩阵。# 计算两个边界框的协方差矩阵元素。# def _get_covariance_matrix(boxes):# -> 用于计算高斯边界框(Gaussian bounding boxes)的协方差矩阵元素。函数返回三个元素,分别对应协方差矩阵的三个元素: a * cos2 + b * sin2 、 a * sin2 + b * cos2 和 (a - b) * cos * sin 。# -> return a * cos2 + b * sin2, a * sin2 + b * cos2, (a - b) * cos * sina1, b1, c1 = _get_covariance_matrix(obb1)a2, b2, c2 = _get_covariance_matrix(obb2)# 计算 IoU 相关的项。# t1 、 t2 和 t3 是用于计算 IoU 的中间项,它们涉及边界框的中心点距离和协方差矩阵元素。t1 = (((a1 + a2) * (y1 - y2).pow(2) + (b1 + b2) * (x1 - x2).pow(2)) / ((a1 + a2) * (b1 + b2) - (c1 + c2).pow(2) + eps)) * 0.25t2 = (((c1 + c2) * (x2 - x1) * (y1 - y2)) / ((a1 + a2) * (b1 + b2) - (c1 + c2).pow(2) + eps)) * 0.5t3 = (((a1 + a2) * (b1 + b2) - (c1 + c2).pow(2))/ (4 * ((a1 * b1 - c1.pow(2)).clamp_(0) * (a2 * b2 - c2.pow(2)).clamp_(0)).sqrt() + eps)+ eps).log() * 0.5# 计算 IoU。# 计算 IoU 的基础项,并确保它在合理的范围内。bd = (t1 + t2 + t3).clamp(eps, 100.0)# 计算 IoU 的调和平均项。hd = (1.0 - (-bd).exp() + eps).sqrt()# 计算最终的 IoU 值。iou = 1 - hd# 计算 CIoU。# 如果 CIoU 为 True ,则计算宽高比的一致性项 v ,并使用它来调整 IoU 值。if CIoU:  # only include the wh aspect ratio partw1, h1 = obb1[..., 2:4].split(1, dim=-1)w2, h2 = obb2[..., 2:4].split(1, dim=-1)# 计算宽高比的一致性项。v = (4 / math.pi**2) * ((w2 / h2).atan() - (w1 / h1).atan()).pow(2)with torch.no_grad():# 计算一个用于调整 IoU 的系数。alpha = v / (v - iou + (1 + eps))# 返回调整后的 IoU 值,即 CIoU。return iou - v * alpha  # CIoU# 返回值。如果 CIoU 为 False ,则返回计算得到的 IoU 值。 如果 CIoU 为 True ,则返回计算得到的 CIoU 值。return iou
# 这个方法的目的是为旋转边界框目标检测任务提供一个准确的 IoU 度量,以便在训练过程中正确地评估模型性能并指导锚点分配。通过计算 IoU 或 CIoU,可以确定预测边界框与真实目标边界框之间的重叠程度,这对于目标检测模型的训练和优化至关重要。

9.def batch_probiou(obb1, obb2, eps=1e-7): 

# 这段代码定义了一个名为 batch_probiou 的函数,它用于计算两个定向边界框(Oriented Bounding Boxes,简称 OBB)之间的概率交并比(Probabilistic Intersection over Union,简称 PIoU)。这个函数接受两个参数 obb1 和 obb2 ,它们分别代表两组 OBB,以及一个可选参数 eps ,用于防止除以零的情况。
# 1.obb1 (torch.Tensor | np.ndarray) :表示真实 obbs 的形状为 (N, 5) 的张量,采用 xywhr 格式。
# 2.obb2 (torch.Tensor | np.ndarray) :表示预测 obbs 的形状为 (M, 5) 的张量,采用 xywhr 格式。
# 3.eps (float,可选) :一个较小的值,以避免被零除。默认为 1e-7。
def batch_probiou(obb1, obb2, eps=1e-7):# 计算定向边界框之间的概率 IoU,https://arxiv.org/pdf/2106.06072v1.pdf。"""Calculate the prob IoU between oriented bounding boxes, https://arxiv.org/pdf/2106.06072v1.pdf.Args:obb1 (torch.Tensor | np.ndarray): A tensor of shape (N, 5) representing ground truth obbs, with xywhr format.obb2 (torch.Tensor | np.ndarray): A tensor of shape (M, 5) representing predicted obbs, with xywhr format.eps (float, optional): A small value to avoid division by zero. Defaults to 1e-7.Returns:(torch.Tensor): A tensor of shape (N, M) representing obb similarities."""# torch.from_numpy(ndarray)# torch.from_numpy() 是 PyTorch 库中的一个函数,它用于将 NumPy 数组转换为 PyTorch 张量。这个函数非常有用,因为它允许你在 PyTorch 和 NumPy 之间无缝转换数据,这两个库在科学计算和深度学习领域都非常流行。# 参数 :# ndarray :一个 NumPy 数组,可以是任何维度的数组。# 返回值 :# 返回一个 PyTorch 张量,与输入的 NumPy 数组共享内存。# 特点 :# 内存共享 : torch.from_numpy() 创建的 PyTorch 张量与原始的 NumPy 数组共享内存。这意味着对张量的修改也会影响原始数组,反之亦然# 数据类型 : 转换后的张量将保持与原始 NumPy 数组相同的数据类型。# 设备兼容性 : 默认情况下,返回的张量会在与 NumPy 数组相同的设备上(通常是 CPU)。如果你需要将张量移动到 GPU 上,可以使用 .to() 方法。# 数据类型转换。将输入的 obb1 和 obb2 转换为 PyTorch 张量(如果它们是 NumPy 数组)。obb1 = torch.from_numpy(obb1) if isinstance(obb1, np.ndarray) else obb1obb2 = torch.from_numpy(obb2) if isinstance(obb2, np.ndarray) else obb2# 提取坐标。从 obb1 和 obb2 中提取中心点坐标 x1, y1 和 x2, y2 。x1, y1 = obb1[..., :2].split(1, dim=-1)x2, y2 = (x.squeeze(-1)[None] for x in obb2[..., :2].split(1, dim=-1))# 计算协方差矩阵。使用 _get_covariance_matrix 函数计算 obb1 和 obb2 的协方差矩阵,得到 a1, b1, c1 和 a2, b2, c2 。# def _get_covariance_matrix(boxes):# -> 用于计算高斯边界框(Gaussian bounding boxes)的协方差矩阵元素。函数返回三个元素,分别对应协方差矩阵的三个元素: a * cos2 + b * sin2 、 a * sin2 + b * cos2 和 (a - b) * cos * sin 。# -> return a * cos2 + b * sin2, a * sin2 + b * cos2, (a - b) * cos * sina1, b1, c1 = _get_covariance_matrix(obb1)a2, b2, c2 = (x.squeeze(-1)[None] for x in _get_covariance_matrix(obb2))# 计算 t1, t2, t3。# t1 是基于 OBB 的 长轴 和 短轴 以及 它们之间的距离 计算的。t1 = (((a1 + a2) * (y1 - y2).pow(2) + (b1 + b2) * (x1 - x2).pow(2)) / ((a1 + a2) * (b1 + b2) - (c1 + c2).pow(2) + eps)) * 0.25# t2 是基于 OBB 的旋转角度和它们之间的距离计算的。t2 = (((c1 + c2) * (x2 - x1) * (y1 - y2)) / ((a1 + a2) * (b1 + b2) - (c1 + c2).pow(2) + eps)) * 0.5# t3 是基于 OBB 的面积和协方差矩阵计算的。t3 = (((a1 + a2) * (b1 + b2) - (c1 + c2).pow(2))/ (4 * ((a1 * b1 - c1.pow(2)).clamp_(0) * (a2 * b2 - c2.pow(2)).clamp_(0)).sqrt() + eps)+ eps).log() * 0.5# 计算边界距离(bd)。将 t1 、 t2 和 t3 相加并应用 clamp 函数限制其值在 eps 和 100.0 之间。bd = (t1 + t2 + t3).clamp(eps, 100.0)# 计算 PIoU。使用 bd 和 eps 计算 PIoU 值,即 1 - hd ,其中 hd 是基于 bd 计算的。hd = (1.0 - (-bd).exp() + eps).sqrt()return 1 - hd
# 这个函数的输出是一个介于 0 和 1 之间的值,表示两个 OBB 之间的 PIoU。值越接近 1 表示两个 OBB 的重叠度越高。

10.def smooth_BCE(eps=0.1): 

# 这段代码定义了一个名为 smooth_BCE 的函数,它用于平滑二元交叉熵(Binary Cross-Entropy, BCE)损失函数。在机器学习中,BCE损失函数常用于二分类问题,但在某些情况下,标准的BCE损失函数在预测值接近0或1时会变得不稳定,因为对数函数在0和1处是未定义的。
# 为了解决这个问题,可以通过引入一个小的正数 eps 来平滑损失函数。这个函数返回两个值 : 1.0 - 0.5 * eps 和 0.5 * eps 。这两个值分别对应于当预测值接近1和0时,平滑后的损失函数的上下限。
# 具体来说,当预测值 p 接近1时, 1 - p 接近0,这时 log(1 - p) 会变得非常大,导致损失函数不稳定。通过将 1 - p 替换为 1 - p + 0.5 * eps ,可以避免这个问题,因为 1 - p + 0.5 * eps 总是大于0,使得对数函数有定义。
# 同样,当 p 接近0时, p 本身接近0,这时 log(p) 也会变得非常大。通过将 p 替换为 p + 0.5 * eps ,可以避免这个问题。
# 这个函数的作用是提供一个 eps 参数,使得调用者可以根据需要调整平滑的程度。 eps 的默认值是0.1,这意味着在计算损失时,预测值会被调整为 p + 0.05 和 1 - p + 0.05 。
def smooth_BCE(eps=0.1):# 计算平滑的正负二元交叉熵目标。# 此函数根据给定的 epsilon 值计算正负标签平滑 BCE 目标。有关实现详细信息,请参阅 https://github.com/ultralytics/yolov3/issues/238#issuecomment-598028441。"""Computes smoothed positive and negative Binary Cross-Entropy targets.This function calculates positive and negative label smoothing BCE targets based on a given epsilon value.For implementation details, refer to https://github.com/ultralytics/yolov3/issues/238#issuecomment-598028441.Args:eps (float, optional): The epsilon value for label smoothing. Defaults to 0.1.Returns:(tuple): A tuple containing the positive and negative label smoothing BCE targets."""return 1.0 - 0.5 * eps, 0.5 * eps
# 请注意,这个函数本身并不计算损失,它只是提供了平滑参数。实际的损失计算需要在其他地方进行,使用这些返回的平滑参数。

11.class ConfusionMatrix: 

# 这段代码定义了一个名为 ConfusionMatrix 的类,它用于在机器学习任务中,特别是在目标检测任务中,跟踪和计算 混淆矩阵 。 混淆矩阵 是一个表格,用于描述分类模型的性能,其中 行 表示 真实类别 , 列 表示 预测类别 。
class ConfusionMatrix:# 用于计算和更新对象检测和分类任务的混淆矩阵的类。"""A class for calculating and updating a confusion matrix for object detection and classification tasks.Attributes:task (str): The type of task, either 'detect' or 'classify'.matrix (np.ndarray): The confusion matrix, with dimensions depending on the task.nc (int): The number of classes.conf (float): The confidence threshold for detections.iou_thres (float): The Intersection over Union threshold."""# 以下是类初始化方法 __init__ 的参数说明 :# 1.nc :类别的数量(number of classes)。# 2.conf :置信度阈值,用于确定是否将预测视为有效。如果 conf 参数的值是 None 或 0.001 ,则默认使用 0.25 。# 3.iou_thres :交并比(Intersection over Union, IoU)阈值,用于确定预测框和真实框是否匹配。如果预测框和真实框的IoU高于这个阈值,则认为它们是匹配的。# 4.task :任务类型,这里有两个选项: "detect" 和其他分类任务。对于检测任务,混淆矩阵的大小是 (nc + 1) x (nc + 1) ,额外的一行和一列用于处理背景或无目标的情况。对于分类任务,混淆矩阵的大小是 nc x nc 。def __init__(self, nc, conf=0.25, iou_thres=0.45, task="detect"):# 初始化 YOLO 模型的属性。"""Initialize attributes for the YOLO model."""# 这行代码将传入的 task 参数赋值给类的实例变量 self.task 。self.task = task# 这行代码根据 self.task 的值来创建一个全零的NumPy数组。如果任务是检测( "detect" ),则创建一个形状为 (nc + 1, nc + 1) 的矩阵;否则,创建一个形状为 (nc, nc) 的矩阵。这个矩阵用于存储类别之间的某种关系或者用于计算。self.matrix = np.zeros((nc + 1, nc + 1)) if self.task == "detect" else np.zeros((nc, nc))# 这行代码将传入的 nc 参数赋值给类的实例变量 self.nc ,它代表类别的数量。self.nc = nc  # number of classes# 这行代码设置置信度阈值。如果传入的 conf 参数是 None 或 0.001 ,则置信度阈值被设置为0.25;否则,使用传入的 conf 值。self.conf = 0.25 if conf in {None, 0.001} else conf  # apply 0.25 if default val conf is passed# 这行代码将传入的 iou_thres 参数赋值给类的实例变量 self.iou_thres ,它代表交并比阈值。self.iou_thres = iou_thres# 这个类的构造函数主要用于设置模型的一些基本参数,这些参数在目标检测过程中会用到。# 这段代码定义了一个名为 process_cls_preds 的方法,它是用于更新分类任务的混淆矩阵(confusion matrix)。混淆矩阵是一个表格,用于描述分类模型的性能,其中行表示真实类别,列表示预测类别。# 这是 process_cls_preds 方法的定义,它接受两个参数。# self :类的实例。# 1.preds :预测的类别标签,是一个形状为 [N, min(nc,5)] 的数组,其中 N 是样本数量, nc 是类别数量, min(nc,5) 表示每个样本预测的类别数量不会超过5个。# 2.targets :真实的类别标签,是一个形状为 [N, 1] 的数组。def process_cls_preds(self, preds, targets):"""Update confusion matrix for classification task.Args:preds (Array[N, min(nc,5)]): Predicted class labels.targets (Array[N, 1]): Ground truth class labels."""# 这行代码将 preds 和 targets 两个列表(或张量)合并为单个张量,并选择第一个维度(即每个样本的第一个预测类别和真实类别)。preds, targets = torch.cat(preds)[:, 0], torch.cat(targets)# 这行代码使用 zip 函数将 预测类别 p 和 真实类别 t 配对,并转换为NumPy数组以便进行索引操作。for p, t in zip(preds.cpu().numpy(), targets.cpu().numpy()):# 这行代码遍历每一对预测和真实类别,然后在混淆矩阵 self.matrix 中对应的位置增加计数。 p 和 t 分别作为行索引和列索引。self.matrix[p][t] += 1# 这个方法的作用是,在模型完成一批样本的预测后,使用这些预测和真实标签来更新混淆矩阵,以便后续可以分析模型的性能,比如计算准确率、召回率等指标。# 这段代码是 process_batch 函数,它处理目标检测模型的检测结果与真实标签,并更新一个统计矩阵(可能是混淆矩阵)。这个函数考虑了检测结果的置信度、真实标签的存在与否,以及检测结果与真实标签之间的匹配情况。# 这行定义了一个名为  process_batch  的方法,它接受三个参数。# 1.detections (Array[N, 6] | Array[N, 7]) :检测到的边界框及其相关信息。每行应包含 (x1, y1, x2, y2, conf, class) 或包含附加元素 `angle`(如果是 obb)。# 2.gt_bboxes (Array[M, 4]| Array[N, 5]) :具有 xyxy/xyxyr 格式的地面实况边界框。# 3.gt_cls (Array[M]) :类标签。def process_batch(self, detections, gt_bboxes, gt_cls):# 更新对象检测任务的混淆矩阵。"""Update confusion matrix for object detection task.Args:detections (Array[N, 6] | Array[N, 7]): Detected bounding boxes and their associated information.Each row should contain (x1, y1, x2, y2, conf, class)or with an additional element `angle` when it's obb.gt_bboxes (Array[M, 4]| Array[N, 5]): Ground truth bounding boxes with xyxy/xyxyr format.gt_cls (Array[M]): The class labels."""# 检查 gt_cls (真实的类别标签)是否为空。if gt_cls.shape[0] == 0:  # Check if labels is empty# 如果 detections (检测到的边界框)不为空。if detections is not None:# 筛选出置信度大于某个阈值 self.conf 的检测结果。detections = detections[detections[:, 4] > self.conf]# 这行代码提取筛选后的检测结果中的类别标签,假设类别标签存储在第6列(索引为5)。detection_classes = detections[:, 5].int()# 获取这些检测结果的类别标签。for dc in detection_classes:# 对于每个检测到的类别,增加混淆矩阵中对应类别的假正例(false positives)计数。self.matrix[dc, self.nc] += 1  # false positives# 如果 gt_cls 为空,则返回。return# 如果 detections 为空。if detections is None:# 获取真实的类别标签。gt_classes = gt_cls.int()# 对于每个真实类别,增加混淆矩阵中背景的假负例(false negatives)计数。for gc in gt_classes:self.matrix[self.nc, gc] += 1  # background FN# 如果 detections 为空,则返回。return# 再次筛选出置信度大于阈值的检测结果。detections = detections[detections[:, 4] > self.conf]# 获取真实的类别标签。gt_classes = gt_cls.int()# 获取检测结果的类别标签。detection_classes = detections[:, 5].int()# 检查是否是旋转边界框(Oriented Bounding Box),即检测结果和真实边界框是否有额外的角度维度。is_obb = detections.shape[1] == 7 and gt_bboxes.shape[1] == 5  # with additional `angle` dimension# 计算检测结果和真实边界框之间的交并比(Intersection over Union, IoU)。如果是旋转边界框,则使用 batch_probiou 函数;否则使用 box_iou 函数。iou = (# def batch_probiou(obb1, obb2, eps=1e-7): -> 用于计算两个定向边界框(Oriented Bounding Boxes,简称 OBB)之间的概率交并比(Probabilistic Intersection over Union,简称 PIoU)。使用 bd 和 eps 计算 PIoU 值。 -> return 1 - hdbatch_probiou(gt_bboxes, torch.cat([detections[:, :4], detections[:, -1:]], dim=-1))if is_obb# def box_iou(box1, box2, eps=1e-7): -> 用于计算两个边界框(bounding boxes)的交并比(Intersection over Union, IoU)。计算IoU值。 -> return inter / ((a2 - a1).prod(2) + (b2 - b1).prod(2) - inter + eps)else box_iou(gt_bboxes, detections[:, :4]))# 找出IoU值大于某个阈值 self.iou_thres 的索引。x = torch.where(iou > self.iou_thres)# 如果存在这样的索引。if x[0].shape[0]:# 创建一个包含 匹配索引 和 IoU值 的数组。matches = torch.cat((torch.stack(x, 1), iou[x[0], x[1]][:, None]), 1).cpu().numpy()# 如果存在多个匹配。if x[0].shape[0] > 1:# 对匹配结果进行排序和去重。# 这行代码对 matches 数组的第三列(即IoU值)进行降序排序,并返回排序后的索引。然后使用这些索引来重新排列 matches 数组,这样IoU值最高的匹配会排在最前面。matches = matches[matches[:, 2].argsort()[::-1]]# 这行代码使用 np.unique 函数找出 matches 数组第二列(即真实边界框的索引)中的唯一值,并返回这些唯一值的索引。然后使用这些索引来重新排列 matches 数组,这样每个真实边界框的匹配只保留IoU值最高的那个。matches = matches[np.unique(matches[:, 1], return_index=True)[1]]# 再次对 matches 数组的第三列(IoU值)进行降序排序,确保在去重之后,IoU值最高的匹配仍然排在前面。matches = matches[matches[:, 2].argsort()[::-1]]# 最后,这行代码使用 np.unique 函数找出 matches 数组第一列(即检测边界框的索引)中的唯一值,并返回这些唯一值的索引。然后使用这些索引来重新排列 matches 数组,这样每个检测边界框的匹配只保留IoU值最高的那个。matches = matches[np.unique(matches[:, 0], return_index=True)[1]]# 总的来说,这段代码的目的是确保每个真实边界框和检测边界框只被匹配一次,并且是IoU值最高的那个匹配。这样做可以避免一个真实边界框被多次计数,以及一个检测边界框被多次计数,从而更准确地评估模型的性能。# 如果没有匹配,则设置匹配数组为空。else:matches = np.zeros((0, 3))# 检查是否有匹配。n = matches.shape[0] > 0# 获取匹配的索引。m0, m1, _ = matches.transpose().astype(int)# 遍历每个真实类别。for i, gc in enumerate(gt_classes):# 找出与当前真实类别匹配的检测结果。j = m0 == i# 如果存在匹配。if n and sum(j) == 1:# 增加混淆矩阵中对应类别的正确检测计数。self.matrix[detection_classes[m1[j]], gc] += 1  # correct# 如果没有匹配,则增加背景的假负例计数。else:self.matrix[self.nc, gc] += 1  # true background# 如果存在匹配。if n:# 遍历每个检测类别。for i, dc in enumerate(detection_classes):# 检查是否有匹配。if not any(m1 == i):# 如果没有匹配,则增加预测背景的假正例计数。self.matrix[dc, self.nc] += 1  # predicted background# 这个函数是目标检测评估流程中的关键部分,通过比较检测结果和真实标注来填充混淆矩阵,从而可以计算出模型的精确度、召回率和其他性能指标。# 这段代码定义了一个名为 matrix 的方法,它用于返回类的实例变量 self.matrix ,这个矩阵通常是在别的方法中更新的混淆矩阵。# 这是 matrix 方法的定义,它只接受一个参数。# 1.self :即类的实例本身。def matrix(self):# 返回混淆矩阵。"""Returns the confusion matrix."""# 这行代码直接返回存储在类实例中的 self.matrix 变量,这个变量在类的其他方法中被更新,用来记录预测类别和真实类别之间的匹配情况。return self.matrix# 这个方法提供了一个简单的接口来获取当前的混淆矩阵,可以在模型训练或评估的过程中调用,以获取混淆矩阵的当前状态。这有助于分析模型的性能,比如哪些类别容易被误分类,或者模型在哪些类别上表现较好。# 这段代码定义了一个名为 tp_fp 的方法,它用于计算和返回真阳性(True Positives, TP)和假阳性(False Positives, FP)。# 定义了一个名为 tp_fp 的方法,它不接受除了 1.self 之外的任何参数。def tp_fp(self):# 返回真阳性和假阳性。"""Returns true positives and false positives."""# 获取 self.matrix 的对角线元素,这些元素代表真阳性。在混淆矩阵中,对角线上的元素表示每个类别正确预测的数量。tp = self.matrix.diagonal()  # true positives# 计算假阳性。 self.matrix.sum(1) 计算每一行的总和,即每个类别被预测为该类别的总次数。然后从这个总和中减去真阳性的数量,得到假阳性的数量。fp = self.matrix.sum(1) - tp  # false positives# 这一行被注释掉了,它计算的是假阴性(False Negatives, FN),即实际为正但预测为负的情况。这里没有使用,因为它不是 tp_fp 方法返回值的一部分。# fn = self.matrix.sum(0) - tp  # false negatives (missed detections)# 根据 self.task 的值决定返回值。如果 self.task 是 "detect" ,则返回除了背景类之外的TP和FP(通过 [:-1] 切片实现)。如果 self.task 不是 "detect" ,则返回所有的TP和FP。return (tp[:-1], fp[:-1]) if self.task == "detect" else (tp, fp)  # remove background class if task=detect# 这个方法的目的是根据不同的任务类型(例如,目标检测或分类)来调整返回的TP和FP,以适应不同的应用场景。在目标检测任务中,通常有一个额外的背景类别,需要从计算中排除。而在其他类型的任务中,可能不需要这样做。# 这段代码是一个Python方法,名为 plot ,它属于 ConfusionMatrix 类,用于绘制混淆矩阵并将其保存为文件。这个方法使用了 seaborn 库来绘制热图,并使用  matplotlib  来设置图表的样式和保存图像。# @TryExcept("WARNING ⚠️ ConfusionMatrix plot failure") 和 @plt_settings() 是装饰器,分别用于异常处理和设置图表的样式。# class TryExcept(contextlib.ContextDecorator):# -> 名为 TryExcept 的上下文管理器类,它继承自 contextlib.ContextDecorator 。这个类用于在 with 语句块中提供异常处理功能,允许用户自定义错误消息和是否打印这些消息。# -> 这个上下文管理器类主要用于简化异常处理和错误消息的打印,特别是在需要频繁处理异常的代码中。 返回 True 表示异常已经被处理,不会向外传播。如果需要重新抛出异常,可以返回 False 或不实现 __exit__ 方法。# -> def __init__(self, msg="", verbose=True):@TryExcept("WARNING ⚠️ ConfusionMatrix plot failure")    # 警告⚠️ConfusionMatrix 绘图失败。# def plt_settings(rcparams=None, backend="Agg"): -> 定义了一个名为 plt_settings 的装饰器,它用于在函数执行期间临时应用 matplotlib 的配置参数(rc参数)和后端设置,并在函数执行完毕后恢复原来的设置。这个装饰器可以在任何需要临时改变 matplotlib 设置的函数上使用。@plt_settings()# 定义了 plot 方法,它接受以下参数。# 1.self :类的实例。# 2.normalize (默认为 True ) :是否要规范化混淆矩阵。# 3.save_dir (默认为空字符串) :保存图表的目录。# 4.names (默认为空元组) :类别的名称,用于图表上的标签。# 5.on_plot (默认为 None ) :一个可选的回调函数,用于在图表渲染后传递图表路径和数据。def plot(self, normalize=True, save_dir="", names=(), on_plot=None):# 使用 seaborn 绘制混淆矩阵并将其保存到文件中。"""Plot the confusion matrix using seaborn and save it to a file.Args:normalize (bool): Whether to normalize the confusion matrix.save_dir (str): Directory where the plot will be saved.names (tuple): Names of classes, used as labels on the plot.on_plot (func): An optional callback to pass plots path and data when they are rendered."""# 导入 seaborn 库,用于绘制热图。import seaborn  # scope for faster 'import ultralytics'# 计算规范化后的混淆矩阵。如果 normalize 为 True ,则除以 每列的和 (加上一个非常小的数以避免除以零)。array = self.matrix / ((self.matrix.sum(0).reshape(1, -1) + 1e-9) if normalize else 1)  # normalize columns# 将小于0.005的值设置为 np.nan ,这样在注释中就不会显示这些值。array[array < 0.005] = np.nan  # don't annotate (would appear as 0.00)# 创建一个图表和一个轴。fig, ax = plt.subplots(1, 1, figsize=(12, 9), tight_layout=True)# 获取 类别的数量 和 名称的数量 。nc, nn = self.nc, len(names)  # number of classes, names# 根据类别的数量设置字体大小。seaborn.set_theme(font_scale=1.0 if nc < 50 else 0.8)  # for label size# 确定是否将名称应用于刻度标签。labels = (0 < nn < 99) and (nn == nc)  # apply names to ticklabels# 设置刻度标签。ticklabels = (list(names) + ["background"]) if labels else "auto"# warnings.catch_warnings()# warnings.catch_warnings 是 Python 的 warnings 模块中的一个上下文管理器,它允许你在代码的特定块中捕获和控制警告信息。使用 warnings.catch_warnings ,你可以临时修改警告过滤器,捕获发出的警告,并在代码块执行完毕后恢复原来的警告状态。# 参数 :# record :默认为 None ,如果设置为 True ,则捕获的警告将被记录在列表中,而不是被抛出。# module :默认为 None ,如果指定模块,则只考虑来自该模块的警告。# category :默认为 Warning ,指定要捕获的警告类别。# message :默认为 None ,如果指定字符串,则只捕获包含该字符串的消息的警告。# rethrow :默认为 False ,如果设置为 True ,则在上下文管理器退出时重新抛出捕获的警告。# warnings.catch_warnings 本身不接受任何参数,但你可以在其上下文管理器中通过调用 warnings.simplefilter 或 warnings.filterwarnings 来设置警告的过滤规则。# 返回值 :# warnings.catch_warnings 返回一个上下文管理器对象,你可以用它来捕获和控制警告。# 用法示例 :# with warnings.catch_warnings():    # 使用 catch_warnings 作为上下文管理器# 注意事项 :# warnings.catch_warnings 通常与 warnings.simplefilter 或 warnings.filterwarnings 结合使用,以设置特定的警告过滤规则。# 在 with 块之外,警告的设置会恢复到进入 with 块之前的状态。# warnings._warnings 属性是一个私有的列表,用于存储在 with 块中捕获的警告。这个列表在 Python 3.11 版本中已被弃用,并将在未来的版本中被移除。因此,建议不要依赖这个属性来访问捕获的警告。# 捕获的警告可以通过上下文管理器的 warnings 属性来访问,这是一个更推荐的方式。# warnings.simplefilter(action, category, lineno, module)# warnings.simplefilter() 是 Python 标准库 warnings 模块中的一个函数,它用于设置警告的过滤规则。这个函数允许你控制哪些警告应该被显示,哪些应该被忽略。# 参数 :# action :一个字符串,指定对警告应该采取的操作。常用的操作包括 :# "ignore" :忽略警告。 "default" :使用默认的警告行为(显示警告)。 "always" :总是显示警告。 "module" :只有当警告的模块与当前被检查的模块相同时,才显示警告。 "once" :只显示一次警告,之后相同类型的警告将被忽略。 "error" :将警告当作错误处理。# category :警告类别,可以是 Warning 的子类,用于指定哪种类型的警告应该被 action 参数影响。# lineno :一个整数,指定警告发生的行号。这个参数通常不使用,因为警告通常与特定的代码行无关。# module :一个模块或模块名的字符串,指定警告发生的模块。这个参数通常不使用,因为警告通常与特定的模块无关。# 返回值 : warnings.simplefilter() 没有返回值。# warnings.simplefilter() 可以多次调用,以设置不同的过滤规则。这些规则将按照它们被设置的顺序应用,直到找到匹配的警告为止。如果一个警告匹配了多个规则,那么最后一个匹配的规则将决定对这个警告采取的操作。# 这个函数是控制 Python 程序中警告显示的常用工具,可以帮助开发者管理代码中的警告信息,特别是在处理第三方库产生的警告时非常有用。# 捕获并忽略警告。with warnings.catch_warnings():# 忽略空矩阵的警告。warnings.simplefilter("ignore")  # suppress empty matrix RuntimeWarning: All-NaN slice encountered# 使用 seaborn 绘制热图。seaborn.heatmap(array,ax=ax,annot=nc < 30,annot_kws={"size": 8},cmap="Blues",fmt=".2f" if normalize else ".0f",square=True,vmin=0.0,xticklabels=ticklabels,yticklabels=ticklabels,).set_facecolor((1, 1, 1))title = "Confusion Matrix" + " Normalized" * normalize# ax.set_xlabel("True") 和 ax.set_ylabel("Predicted") 设置轴标签。ax.set_xlabel("True")ax.set_ylabel("Predicted")# 设置图表标题。ax.set_title(title)# 构造保存文件的路径。plot_fname = Path(save_dir) / f'{title.lower().replace(" ", "_")}.png'# 保存图表。fig.savefig(plot_fname, dpi=250)# 关闭图表以释放内存。plt.close(fig)# 如果提供了 on_plot 回调函数,则调用它并传递保存的文件路径。回调函数是一种以函数作为参数并在某个事件或条件触发时执行的编程技巧。在编程中,回调函数是一种常用的异步处理机制,允许程序在某个操作完成或某个事件发生时获得通知。if on_plot:on_plot(plot_fname)# 这个方法提供了一个完整的流程,从规范化混淆矩阵到绘制热图,再到保存和可选的回调函数调用。它使得混淆矩阵的可视化变得简单和自动化。# 这段代码定义了一个名为 print 的方法,它是 ConfusionMatrix 类的一个成员方法,用于将混淆矩阵打印到控制台。这个方法使用了 LOGGER 对象来记录信息, LOGGER 是一个配置好的日志记录器(logger),用于输出日志信息。# 定义了一个名为 print 的方法,它接受 1.self 作为参数, self 指的是类的实例本身。def print(self):# 将混淆矩阵打印到控制台。"""Print the confusion matrix to the console."""# 这是一个循环,它遍历从 0 到 self.nc (包括 self.nc )的索引。 self.nc 是类的一个属性,表示类别的数量。for i in range(self.nc + 1):# 在循环内部,这行代码执行以下操作 :# self.matrix[i] 获取混淆矩阵的第 i 行。# map(str, self.matrix[i]) 将该行中的每个元素转换为字符串。# " ".join(...) 将转换后的字符串元素连接成一个单一的字符串,元素之间用空格分隔。# LOGGER.info(...) 使用 LOGGER 的 info 方法将连接后的字符串记录为一条信息级别的日志,这通常意味着这条信息会被打印到控制台。LOGGER.info(" ".join(map(str, self.matrix[i])))# 这个方法的目的是将混淆矩阵的每一行作为一个字符串输出到控制台,每个元素之间用空格分隔。这种格式通常用于简单直观地查看混淆矩阵的内容。

12.def smooth(y, f=0.05): 

# 这段代码定义了一个名为 smooth 的函数,它使用盒式滤波器(Box filter)对输入的数据序列 y 进行平滑处理。这个函数的目的是减少数据中的噪声,使数据看起来更平滑。
# 定义了一个名为 smooth 的函数,它接受两个参数。
# 1.y :是要平滑的数据序列。
# 2.f (默认为 0.05 ) :是滤波器的分数,表示滤波器窗口大小相对于数据长度的比例。
def smooth(y, f=0.05):"""Box filter of fraction f."""# 计算滤波器的元素数量 nf 。这个值必须是奇数,因为盒式滤波器需要一个中心点。这里通过将数据长度乘以 f 的两倍,然后除以2并加1来确保结果为奇数。nf = round(len(y) * f * 2) // 2 + 1  # number of filter elements (must be odd)# 创建一个长度为 nf 的一半的数组,所有元素都为1。这个数组将用于在原始数据的两端进行填充。p = np.ones(nf // 2)  # ones padding# 将 填充数组 与 原始数据序列 y 进行拼接,形成一个新的数组 yp 。填充的值是原始数据的第一个和最后一个值,以保持数据的连续性。yp = np.concatenate((p * y[0], y, p * y[-1]), 0)  # y padded# numpy.convolve(in1, in2, mode='full', method='auto')# np.convolve 是 NumPy 库中的一个函数,用于对两个序列进行一维卷积。这个函数可以用于信号处理、图像处理、统计分析等多种应用中,特别是在需要分析两个信号之间的相似性或者一个信号的自身相似性时。# 参数 :# in1 :第一个输入序列,可以是一维的 NumPy 数组。# in2 :第二个输入序列,也可以是一维的 NumPy 数组,通常称为卷积核或滤波器。# mode :卷积模式,可以是以下选项之一 :# 'full' :返回完整的卷积结果,输出长度为 len(in1) + len(in2) - 1 。 'valid' :返回只有当两个输入序列完全重叠时的卷积结果,输出长度最短,可能为零。 'same' :返回卷积结果,使得输出长度与 in1 相同。# method :指定卷积的方法,可以是 'auto' 、 'direct' 或 'fft' 。 'auto' 表示 NumPy 自动选择最佳方法。# 返回值 :# 返回一个数组,表示两个输入序列的卷积结果。# np.convolve 是一个非常灵活的函数,可以根据需要选择不同的卷积模式和方法,以适应不同的应用场景。# 使用 np.convolve 函数对填充后的数据 yp 进行卷积操作,以实现平滑。卷积核是一个长度为 nf 的数组,所有元素都为1,然后除以 nf 以确保卷积核的总和为1。 mode="valid" 参数表示只返回卷积结果中完全由输入数组覆盖的部分,这样输出数组的长度将与原始数据 y 相同。return np.convolve(yp, np.ones(nf) / nf, mode="valid")  # y-smoothed
# 这个函数对于处理时间序列数据或者任何需要平滑处理的数据序列都是有用的。

13.def plot_pr_curve(px, py, ap, save_dir=Path("pr_curve.png"), names={}, on_plot=None): 

# 这段代码定义了一个名为 plot_pr_curve 的函数,它用于绘制精确度-召回率曲线(Precision-Recall Curve)。
# 是一个装饰器,用于设置绘图的环境和参数。
@plt_settings()
# 定义了 plot_pr_curve 函数,它接受以下参数 :
# 1.px :x轴数据,通常是召回率(Recall)的值。
# 2.py :y轴数据,通常是精确度(Precision)的值。
# 3.ap :平均精确度(Average Precision)的值。
# 4.save_dir (默认为 Path("pr_curve.png") ):保存图表的文件路径。
# 5.names (默认为空字典):类别的名称,用于图表上的图例。
# 6.on_plot (默认为 None ):一个可选的回调函数,用于在图表渲染后传递图表路径和数据。
def plot_pr_curve(px, py, ap, save_dir=Path("pr_curve.png"), names={}, on_plot=None):# 绘制精确度-召回率曲线。"""Plots a precision-recall curve."""# 创建 一个图表 和 一个轴 ,设置图表大小为9x6英寸,并启用紧凑布局。fig, ax = plt.subplots(1, 1, figsize=(9, 6), tight_layout=True)# 将 py 数据堆叠起来,以便进行绘图。py = np.stack(py, axis=1)# 检查类别名称的数量是否在1到20之间,如果是,则显示每个类别的图例。if 0 < len(names) < 21:  # display per-class legend if < 21 classes# 遍历每个类别的精确度-召回率曲线。for i, y in enumerate(py.T):# 绘制每个类别的曲线,并添加图例。ax.plot(px, y, linewidth=1, label=f"{names[i]} {ap[i, 0]:.3f}")  # plot(recall, precision)# 如果类别数量不满足显示图例的条件,则绘制所有类别的灰色曲线。else:ax.plot(px, py, linewidth=1, color="grey")  # plot(recall, precision)# 绘制所有类别的平均精确度-召回率曲线,并设置线宽和颜色。ax.plot(px, py.mean(1), linewidth=3, color="blue", label=f"all classes {ap[:, 0].mean():.3f} mAP@0.5")# 设置x轴和y轴的标签。ax.set_xlabel("Recall")ax.set_ylabel("Precision")# 设置x轴和y轴的显示范围。ax.set_xlim(0, 1)ax.set_ylim(0, 1)# 设置图例的位置。ax.legend(bbox_to_anchor=(1.04, 1), loc="upper left")# 设置图表的标题。ax.set_title("Precision-Recall Curve")# 保存图表到指定路径,设置分辨率为250dpi。fig.savefig(save_dir, dpi=250)# 关闭图表,释放资源。plt.close(fig)# 如果提供了 on_plot 回调函数,则调用它并传递保存的文件路径。if on_plot:on_plot(save_dir)
# 这个函数提供了一个完整的流程,从绘制精确度-召回率曲线到保存和可选的回调函数调用。它使得精确度-召回率曲线的可视化变得简单和自动化。

14.def plot_mc_curve(px, py, save_dir=Path("mc_curve.png"), names={}, xlabel="Confidence", ylabel="Metric", on_plot=None): 

# 这段代码定义了一个名为 plot_mc_curve 的函数,它用于绘制度量-置信度曲线(Metric-Confidence Curve)。
# 是一个装饰器,用于设置绘图的环境和参数。
@plt_settings()
# 定义了 plot_mc_curve 函数,它接受以下参数 :
# 1.px :x轴数据,通常是置信度(Confidence)的值。
# 2.py :y轴数据,通常是度量(Metric)的值。
# 3.save_dir (默认为 Path("mc_curve.png") ):保存图表的文件路径。
# 4.names (默认为空字典):类别的名称,用于图表上的图例。
# 5.xlabel (默认为 "Confidence" ):x轴的标签。
# 6.ylabel (默认为 "Metric" ):y轴的标签。
# 7.on_plot (默认为 None ):一个可选的回调函数,用于在图表渲染后传递图表路径和数据。
def plot_mc_curve(px, py, save_dir=Path("mc_curve.png"), names={}, xlabel="Confidence", ylabel="Metric", on_plot=None):# 绘制度量-置信度曲线。"""Plots a metric-confidence curve."""# 创建一个图表和一个轴,设置图表大小为9x6英寸,并启用紧凑布局。fig, ax = plt.subplots(1, 1, figsize=(9, 6), tight_layout=True)# 检查类别名称的数量是否在1到20之间,如果是,则显示每个类别的图例。if 0 < len(names) < 21:  # display per-class legend if < 21 classes# 遍历每个类别的度量-置信度曲线。for i, y in enumerate(py):# 绘制每个类别的曲线,并添加图例。ax.plot(px, y, linewidth=1, label=f"{names[i]}")  # plot(confidence, metric)# 如果类别数量不满足显示图例的条件,则绘制所有类别的灰色曲线。else:ax.plot(px, py.T, linewidth=1, color="grey")  # plot(confidence, metric)# 对所有类别的平均度量-置信度曲线进行平滑处理。y = smooth(py.mean(0), 0.05)# 绘制平滑后的所有类别的平均度量-置信度曲线,并设置线宽和颜色。ax.plot(px, y, linewidth=3, color="blue", label=f"all classes {y.max():.2f} at {px[y.argmax()]:.3f}")# 设置x轴和y轴的标签。ax.set_xlabel(xlabel)ax.set_ylabel(ylabel)# 设置x轴和y轴的显示范围。ax.set_xlim(0, 1)ax.set_ylim(0, 1)# 设置图例的位置。ax.legend(bbox_to_anchor=(1.04, 1), loc="upper left")# 设置图表的标题。ax.set_title(f"{ylabel}-Confidence Curve")# 保存图表到指定路径,设置分辨率为250dpi。fig.savefig(save_dir, dpi=250)# 关闭图表,释放资源。plt.close(fig)# 如果提供了 on_plot 回调函数,则调用它并传递保存的文件路径。if on_plot:on_plot(save_dir)
# 这个函数提供了一个完整的流程,从绘制度量-置信度曲线到保存和可选的回调函数调用。它使得度量-置信度曲线的可视化变得简单和自动化。

15.def compute_ap(recall, precision): 

# 这段代码定义了一个名为 compute_ap 的函数,用于计算平均精度(Average Precision, AP)。平均精度是评估分类模型性能的一个指标,特别是在目标检测和信息检索领域。
# 定义了一个名为 compute_ap 的函数,它接受两个参数。
# 1.recall :召回率数组,表示模型在不同置信度阈值下的召回率。
# 2.precision :精确度数组,表示模型在不同置信度阈值下的精确度。
def compute_ap(recall, precision):# 根据召回率和准确率曲线计算平均准确率 (AP)。"""Compute the average precision (AP) given the recall and precision curves.Args:recall (list): The recall curve.precision (list): The precision curve.Returns:(float): Average precision.(np.ndarray): Precision envelope curve.(np.ndarray): Modified recall curve with sentinel values added at the beginning and end."""# Append sentinel values to beginning and end# 将0.0和1.0作为哨兵值分别添加到 召回率数组 的开始和结束,以便于计算。mrec = np.concatenate(([0.0], recall, [1.0]))# 将1.0和0.0作为哨兵值分别添加到 精确度数组 的开始和结束,以便于计算。mpre = np.concatenate(([1.0], precision, [0.0]))# Compute the precision envelope# 计算 精确度的累积最大值 (precision envelope),这用于确定每个 召回率 水平下的最大精确度。mpre = np.flip(np.maximum.accumulate(np.flip(mpre)))# Integrate area under curve# 设置计算AP的方法,可以是 "interp" 或 "continuous" 。method = "interp"  # methods: 'continuous', 'interp'# 如果选择插值方法。if method == "interp":# 创建一个从0到1的101个点的线性空间,用于插值。x = np.linspace(0, 1, 101)  # 101-point interp (COCO)# 使用插值计算AP, np.interp 函数在 mrec 和 mpre 之间进行插值, np.trapz 函数计算梯形积分。ap = np.trapz(np.interp(x, mrec, mpre), x)  # integrate# 如果选择连续方法。else:  # 'continuous'# 找到召回率变化的点。i = np.where(mrec[1:] != mrec[:-1])[0]  # points where x-axis (recall) changes# 计算这些点下的面积,即AP。ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])  # area under curve# 返回计算的 平均精度AP ,以及用于计算的 精确度 和 召回率 数组 。return ap, mpre, mrec
# 这个函数提供了两种计算AP的方法:插值方法和连续方法。插值方法通过在召回率曲线上进行插值来计算AP,而连续方法则直接计算召回率变化点下的面积。这两种方法都可以得到AP值,但在不同的应用场景和评估标准中可能会选择不同的方法。

16.def ap_per_class(tp, conf, pred_cls, target_cls, plot=False, on_plot=None, save_dir=Path(), names={}, eps=1e-16, prefix=""):

# 这段代码定义了一个名为 ap_per_class 的函数,它用于计算每个类别的 平均精度 (AP) 并绘制相关的度量曲线。这个函数处理目标检测任务中的 真实标签(tp) 、 置信度(conf) 、 预测类别(pred_cls) 和 目标类别(target_cls) 。
# 定义了 ap_per_class 函数,它接受以下参数 :
# 1.tp :真实阳性数组,表示每个预测是否为真实阳性。
# 2.conf :置信度数组,表示每个预测的置信度。
# 3.pred_cls :预测类别数组。
# 4.target_cls :目标类别数组。
# 5.plot (默认为 False ):是否绘制度量曲线。
# 6.on_plot (默认为 None ):一个可选的回调函数,用于在图表渲染后传递图表路径和数据。
# 7.save_dir (默认为 Path() ):保存图表的目录。
# 8.names (默认为空字典):类别的名称,用于图表上的图例。
# 9.eps (默认为 1e-16 ):用于数值稳定性的小值。
# 10.prefix (默认为空字符串):保存文件名前缀。
def ap_per_class(tp, conf, pred_cls, target_cls, plot=False, on_plot=None, save_dir=Path(), names={}, eps=1e-16, prefix=""
):# 计算每个类别的平均精度以进行对象检测评估。"""Computes the average precision per class for object detection evaluation.Args:tp (np.ndarray): Binary array indicating whether the detection is correct (True) or not (False).conf (np.ndarray): Array of confidence scores of the detections.pred_cls (np.ndarray): Array of predicted classes of the detections.target_cls (np.ndarray): Array of true classes of the detections.plot (bool, optional): Whether to plot PR curves or not. Defaults to False.on_plot (func, optional): A callback to pass plots path and data when they are rendered. Defaults to None.save_dir (Path, optional): Directory to save the PR curves. Defaults to an empty path.names (dict, optional): Dict of class names to plot PR curves. Defaults to an empty tuple.eps (float, optional): A small value to avoid division by zero. Defaults to 1e-16.prefix (str, optional): A prefix string for saving the plot files. Defaults to an empty string.Returns:(tuple): A tuple of six arrays and one array of unique classes, where:tp (np.ndarray): True positive counts at threshold given by max F1 metric for each class.Shape: (nc,).fp (np.ndarray): False positive counts at threshold given by max F1 metric for each class. Shape: (nc,).p (np.ndarray): Precision values at threshold given by max F1 metric for each class. Shape: (nc,).r (np.ndarray): Recall values at threshold given by max F1 metric for each class. Shape: (nc,).f1 (np.ndarray): F1-score values at threshold given by max F1 metric for each class. Shape: (nc,).ap (np.ndarray): Average precision for each class at different IoU thresholds. Shape: (nc, 10).unique_classes (np.ndarray): An array of unique classes that have data. Shape: (nc,).p_curve (np.ndarray): Precision curves for each class. Shape: (nc, 1000).r_curve (np.ndarray): Recall curves for each class. Shape: (nc, 1000).f1_curve (np.ndarray): F1-score curves for each class. Shape: (nc, 1000).x (np.ndarray): X-axis values for the curves. Shape: (1000,).prec_values: Precision values at mAP@0.5 for each class. Shape: (nc, 1000)."""# Sort by objectness# 根据 置信度 对索引进行排序,置信度最高的排在前面。i = np.argsort(-conf)# 根据排序后的索引重新排列 tp 、 conf 和 pred_cls 。tp, conf, pred_cls = tp[i], conf[i], pred_cls[i]# Find unique classes# 找到 目标类别 及其 计数 。unique_classes, nt = np.unique(target_cls, return_counts=True)# 获取类别数量。nc = unique_classes.shape[0]  # number of classes, number of detections# Create Precision-Recall curve and compute AP for each class# 创建一个从0到1的1000个点的线性空间,用于插值。x, prec_values = np.linspace(0, 1, 1000), []# 这段代码是 ap_per_class 函数的一部分,它计算每个类别的平均精度(AP)并绘制相关的度量曲线。# Average precision, precision and recall curves# 初始化存储 每个类别的AP 、 精确度曲线 和 召回率曲线 的 数组 。 nc 是类别数量, tp.shape[1] 是不同置信度阈值的数量。ap, p_curve, r_curve = np.zeros((nc, tp.shape[1])), np.zeros((nc, 1000)), np.zeros((nc, 1000))# 遍历每个唯一的类别。for ci, c in enumerate(unique_classes):# 找到当前类别的预测。i = pred_cls == c# 分别获取当前类别的 标签数量 和 预测数量 。n_l = nt[ci]  # number of labelsn_p = i.sum()  # number of predictions# 如果当前类别没有预测或没有标签,则跳过该类别。if n_p == 0 or n_l == 0:continue# Accumulate FPs and TPs# 计算累积的假阳性和真阳性。fpc = (1 - tp[i]).cumsum(0)tpc = tp[i].cumsum(0)# Recall# 计算召回率曲线。recall = tpc / (n_l + eps)  # recall curve# 使用插值计算召回率曲线, x 是从0到1的1000个点的线性空间, conf[i] 是当前类别的置信度, recall[:, 0] 是当前类别的召回率。r_curve[ci] = np.interp(-x, -conf[i], recall[:, 0], left=0)  # negative x, xp because xp decreases# Precision# 计算精确度曲线。precision = tpc / (tpc + fpc)  # precision curve# 使用插值计算精确度曲线, left=1 表示在插值时,如果 x 小于 conf[i] 的最小值,则返回1。p_curve[ci] = np.interp(-x, -conf[i], precision[:, 0], left=1)  # p at pr_score# AP from recall-precision curve# 遍历不同的置信度阈值。for j in range(tp.shape[1]):# 计算每个类别的AP。# def compute_ap(recall, precision): -> 用于计算平均精度(Average Precision, AP)。返回计算的 平均精度AP ,以及用于计算的 精确度 和 召回率 数组 。 -> return ap, mpre, mrecap[ci, j], mpre, mrec = compute_ap(recall[:, j], precision[:, j])# 如果需要绘图且当前是第一个置信度阈值,则存储插值后的精确度值。if plot and j == 0:prec_values.append(np.interp(x, mrec, mpre))  # precision at mAP@0.5# 将插值后的精确度值转换为数组。prec_values = np.array(prec_values)  # (nc, 1000)# 这段代码提供了一个完整的流程,从计算每个类别的AP到绘制相关的度量曲线,使得模型性能的评估和可视化变得简单和自动化。# 这段代码继续了 ap_per_class 函数的定义,它计算每个类别的平均精度(AP)并绘制相关的度量曲线。# Compute F1 (harmonic mean of precision and recall)# 计算F1曲线,F1是精确度和召回率的调和平均值。f1_curve = 2 * p_curve * r_curve / (p_curve + r_curve + eps)# 创建一个只包含有数据的类别的名称列表。names = [v for k, v in names.items() if k in unique_classes]  # list: only classes that have data# 将列表转换为字典,以便于绘图时使用。names = dict(enumerate(names))  # to dict# 如果需要绘图。if plot:# 绘制精确度-召回率曲线。plot_pr_curve(x, prec_values, ap, save_dir / f"{prefix}PR_curve.png", names, on_plot=on_plot)# 绘制F1曲线。plot_mc_curve(x, f1_curve, save_dir / f"{prefix}F1_curve.png", names, ylabel="F1", on_plot=on_plot)# 绘制精确度曲线。plot_mc_curve(x, p_curve, save_dir / f"{prefix}P_curve.png", names, ylabel="Precision", on_plot=on_plot)# 绘制召回率曲线。plot_mc_curve(x, r_curve, save_dir / f"{prefix}R_curve.png", names, ylabel="Recall", on_plot=on_plot)# 找到F1曲线均值的最大索引,这表示最佳的置信度阈值。i = smooth(f1_curve.mean(0), 0.1).argmax()  # max F1 index# 获取最大F1值对应的 精确度 、 召回率 和 F1值 。p, r, f1 = p_curve[:, i], r_curve[:, i], f1_curve[:, i]  # max-F1 precision, recall, F1 values# 计算 真阳性 ,即在最佳置信度阈值下的正确预测数量。tp = (r * nt).round()  # true positives# 计算 假阳性 即在最佳置信度阈值下的错误预测数量。fp = (tp / (p + eps) - tp).round()  # false positives# 返回:# (tuple):六个数组和一个唯一类数组的元组,其中:# tp (np.ndarray) :每个类的最大 F1 度量给出的阈值处的真阳性计数。形状:(nc,)。# fp (np.ndarray) :每个类的最大 F1 度量给出的阈值处的假阳性计数。形状:(nc,)。# p (np.ndarray) :每个类的最大 F1 度量给出的阈值处的精确度值。形状:(nc,)。# r (np.ndarray) :每个类的最大 F1 度量给出的阈值处的召回率值。形状:(nc,)。# f1 (np.ndarray) :每个类的最大 F1 度量给出的阈值处的 F1 分数值。形状:(nc,)。# ap  (np.ndarray) :不同 IoU 阈值下每个类的平均精度。形状:(nc, 10)。# unique_classes  (np.ndarray) :具有数据的唯一类的数组。形状:(nc,)。# p_curve  (np.ndarray) :每个类的精度曲线。形状:(nc, 1000)。# r_curve  (np.ndarray) :每个类的召回率曲线。形状:(nc, 1000)。# f1_curve  (np.ndarray) :每个类的 F1 分数曲线。形状:(nc, 1000)。# x (np.ndarray) :曲线的 X 轴值。形状:(1000,)。# prec_value :每个类在 mAP@0.5 时的精度值。形状:(nc, 1000)。# 返回计算结果,包括 真阳性tp 、 假阳性fp 、 精确度p 、 召回率r 、 F1值f1 、 APap 、 类别unique_classes.astype(int) 、 精确度曲线p_curve 、 召回率曲线r_curve 、 F1曲线f1_curve 和 插值后的精确度值prec_values 。return tp, fp, p, r, f1, ap, unique_classes.astype(int), p_curve, r_curve, f1_curve, x, prec_values# 这段代码提供了一个完整的流程,从计算每个类别的AP到绘制相关的度量曲线,使得模型性能的评估和可视化变得简单和自动化。
# 这个函数提供了一个完整的流程,从计算每个类别的AP到绘制相关的度量曲线,使得模型性能的评估和可视化变得简单和自动化。

17.class Metric(SimpleClass): 

# 这段代码定义了一个名为 Metric 的类,它继承自 SimpleClass 。 Metric 类的实例用于计算 YOLOv8 模型的评估指标。
# 定义了一个名为 Metric 的类,它继承自 SimpleClass 。这意味着 Metric 类将拥有 SimpleClass 的所有属性和方法。
# class SimpleClass:
# -> 这段代码定义了一个名为 SimpleClass 的基类,它提供了一些基本的功能,包括对象的字符串表示、机器可读的字符串表示,以及自定义的属性访问错误消息。
# -> def __str__(self):
# -> 定义了 __str__ 方法,它返回一个人类可读的字符串表示形式,通常用于打印和日志记录。
# -> def __repr__(self):
# -> 定义了 __repr__ 方法,它返回一个机器可读的字符串表示形式,通常用于调试和开发。
# -> def __getattr__(self, attr):
# -> 定义了 __getattr__ 方法,它在尝试访问不存在的属性时被调用。
class Metric(SimpleClass):# 用于计算 YOLOv8 模型评估指标的类。# 属性:# p (list):每个类的准确率。形状:(nc,)。# r (list):每个类的召回率。形状:(nc,)。# f1 (list):每个类的 F1 分数。形状:(nc,)。# all_ap (list):所有类和所有 IoU 阈值的 AP 分数。形状:(nc, 10)。# ap_class_index (list):每个 AP 分数的类索引。形状:(nc,)。# nc (int):类数。# 方法:# ap50():所有类的 IoU 阈值为 0.5 时的 AP。返回:AP 分数列表。形状:(nc,) 或 []。# ap():所有类的 IoU 阈值从 0.5 到 0.95 时的 AP。返回:AP 分数列表。形状:(nc,) 或 []。# mp():所有类的平均准确率。返回:浮点数。# mr():所有类别的平均召回率。返回:浮点数。# map50():所有类别在 IoU 阈值为 0.5 时的平均 AP。返回:浮点数。# map75():所有类别在 IoU 阈值为 0.75 时的平均 AP。返回:浮点数。# map():所有类别在 IoU 阈值从 0.5 到 0.95 时的平均 AP。返回:浮点数。# mean_results():结果的平均值,返回 mp、mr、map50、map。# class_result(i):类别感知结果,返回 p[i]、r[i]、ap50[i]、ap[i]。# maps():每个类别的 mAP。返回:mAP 分数数组,形状:(nc,)。# fitness():将适应度建模为指标的加权组合。返回:浮点数。# update(results):使用新的评估结果更新指标属性。"""Class for computing evaluation metrics for YOLOv8 model.Attributes:p (list): Precision for each class. Shape: (nc,).r (list): Recall for each class. Shape: (nc,).f1 (list): F1 score for each class. Shape: (nc,).all_ap (list): AP scores for all classes and all IoU thresholds. Shape: (nc, 10).ap_class_index (list): Index of class for each AP score. Shape: (nc,).nc (int): Number of classes.Methods:ap50(): AP at IoU threshold of 0.5 for all classes. Returns: List of AP scores. Shape: (nc,) or [].ap(): AP at IoU thresholds from 0.5 to 0.95 for all classes. Returns: List of AP scores. Shape: (nc,) or [].mp(): Mean precision of all classes. Returns: Float.mr(): Mean recall of all classes. Returns: Float.map50(): Mean AP at IoU threshold of 0.5 for all classes. Returns: Float.map75(): Mean AP at IoU threshold of 0.75 for all classes. Returns: Float.map(): Mean AP at IoU thresholds from 0.5 to 0.95 for all classes. Returns: Float.mean_results(): Mean of results, returns mp, mr, map50, map.class_result(i): Class-aware result, returns p[i], r[i], ap50[i], ap[i].maps(): mAP of each class. Returns: Array of mAP scores, shape: (nc,).fitness(): Model fitness as a weighted combination of metrics. Returns: Float.update(results): Update metric attributes with new evaluation results."""# 定义了 Metric 类的构造函数,它在创建类的实例时被调用。def __init__(self) -> None:# 初始化 Metric 实例,用于计算 YOLOv8 模型的评估指标。"""Initializes a Metric instance for computing evaluation metrics for the YOLOv8 model."""# 初始化一个空列表来存储每个类别的精确度(Precision)值。self.p = []  # (nc, )# 初始化一个空列表来存储每个类别的召回率(Recall)值。self.r = []  # (nc, )# 初始化一个空列表来存储每个类别的 F1 分数。self.f1 = []  # (nc, )# 初始化一个空列表来存储每个类别的 AP 值,这里假设有10个不同的置信度阈值。self.all_ap = []  # (nc, 10)# 初始化一个空列表来存储每个类别的 AP 值对应的类别索引。self.ap_class_index = []  # (nc, )# 初始化一个变量来存储类别的数量,初始值为0。self.nc = 0# 这个类的构造函数主要用于初始化一些用于存储评估指标的变量。这些变量将在模型评估过程中被填充,并用于计算和存储精确度、召回率、F1分数和平均精度等指标。 self.nc 将用于存储类别的总数,而其他列表将用于存储每个类别对应的评估指标。# 这段代码定义了一个名为 ap50 的属性装饰器(使用 @property 装饰器),它通常用于类的实例中,用于提供一个名为 ap50 的只读属性。这个属性返回 all_ap 数组的第一列,即在置信度阈值为 50% 时的平均精度(AP)值。# @property 是一个装饰器,它将一个方法转换为属性。这意味着你可以像访问属性一样访问这个方法,而不需要使用括号。@property# 定义了一个名为 ap50 的方法,它接受 self 作为参数。# 1.self :指的是类的实例本身。def ap50(self):# 返回所有类别在 IoU 阈值为 0.5 时的平均精度 (AP)。"""Returns the Average Precision (AP) at an IoU threshold of 0.5 for all classes.Returns:(np.ndarray, list): Array of shape (nc,) with AP50 values per class, or an empty list if not available."""# 是方法的主体。它检查 self.all_ap 数组是否非空。如果 self.all_ap 非空(即至少有一个元素),则返回 self.all_ap 的第一列,使用 self.all_ap[:, 0] 进行索引。 如果 self.all_ap 为空(即没有元素),则返回一个空列表 [] 。return self.all_ap[:, 0] if len(self.all_ap) else []# 这个属性装饰器提供了一种简洁的方式来访问特定置信度阈值下的平均精度值。使用 @property 装饰器,你可以像这样访问 ap50 属性:# instance = SomeClass()# ap50_values = instance.ap50# 在这个例子中, SomeClass 是包含 ap50 属性的类, instance 是该类的实例。通过访问 instance.ap50 ,实际上是调用了 ap50 方法,并获取了返回值。如果 self.all_ap 是空的, ap50 将返回一个空列表,这提供了一种安全的方式来避免索引错误。# 这段代码定义了一个名为 ap 的属性装饰器,它用于计算并返回所有类别在 IoU(交并比)阈值从 0.5 到 0.95 的平均精度(AP)。# @property 是一个装饰器,它允许将一个方法作为属性来访问,使得可以通过属性访问的方式来调用这个方法,而不需要使用括号。@property# 定义了一个名为 ap 的方法,它接受 self 作为参数。 1.self :代表类的实例本身。def ap(self):# 返回所有类别的 IoU 阈值为 0.5-0.95 的平均精度 (AP)。"""Returns the Average Precision (AP) at an IoU threshold of 0.5-0.95 for all classes.Returns:(np.ndarray, list): Array of shape (nc,) with AP50-95 values per class, or an empty list if not available."""# 是方法的主体。它检查 self.all_ap 数组是否非空。如果 self.all_ap 非空(即至少有一个元素),则计算 self.all_ap 在维度 1(即列)上的平均值,并返回这个结果。这实际上是计算每个类别在所有 IoU 阈值上的平均精度的平均值。 如果 self.all_ap 为空(即没有元素),则返回一个空列表 [] 。return self.all_ap.mean(1) if len(self.all_ap) else []# 这个方法提供了一种简洁的方式来访问每个类别在一系列 IoU 阈值上的平均精度值。# 这段代码定义了一个名为 mp 的属性装饰器,它用于计算并返回所有类别的精确度(Precision)的平均值。# @property 是一个装饰器,它将一个方法转换为属性,允许你像访问属性一样访问这个方法,而不需要使用括号。@property# 定义了一个名为 mp 的方法,它接受 self 作为参数。1.self :代表类的实例本身。def mp(self):# 返回所有类别的平均精度。"""Returns the Mean Precision of all classes.Returns:(float): The mean precision of all classes."""# 是方法的主体。它检查 self.p 列表是否非空。如果 self.p 非空(即至少有一个元素),则计算 self.p 中所有元素的平均值,并返回这个结果。这里 self.p 是一个包含各个类别精确度值的列表或数组, .mean() 方法计算这些值的平均值。 如果 self.p 为空(即没有元素),则返回 0.0 。return self.p.mean() if len(self.p) else 0.0# 这个方法提供了一种简洁的方式来访问所有类别的精确度平均值。# 这段代码定义了一个名为 mr 的属性装饰器,它用于计算并返回所有类别的召回率(Recall)的平均值。# @property 是一个装饰器,它将一个方法转换为属性,允许你像访问属性一样访问这个方法,而不需要使用括号。@property# 定义了一个名为 mr 的方法,它接受 self 作为参数。1.self :代表类的实例本身。def mr(self):# 返回所有类别的平均召回率。"""Returns the Mean Recall of all classes.Returns:(float): The mean recall of all classes."""# 是方法的主体。它检查 self.r 列表是否非空。如果 self.r 非空(即至少有一个元素),则计算 self.r 中所有元素的平均值,并返回这个结果。这里 self.r 是一个包含各个类别召回率值的列表或数组, .mean() 方法计算这些值的平均值。 如果 self.r 为空(即没有元素),则返回 0.0 。return self.r.mean() if len(self.r) else 0.0# 这个方法提供了一种简洁的方式来访问所有类别的召回率平均值。# 这段代码定义了一个名为 map50 的属性装饰器,它用于计算并返回所有类别在 IoU 阈值为 0.5 时的平均精度(Average Precision, AP)的平均值,也就是 mAP@0.5。# @property 是一个装饰器,它允许将一个方法转换为属性,使得可以通过属性访问的方式来调用这个方法,而不需要使用括号。@property# 定义了一个名为 map50 的方法,它接受 self 作为参数。1.self :代表类的实例本身。def map50(self):# 返回 IoU 阈值为 0.5 时的平均精度 (mAP)。"""Returns the mean Average Precision (mAP) at an IoU threshold of 0.5.Returns:(float): The mAP at an IoU threshold of 0.5."""# 是方法的主体。它检查 self.all_ap 数组是否非空。如果 self.all_ap 非空(即至少有一个元素),则返回 self.all_ap 的第一列(即 IoU 阈值为 0.5 时的 AP 值)的平均值。这里使用 self.all_ap[:, 0] 来索引第一列, .mean() 方法计算这些值的平均值。 如果 self.all_ap 为空(即没有元素),则返回 0.0 。return self.all_ap[:, 0].mean() if len(self.all_ap) else 0.0# 这个方法提供了一种简洁的方式来访问所有类别在 IoU 阈值为 0.5 时的平均精度的平均值。# 这段代码定义了一个名为 map75 的属性装饰器,它用于计算并返回所有类别在 IoU 阈值为 0.75 时的平均精度(Average Precision, AP)的平均值,也就是 mAP@0.75。# @property 是一个装饰器,它允许将一个方法转换为属性,使得可以通过属性访问的方式来调用这个方法,而不需要使用括号。@property# 定义了一个名为 map75 的方法,它接受 self 作为参数。1.self :代表类的实例本身。def map75(self):# 返回 IoU 阈值为 0.75 时的平均准确率 (mAP)。"""Returns the mean Average Precision (mAP) at an IoU threshold of 0.75.Returns:(float): The mAP at an IoU threshold of 0.75."""# 是方法的主体。它检查 self.all_ap 数组是否非空。如果 self.all_ap 非空(即至少有一个元素),则返回 self.all_ap 的第6列(即 IoU 阈值为 0.75 时的 AP 值)的平均值。这里使用 self.all_ap[:, 5] 来索引第6列(因为索引是从0开始的), .mean() 方法计算这些值的平均值。 如果 self.all_ap 为空(即没有元素),则返回 0.0 。return self.all_ap[:, 5].mean() if len(self.all_ap) else 0.0# 这个方法提供了一种简洁的方式来访问所有类别在 IoU 阈值为 0.75 时的平均精度的平均值。# 这段代码定义了一个名为 map 的属性装饰器,它用于计算并返回所有类别在所有 IoU 阈值下的平均精度(Average Precision, AP)的平均值,也就是 mAP(mean Average Precision)。# @property 是一个装饰器,它允许将一个方法转换为属性,使得可以通过属性访问的方式来调用这个方法,而不需要使用括号。@property# 定义了一个名为 map 的方法,它接受 self 作为参数。1.self :代表类的实例本身。def map(self):# 返回 IoU 阈值为 0.5 - 0.95 时的平均精度 (mAP),步长为 0.05。"""Returns the mean Average Precision (mAP) over IoU thresholds of 0.5 - 0.95 in steps of 0.05.Returns:(float): The mAP over IoU thresholds of 0.5 - 0.95 in steps of 0.05."""# 是方法的主体。它检查 self.all_ap 数组是否非空。如果 self.all_ap 非空(即至少有一个元素),则返回 self.all_ap 中所有元素的平均值。这里 self.all_ap 应该是一个包含各个类别在不同 IoU 阈值下的 AP 值的二维数组, .mean() 方法计算这些值的平均值。 如果 self.all_ap 为空(即没有元素),则返回 0.0 。return self.all_ap.mean() if len(self.all_ap) else 0.0# 这个方法提供了一种简洁的方式来访问所有类别在所有 IoU 阈值下的平均精度的平均值。# 这段代码定义了一个名为 mean_results 的方法,它用于计算并返回模型性能的几个关键平均指标。# 定义了一个名为 mean_results 的方法,它接受 self 作为参数。1.self :代表类的实例本身。def mean_results(self):# 结果的平均值,返回mp、mr、map50、map。"""Mean of results, return mp, mr, map50, map."""# 是方法的主体,它返回一个列表,包含以下四个指标。self.mp :通过 mp 属性装饰器访问的精确度平均值。 self.mr :通过 mr 属性装饰器访问的召回率平均值。 self.map50 :通过 map50 属性装饰器访问的在 IoU 阈值为 0.5 时的平均精度平均值。 self.map :通过 map 属性装饰器访问的所有 IoU 阈值下的平均精度平均值。return [self.mp, self.mr, self.map50, self.map]# 这个方法提供了一种简洁的方式来一次性获取模型性能的关键平均指标。# 这段代码定义了一个名为 class_result 的方法,它用于获取特定类别的评估结果,包括精确度(Precision)、召回率(Recall)、在 IoU 阈值为 0.5 时的平均精度(AP50)以及所有 IoU 阈值下的平均精度(AP)。# 定义了一个名为 class_result 的方法,它接受两个参数。# 1.self :代表类的实例本身。# 2.i :是要查询的类别的索引。def class_result(self, i):# 类感知结果,返回 p[i]、r[i]、ap50[i]、ap[i]。"""Class-aware result, return p[i], r[i], ap50[i], ap[i]."""# 是方法的主体,它返回一个包含四个指标的元组。 self.p[i] :第 i 个类别的精确度值。 self.r[i] :第 i 个类别的召回率值。 self.ap50[i] :第 i 个类别在 IoU 阈值为 0.5 时的平均精度值。 self.ap[i] :第 i 个类别在所有 IoU 阈值下的平均精度值。return self.p[i], self.r[i], self.ap50[i], self.ap[i]# 这个方法提供了一种方式来获取特定类别的详细评估结果。# 这段代码定义了一个名为 maps 的属性装饰器,它用于计算并返回每个类别的平均精度(Average Precision, AP),即 mAP(mean Average Precision)的数组。# @property 是一个装饰器,它允许将一个方法转换为属性,使得可以通过属性访问的方式来调用这个方法,而不需要使用括号。@property# 定义了一个名为 maps 的方法,它接受 self 作为参数。1.self :代表类的实例本身。def maps(self):"""MAP of each class."""# 初始化一个长度为 self.nc (类别数量)的数组 maps ,并将 self.map (所有类别的平均精度的平均值)赋值给数组中的每个元素。maps = np.zeros(self.nc) + self.map# 遍历 self.ap_class_index  ,这是一个包含类别索引的列表,其中每个索引对应于 self.ap 数组中的一个 AP 值。for i, c in enumerate(self.ap_class_index):# 将 self.ap 数组中的第 i 个 AP 值赋值给 maps 数组中的第 c 个元素,其中 c 是类别索引。maps[c] = self.ap[i]# 返回 maps 数组,它包含每个类别的平均精度值。return maps# 这个方法提供了一种方式来获取每个类别的平均精度值。# 这段代码定义了一个名为 fitness 的方法,它用于计算模型的适应度,即模型性能的加权组合。#  定义了一个名为 fitness 的方法,它接受 self 作为参数。1.self :代表类的实例本身。def fitness(self):# 将模型适应度作为指标的加权组合。"""Model fitness as a weighted combination of metrics."""# 定义了一个权重列表 w ,用于计算模型适应度。这些权重分别对应于 精确度(P) 、 召回率(R) 、 在 IoU 阈值为 0.5 时的平均精度(mAP@0.5) 以及 在 IoU 阈值从 0.5 到 0.95 的平均精度(mAP@0.5:0.95) 。w = [0.0, 0.0, 0.1, 0.9]  # weights for [P, R, mAP@0.5, mAP@0.5:0.95]# 是方法的主体,它执行以下操作 :# self.mean_results() 调用 mean_results 方法,获取模型的平均精确度、平均召回率、mAP@0.5 和 mAP@0.5:0.95。# np.array(self.mean_results()) 将返回的列表转换为 NumPy 数组。# np.array(self.mean_results()) * w 将 NumPy 数组中的每个元素与对应的权重相乘。# (np.array(self.mean_results()) * w).sum() 计算加权数组的总和,即模型的适应度。return (np.array(self.mean_results()) * w).sum()# 这个方法提供了一种方式来计算模型的适应度,它考虑了模型在不同指标上的表现,并通过权重来调整这些指标的重要性。# 这段代码定义了一个名为 update 的方法,它用于更新类实例的状态,将传入的结果赋值给实例的相应属性。# 定义了一个名为 update 的方法,它接受两个参数。# 1.self :代表类的实例本身。# 2.results :是包含要更新的数据的元组或列表。def update(self, results):# 使用一组新结果更新模型的评估指标。"""Updates the evaluation metrics of the model with a new set of results.Args:results (tuple): A tuple containing the following evaluation metrics:- p (list): Precision for each class. Shape: (nc,).- r (list): Recall for each class. Shape: (nc,).- f1 (list): F1 score for each class. Shape: (nc,).- all_ap (list): AP scores for all classes and all IoU thresholds. Shape: (nc, 10).- ap_class_index (list): Index of class for each AP score. Shape: (nc,).Side Effects:Updates the class attributes `self.p`, `self.r`, `self.f1`, `self.all_ap`, and `self.ap_class_index` basedon the values provided in the `results` tuple."""# 是方法的主体,它将 results 元组中的值分别赋给类实例的属性 :# self.p :更新精确度(Precision)值。# self.r :更新召回率(Recall)值。# self.f1 :更新 F1 分数。# self.all_ap :更新所有类别的平均精度(AP)值。# self.ap_class_index :更新 AP 值对应的类别索引。# self.p_curve :更新精确度曲线。# self.r_curve :更新召回率曲线。# self.f1_curve :更新 F1 分数曲线。# self.px :更新 x 轴的值,通常用于绘制曲线。# self.prec_values :更新精确度值,可能用于绘制精确度曲线。(self.p,self.r,self.f1,self.all_ap,self.ap_class_index,self.p_curve,self.r_curve,self.f1_curve,self.px,self.prec_values,) = results# 这个方法允许类的实例在运行时动态更新其状态,通常用于累积或更新模型评估的结果。# 这段代码定义了一个名为 curves 的属性装饰器,它用于返回一个包含特定度量曲线的列表。# @property 是一个装饰器,它将一个方法转换为属性,允许你像访问属性一样访问这个方法,而不需要使用括号。@property# 定义了一个名为 curves 的方法,它接受 self 作为参数。1.self :代表类的实例本身。def curves(self):# 返回用于访问特定指标曲线的曲线列表。"""Returns a list of curves for accessing specific metrics curves."""#  是方法的主体,它返回一个空列表。这表明在当前的实现中,并没有提供具体的度量曲线数据。return []# 这个方法提供了一个接口来访问度量曲线,但在这个方法的实现中,并没有实际返回任何曲线数据。在实际应用中,这个方法可能会被重写或扩展,以返回包含精确度曲线、召回率曲线、F1分数曲线等度量曲线的列表。# property(fget=None, fset=None, fdel=None, doc=None)# 在 Python 中, property 是一个内置函数,用于创建属性访问器(getter)、修改器(setter)和删除器(deleter)。 property 函数通常用于将类的方法转换为属性,使得这些方法可以像访问普通属性一样被访问。# 参数 :# fget :一个函数,用于获取属性值。如果没有提供,则属性将只写。# fset :一个函数,用于设置属性值。如果没有提供,则属性将只读。# fdel :一个函数,用于删除属性。如果没有提供,则属性将不能被删除。# doc :属性的文档字符串。# 返回值 :# 返回一个属性对象,该对象可以用于定义管理属性访问的方法。# 用法示例 :# @property# property 函数是 Python 中实现 getter/setter/ deleter 的标准方式,它允许在访问属性时执行额外的逻辑,例如验证或更新其他属性。# 这段代码定义了一个名为 curves_results 的属性装饰器,它用于返回一个包含特定度量曲线的列表。# @property 是一个装饰器,它将一个方法转换为属性,允许你像访问属性一样访问这个方法,而不需要使用括号。@property# 定义了一个名为 curves_results 的方法,它接受 self 作为参数。1.self :代表类的实例本身。def curves_results(self):# 返回用于访问特定指标曲线的曲线列表。"""Returns a list of curves for accessing specific metrics curves."""# 是方法的主体,它返回一个列表,其中包含四个元组,每个元组代表一个度量曲线的数据 :# 第一个元组包含 self.px (x轴的值,通常用于绘制曲线), self.prec_values (精确度值),"Recall"(y轴标签),和 "Precision"(曲线名称)。# 第二个元组包含 self.px , self.f1_curve (F1分数曲线),"Confidence"(y轴标签),和 "F1"(曲线名称)。# 第三个元组包含 self.px , self.p_curve (精确度曲线),"Confidence"(y轴标签),和 "Precision"(曲线名称)。# 第四个元组包含 self.px , self.r_curve (召回率曲线),"Confidence"(y轴标签),和 "Recall"(曲线名称)。return [[self.px, self.prec_values, "Recall", "Precision"],[self.px, self.f1_curve, "Confidence", "F1"],[self.px, self.p_curve, "Confidence", "Precision"],[self.px, self.r_curve, "Confidence", "Recall"],]# 这个方法提供了一个接口来访问度量曲线,包括精确度、召回率、F1分数等。

18.class DetMetrics(SimpleClass): 

# 这段代码定义了一个名为 DetMetrics 的类,它继承自 SimpleClass 。 DetMetrics 类的实例用于计算和存储目标检测模型的性能指标。
class DetMetrics(SimpleClass):# 用于计算检测指标(例如对象检测模型的精度、召回率和平均精度 (mAP))的实用程序类。# 属性:# save_dir (Path):保存输出图的目录路径。# plot (bool):指示是否为每个类绘制精确召回率曲线的标志。# on_plot (func):可选回调,用于在渲染图时传递图路径和数据。# names (str 字典):表示类名称的字符串字典。默认为空元组。类。# box(Metric):用于存储检测指标结果的 Metric 类的实例。# speed(dict):用于存储检测过程不同部分的执行时间的字典。"""Utility class for computing detection metrics such as precision, recall, and mean average precision (mAP) of anobject detection model.Args:save_dir (Path): A path to the directory where the output plots will be saved. Defaults to current directory.plot (bool): A flag that indicates whether to plot precision-recall curves for each class. Defaults to False.on_plot (func): An optional callback to pass plots path and data when they are rendered. Defaults to None.names (dict of str): A dict of strings that represents the names of the classes. Defaults to an empty tuple.Attributes:save_dir (Path): A path to the directory where the output plots will be saved.plot (bool): A flag that indicates whether to plot the precision-recall curves for each class.on_plot (func): An optional callback to pass plots path and data when they are rendered.names (dict of str): A dict of strings that represents the names of the classes.box (Metric): An instance of the Metric class for storing the results of the detection metrics.speed (dict): A dictionary for storing the execution time of different parts of the detection process.Methods:process(tp, conf, pred_cls, target_cls): Updates the metric results with the latest batch of predictions.keys: Returns a list of keys for accessing the computed detection metrics.mean_results: Returns a list of mean values for the computed detection metrics.class_result(i): Returns a list of values for the computed detection metrics for a specific class.maps: Returns a dictionary of mean average precision (mAP) values for different IoU thresholds.fitness: Computes the fitness score based on the computed detection metrics.ap_class_index: Returns a list of class indices sorted by their average precision (AP) values.results_dict: Returns a dictionary that maps detection metric keys to their computed values.curves: TODOcurves_results: TODO"""# 定义了 DetMetrics 类的构造函数,它接受以下参数 :# 1.save_dir (默认为当前目录):保存图表和结果的目录。# 2.plot (默认为 False ):是否绘制度量曲线。# 3.on_plot (默认为 None ):一个可选的回调函数,用于在图表渲染后传递图表路径和数据。# 4.names (默认为空字典):类别的名称,用于图表上的图例。def __init__(self, save_dir=Path("."), plot=False, on_plot=None, names={}) -> None:# 使用保存目录、绘图标志、回调函数和类名初始化 DetMetrics 实例。"""Initialize a DetMetrics instance with a save directory, plot flag, callback function, and class names."""# 将构造函数的参数赋值给实例变量。self.save_dir = save_dirself.plot = plotself.on_plot = on_plotself.names = names# 创建一个 Metric 类的实例,用于存储和计算性能指标。self.box = Metric()# 初始化一个字典来存储不同处理阶段的速度。self.speed = {"preprocess": 0.0, "inference": 0.0, "loss": 0.0, "postprocess": 0.0}# 设置任务类型为 "detect"。self.task = "detect"# 定义了一个名为 process 的方法,用于处理预测结果并更新指标。# 1.tp :真实阳性数组。# 2.conf :置信度数组。# 3.pred_cls :预测类别数组。# 4.target_cls :目标类别数组。def process(self, tp, conf, pred_cls, target_cls):# 处理对象检测的预测结果并更新指标。"""Process predicted results for object detection and update metrics."""# 调用 ap_per_class 函数计算每个类别的 AP 值和其他指标。# def ap_per_class(tp, conf, pred_cls, target_cls, plot=False, on_plot=None, save_dir=Path(), names={}, eps=1e-16, prefix=""):# -> 它用于计算每个类别的 平均精度 (AP) 并绘制相关的度量曲线。返回计算结果,包括 真阳性tp 、 假阳性fp 、 精确度p 、 召回率r 、 F1值f1 、 APap 、 类别unique_classes.astype(int) 、 精确度曲线p_curve 、 召回率曲线r_curve 、 F1曲线f1_curve 和 插值后的精确度值prec_values 。# -> return tp, fp, p, r, f1, ap, unique_classes.astype(int), p_curve, r_curve, f1_curve, x, prec_valuesresults = ap_per_class(tp,conf,pred_cls,target_cls,plot=self.plot,save_dir=self.save_dir,names=self.names,on_plot=self.on_plot,)[2:]self.box.nc = len(self.names)# 更新 Metric 实例的状态。self.box.update(results)# 定义了一个名为 keys 的属性装饰器,返回一个列表,包含用于访问特定指标的键。@propertydef keys(self):# 返回用于访问特定指标的键列表。"""Returns a list of keys for accessing specific metrics."""return ["metrics/precision(B)", "metrics/recall(B)", "metrics/mAP50(B)", "metrics/mAP50-95(B)"]# 定义了一个名为 mean_results 的方法,计算并返回模型的平均精确度、召回率、mAP@0.5 和 mAP@0.5-0.95。def mean_results(self):# 计算检测到的物体的平均值并返回精度、召回率、mAP50 和 mAP50-95。"""Calculate mean of detected objects & return precision, recall, mAP50, and mAP50-95."""return self.box.mean_results()# 定义了一个名为 class_result 的方法,返回特定类别的性能评估结果。def class_result(self, i):# 返回评估对象检测模型在特定类别上的性能的结果。"""Return the result of evaluating the performance of an object detection model on a specific class."""return self.box.class_result(i)# 定义了一个名为 maps 的属性装饰器,返回每个类别的 mAP 分数。@propertydef maps(self):# 返回每个类别的平均精度(mAP)分数。"""Returns mean Average Precision (mAP) scores per class."""return self.box.maps# 定义了一个名为 fitness 的属性装饰器,返回模型的适应度。@propertydef fitness(self):# 返回边界框对象的适应度。"""Returns the fitness of box object."""return self.box.fitness()#  定义了一个名为 ap_class_index 的属性装饰器,返回每个类别的 AP 索引。@propertydef ap_class_index(self):# 返回每个类的平均精度指数。"""Returns the average precision index per class."""return self.box.ap_class_index# 定义了一个名为 results_dict 的属性装饰器,返回一个字典,包含计算出的性能指标和统计数据。@propertydef results_dict(self):# 返回计算的性能指标和统计数据的字典。"""Returns dictionary of computed performance metrics and statistics."""# 这行代码创建了一个字典,它将 self.keys 列表中的键与 self.mean_results() 方法返回的值以及键 "fitness" 与 self.fitness 属性的值相映射。# zip(self.keys + ["fitness"], self.mean_results() + [self.fitness]) 使用 zip 函数将两个列表中的元素配对,形成一个迭代器。# dict(zip(self.keys + ["fitness"], self.mean_results() + [self.fitness])) 将 zip 函数返回的迭代器转换为字典。# 在 Python 中, + 运算符用于连接两个列表,创建一个新的列表。在表达式 self.keys + ["fitness"] 中, + 运算符将列表 self.keys 和包含单个字符串 "fitness" 的列表 ["fitness"] 连接在一起。# 这个新列表包含了 self.keys 中的所有元素,并且在末尾追加了 "fitness" 这个元素。这个操作是不可变的,意味着 self.keys 本身不会被修改,而是创建了一个新的列表。这个新列表通常用于后续的操作,比如 zip 函数,用于将两个列表的元素配对。return dict(zip(self.keys + ["fitness"], self.mean_results() + [self.fitness]))# 定义了一个名为 curves 的属性装饰器,返回一个列表,包含用于访问特定度量曲线的曲线名称。@propertydef curves(self):# 返回用于访问特定指标曲线的曲线列表。"""Returns a list of curves for accessing specific metrics curves."""return ["Precision-Recall(B)", "F1-Confidence(B)", "Precision-Confidence(B)", "Recall-Confidence(B)"]# 定义了一个名为 curves_results 的属性装饰器,返回一个字典,包含计算出的性能指标和统计数据。@propertydef curves_results(self):# 返回计算的性能指标和统计数据的字典。"""Returns dictionary of computed performance metrics and statistics."""return self.box.curves_results
# 这个类提供了一个完整的框架来计算和存储目标检测模型的性能指标,包括精确度、召回率、F1分数和平均精度。它还提供了方法来绘制度量曲线和返回性能指标的字典。

19.class SegmentMetrics(SimpleClass): 

# 这段代码定义了一个名为 SegmentMetrics 的类,它继承自 SimpleClass 。 SegmentMetrics 类的实例用于计算和存储目标检测(bounding box)和语义分割(mask)模型的性能指标。
class SegmentMetrics(SimpleClass):# 计算并汇总给定类集的检测和分割指标。# 方法:# process(tp_m、tp_b、conf、pred_cls、target_cls):处理给定预测集的指标。# mean_results():返回所有类别的检测和分割指标的平均值。# class_result(i):返回类“i”的检测和分割指标。# map:返回 IoU 阈值的平均平均精度 (mAP) 分数,范围从 0.50 到 0.95。# fitness:返回适应度分数,即指标的单一加权组合。# ap_class_index:返回用于计算平均精度 (AP) 的类索引列表。# results_dict:返回包含所有检测和分割指标以及适应度分数的字典。"""Calculates and aggregates detection and segmentation metrics over a given set of classes.Args:save_dir (Path): Path to the directory where the output plots should be saved. Default is the current directory.plot (bool): Whether to save the detection and segmentation plots. Default is False.on_plot (func): An optional callback to pass plots path and data when they are rendered. Defaults to None.names (list): List of class names. Default is an empty list.Attributes:save_dir (Path): Path to the directory where the output plots should be saved.plot (bool): Whether to save the detection and segmentation plots.on_plot (func): An optional callback to pass plots path and data when they are rendered.names (list): List of class names.box (Metric): An instance of the Metric class to calculate box detection metrics.seg (Metric): An instance of the Metric class to calculate mask segmentation metrics.speed (dict): Dictionary to store the time taken in different phases of inference.Methods:process(tp_m, tp_b, conf, pred_cls, target_cls): Processes metrics over the given set of predictions.mean_results(): Returns the mean of the detection and segmentation metrics over all the classes.class_result(i): Returns the detection and segmentation metrics of class `i`.maps: Returns the mean Average Precision (mAP) scores for IoU thresholds ranging from 0.50 to 0.95.fitness: Returns the fitness scores, which are a single weighted combination of metrics.ap_class_index: Returns the list of indices of classes used to compute Average Precision (AP).results_dict: Returns the dictionary containing all the detection and segmentation metrics and fitness score."""# 定义了 SegmentMetrics 类的构造函数,它接受以下参数。# 1.save_dir (默认为当前目录):保存图表和结果的目录。# 2.plot (默认为 False ):是否绘制度量曲线。# 3.on_plot (默认为 None ):一个可选的回调函数,用于在图表渲染后传递图表路径和数据。# 4.names (默认为空元组):类别的名称,用于图表上的图例。def __init__(self, save_dir=Path("."), plot=False, on_plot=None, names=()) -> None:"""Initialize a SegmentMetrics instance with a save directory, plot flag, callback function, and class names."""# 将构造函数的参数赋值给实例变量。self.save_dir = save_dirself.plot = plotself.on_plot = on_plotself.names = names# 创建两个 Metric 类的实例,分别用于存储和计算 目标检测 和 语义分割 的性能指标。self.box = Metric()self.seg = Metric()# 初始化一个字典来存储不同处理阶段的速度。self.speed = {"preprocess": 0.0, "inference": 0.0, "loss": 0.0, "postprocess": 0.0}# 设置任务类型为 "segment"。self.task = "segment"# 定义了一个名为 process 的方法,用于处理预测结果并更新目标检测和语义分割的指标。# 1.tp :真实阳性边界框数组。# 2.tp_m :真实阳性掩码数组。# 3.conf :置信度数组。# 4.pred_cls :预测类别数组。# 5.target_cls :目标类别数组。def process(self, tp, tp_m, conf, pred_cls, target_cls):"""Processes the detection and segmentation metrics over the given set of predictions.Args:tp (list): List of True Positive boxes.tp_m (list): List of True Positive masks.conf (list): List of confidence scores.pred_cls (list): List of predicted classes.target_cls (list): List of target classes."""# results_mask = ap_per_class(...) 和 results_box = ap_per_class(...) 调用 ap_per_class 函数计算每个类别的 AP 值和其他指标,分别针对掩码和边界框。results_mask = ap_per_class(tp_m,conf,pred_cls,target_cls,plot=self.plot,on_plot=self.on_plot,save_dir=self.save_dir,names=self.names,prefix="Mask",)[2:]self.seg.nc = len(self.names)# self.seg.update(results_mask) 和 self.box.update(results_box) 更新 Metric 实例的状态。self.seg.update(results_mask)results_box = ap_per_class(tp,conf,pred_cls,target_cls,plot=self.plot,on_plot=self.on_plot,save_dir=self.save_dir,names=self.names,prefix="Box",)[2:]self.box.nc = len(self.names)self.box.update(results_box)# 定义了一个名为 keys 的属性装饰器,返回一个列表,包含用于访问特定指标的键。@propertydef keys(self):"""Returns a list of keys for accessing metrics."""return ["metrics/precision(B)","metrics/recall(B)","metrics/mAP50(B)","metrics/mAP50-95(B)","metrics/precision(M)","metrics/recall(M)","metrics/mAP50(M)","metrics/mAP50-95(M)",]# 定义了一个名为 mean_results 的方法,计算并返回模型的平均精确度、召回率、mAP@0.5 和 mAP@0.5-0.95,分别针对边界框和掩码。def mean_results(self):"""Return the mean metrics for bounding box and segmentation results."""return self.box.mean_results() + self.seg.mean_results()# 定义了一个名为 class_result 的方法,返回特定类别的性能评估结果,分别针对边界框和掩码。def class_result(self, i):"""Returns classification results for a specified class index."""return self.box.class_result(i) + self.seg.class_result(i)# 定义了一个名为 maps 的属性装饰器,返回每个类别的 mAP 分数,分别针对边界框和掩码。@propertydef maps(self):"""Returns mAP scores for object detection and semantic segmentation models."""return self.box.maps + self.seg.maps# 定义了一个名为 fitness 的属性装饰器,返回模型的适应度,分别针对边界框和掩码。@propertydef fitness(self):"""Get the fitness score for both segmentation and bounding box models."""return self.seg.fitness() + self.box.fitness()# 定义了一个名为 ap_class_index 的属性装饰器,返回每个类别的 AP 索引。@propertydef ap_class_index(self):"""Boxes and masks have the same ap_class_index."""return self.box.ap_class_index# 定义了一个名为 results_dict 的属性装饰器,返回一个字典,包含计算出的性能指标和统计数据。@propertydef results_dict(self):"""Returns results of object detection model for evaluation."""return dict(zip(self.keys + ["fitness"], self.mean_results() + [self.fitness]))# 定义了一个名为 curves 的属性装饰器,返回一个列表,包含用于访问特定度量曲线的曲线名称。@propertydef curves(self):"""Returns a list of curves for accessing specific metrics curves."""return ["Precision-Recall(B)","F1-Confidence(B)","Precision-Confidence(B)","Recall-Confidence(B)","Precision-Recall(M)","F1-Confidence(M)","Precision-Confidence(M)","Recall-Confidence(M)",]# 定义了一个名为 curves_results 的属性装饰器,返回一个字典,包含计算出的性能指标和统计数据。@propertydef curves_results(self):"""Returns dictionary of computed performance metrics and statistics."""return self.box.curves_results + self.seg.curves_results
# 这个类提供了一个完整的框架来计算和存储目标检测和语义分割模型的性能指标,包括精确度、召回率、F1分数和平均精度。它还提供了方法来绘制度量曲线和返回性能指标的字典。

20.class PoseMetrics(SegmentMetrics): 

# 这段代码定义了一个名为 PoseMetrics 的类,它继承自 SegmentMetrics 类。 PoseMetrics 类的实例用于计算和存储目标检测(bounding box)和姿态估计(pose)模型的性能指标。
class PoseMetrics(SegmentMetrics):# 计算并汇总给定类集的检测和姿势指标。# 方法:# process(tp_m、tp_b、conf、pred_cls、target_cls):处理给定预测集的指标。# mean_results():返回所有类别的检测和分割指标的平均值。# class_result(i):返回类“i”的检测和分割指标。# map:返回 IoU 阈值的平均平均精度 (mAP) 分数,范围从 0.50 到 0.95。# fitness:返回适应度分数,即指标的单一加权组合。# ap_class_index:返回用于计算平均精度 (AP) 的类索引列表。# results_dict:返回包含所有检测和分割指标以及适应度分数的字典。"""Calculates and aggregates detection and pose metrics over a given set of classes.Args:save_dir (Path): Path to the directory where the output plots should be saved. Default is the current directory.plot (bool): Whether to save the detection and segmentation plots. Default is False.on_plot (func): An optional callback to pass plots path and data when they are rendered. Defaults to None.names (list): List of class names. Default is an empty list.Attributes:save_dir (Path): Path to the directory where the output plots should be saved.plot (bool): Whether to save the detection and segmentation plots.on_plot (func): An optional callback to pass plots path and data when they are rendered.names (list): List of class names.box (Metric): An instance of the Metric class to calculate box detection metrics.pose (Metric): An instance of the Metric class to calculate mask segmentation metrics.speed (dict): Dictionary to store the time taken in different phases of inference.Methods:process(tp_m, tp_b, conf, pred_cls, target_cls): Processes metrics over the given set of predictions.mean_results(): Returns the mean of the detection and segmentation metrics over all the classes.class_result(i): Returns the detection and segmentation metrics of class `i`.maps: Returns the mean Average Precision (mAP) scores for IoU thresholds ranging from 0.50 to 0.95.fitness: Returns the fitness scores, which are a single weighted combination of metrics.ap_class_index: Returns the list of indices of classes used to compute Average Precision (AP).results_dict: Returns the dictionary containing all the detection and segmentation metrics and fitness score."""# 定义了 PoseMetrics 类的构造函数,它接受以下参数 :# 1.save_dir (默认为当前目录):保存图表和结果的目录。# 2.plot (默认为 False ):是否绘制度量曲线。# 3.on_plot (默认为 None ):一个可选的回调函数,用于在图表渲染后传递图表路径和数据。# 4.names (默认为空元组):类别的名称,用于图表上的图例。def __init__(self, save_dir=Path("."), plot=False, on_plot=None, names=()) -> None:"""Initialize the PoseMetrics class with directory path, class names, and plotting options."""# 调用父类 SegmentMetrics 的构造函数来初始化继承的属性。super().__init__(save_dir, plot, names)# 将构造函数的参数赋值给实例变量。self.save_dir = save_dirself.plot = plotself.on_plot = on_plotself.names = names# 创建两个 Metric 类的实例,分别用于存储和计算 目标检测 和 姿态估计 的性能指标。self.box = Metric()self.pose = Metric()# 初始化一个字典来存储不同处理阶段的速度。self.speed = {"preprocess": 0.0, "inference": 0.0, "loss": 0.0, "postprocess": 0.0}# 设置任务类型为 "pose"。self.task = "pose"# 定义了一个名为 process 的方法,用于处理预测结果并更新目标检测和姿态估计的指标。# 1.tp :真实阳性边界框数组。# 2.tp_p :真实阳性关键点数组。# 3.conf :置信度数组。# 4.pred_cls :预测类别数组。# 5.target_cls :目标类别数组。def process(self, tp, tp_p, conf, pred_cls, target_cls):"""Processes the detection and pose metrics over the given set of predictions.Args:tp (list): List of True Positive boxes.tp_p (list): List of True Positive keypoints.conf (list): List of confidence scores.pred_cls (list): List of predicted classes.target_cls (list): List of target classes."""# results_pose = ap_per_class(...) 和 results_box = ap_per_class(...) 调用 ap_per_class 函数计算每个类别的 AP 值和其他指标,分别针对关键点和边界框。results_pose = ap_per_class(tp_p,conf,pred_cls,target_cls,plot=self.plot,on_plot=self.on_plot,save_dir=self.save_dir,names=self.names,prefix="Pose",)[2:]self.pose.nc = len(self.names)# self.pose.update(results_pose) 和 self.box.update(results_box) 更新 Metric 实例的状态。self.pose.update(results_pose)results_box = ap_per_class(tp,conf,pred_cls,target_cls,plot=self.plot,on_plot=self.on_plot,save_dir=self.save_dir,names=self.names,prefix="Box",)[2:]self.box.nc = len(self.names)self.box.update(results_box)# 定义了一个名为 keys 的属性装饰器,返回一个列表,包含用于访问特定指标的键。@propertydef keys(self):"""Returns list of evaluation metric keys."""return ["metrics/precision(B)","metrics/recall(B)","metrics/mAP50(B)","metrics/mAP50-95(B)","metrics/precision(P)","metrics/recall(P)","metrics/mAP50(P)","metrics/mAP50-95(P)",]# 定义了一个名为 mean_results 的方法,计算并返回模型的平均精确度、召回率、mAP@0.5 和 mAP@0.5-0.95,分别针对边界框和关键点。def mean_results(self):"""Return the mean results of box and pose."""return self.box.mean_results() + self.pose.mean_results()# 定义了一个名为 class_result 的方法,返回特定类别的性能评估结果,分别针对边界框和关键点。def class_result(self, i):"""Return the class-wise detection results for a specific class i."""return self.box.class_result(i) + self.pose.class_result(i)# 定义了一个名为 maps 的属性装饰器,返回每个类别的 mAP 分数,分别针对边界框和关键点。@propertydef maps(self):"""Returns the mean average precision (mAP) per class for both box and pose detections."""return self.box.maps + self.pose.maps# 定义了一个名为 fitness 的属性装饰器,返回模型的适应度,分别针对边界框和关键点。@propertydef fitness(self):"""Computes classification metrics and speed using the `targets` and `pred` inputs."""return self.pose.fitness() + self.box.fitness()# 定义了一个名为 curves 的属性装饰器,返回一个列表,包含用于访问特定度量曲线的曲线名称。@propertydef curves(self):"""Returns a list of curves for accessing specific metrics curves."""return ["Precision-Recall(B)","F1-Confidence(B)","Precision-Confidence(B)","Recall-Confidence(B)","Precision-Recall(P)","F1-Confidence(P)","Precision-Confidence(P)","Recall-Confidence(P)",]# 定义了一个名为 curves_results 的属性装饰器,返回一个字典,包含计算出的性能指标和统计数据。@propertydef curves_results(self):"""Returns dictionary of computed performance metrics and statistics."""return self.box.curves_results + self.pose.curves_results
# 这个类提供了一个完整的框架来计算和存储目标检测和姿态估计模型的性能指标,包括精确度、召回率、F1分数和平均精度。它还提供了方法来绘制度量曲线和返回性能指标的字典。

21.class ClassifyMetrics(SimpleClass): 

# 这段代码定义了一个名为 ClassifyMetrics 的类,它继承自 SimpleClass 。 ClassifyMetrics 类的实例用于计算和存储分类模型的性能指标。
class ClassifyMetrics(SimpleClass):# 用于计算分类指标的类,包括 top-1 和 top-5 准确度。# 方法:# process(targets, pred):处理目标和预测以计算分类指标。"""Class for computing classification metrics including top-1 and top-5 accuracy.Attributes:top1 (float): The top-1 accuracy.top5 (float): The top-5 accuracy.speed (Dict[str, float]): A dictionary containing the time taken for each step in the pipeline.fitness (float): The fitness of the model, which is equal to top-5 accuracy.results_dict (Dict[str, Union[float, str]]): A dictionary containing the classification metrics and fitness.keys (List[str]): A list of keys for the results_dict.Methods:process(targets, pred): Processes the targets and predictions to compute classification metrics."""# 定义了 ClassifyMetrics 类的构造函数,它不接受任何参数,除了 self 。def __init__(self) -> None:"""Initialize a ClassifyMetrics instance."""# self.top1 = 0 和 self.top5 = 0 初始化两个变量来存储 top-1 和 top-5 准确率。self.top1 = 0self.top5 = 0# 初始化一个字典来存储不同处理阶段的速度。self.speed = {"preprocess": 0.0, "inference": 0.0, "loss": 0.0, "postprocess": 0.0}# 设置任务类型为 "classify"。self.task = "classify"# 定义了一个名为 process 的方法,用于处理真实标签(1.targets)和预测标签(2.pred)。def process(self, targets, pred):"""Target classes and predicted classes."""# 将 预测 和 标签的列表 连接成单个张量。pred, targets = torch.cat(pred), torch.cat(targets)# 计算预测和标签是否匹配,并转换为浮点数。correct = (targets[:, None] == pred).float()# 计算 top-1 和 top-5 准确率。acc = torch.stack((correct[:, 0], correct.max(1).values), dim=1)  # (top1, top5) accuracy# 计算平均准确率并转换为列表。self.top1, self.top5 = acc.mean(0).tolist()# 定义了一个名为 fitness 的属性装饰器,返回 top-1 和 top-5 准确率的平均值作为适应度分数。@propertydef fitness(self):"""Returns mean of top-1 and top-5 accuracies as fitness score."""return (self.top1 + self.top5) / 2# 定义了一个名为 results_dict 的属性装饰器,返回一个包含模型性能指标和适应度分数的字典。@propertydef results_dict(self):"""Returns a dictionary with model's performance metrics and fitness score."""return dict(zip(self.keys + ["fitness"], [self.top1, self.top5, self.fitness]))# 定义了一个名为 keys 的属性装饰器,返回一个列表,包含用于 results_dict 属性的键。@propertydef keys(self):"""Returns a list of keys for the results_dict property."""return ["metrics/accuracy_top1", "metrics/accuracy_top5"]# @property def curves(self): 和 @property def curves_results(self): 定义了两个属性装饰器,返回空列表,表示没有特定的度量曲线。@propertydef curves(self):"""Returns a list of curves for accessing specific metrics curves."""return []@propertydef curves_results(self):"""Returns a list of curves for accessing specific metrics curves."""return []
# 这个类提供了一个框架来计算和存储分类模型的性能指标,包括 top-1 和 top-5 准确率,并提供了方法来获取性能指标的字典和适应度分数。

22.class OBBMetrics(SimpleClass): 

# 这段代码定义了一个名为 OBBMetrics 的类,它继承自 SimpleClass 。 OBBMetrics 类的实例用于计算和存储面向对象检测(Oriented Bounding Box,OBB)模型的性能指标。
class OBBMetrics(SimpleClass):"""Metrics for evaluating oriented bounding box (OBB) detection, see https://arxiv.org/pdf/2106.06072.pdf."""# 定义了 OBBMetrics 类的构造函数,它接受以下参数 :# 1.save_dir (默认为当前目录):保存图表和结果的目录。# 2.plot (默认为 False ):是否绘制度量曲线。# 3.on_plot (默认为 None ):一个可选的回调函数,用于在图表渲染后传递图表路径和数据。# 4.names (默认为空元组):类别的名称,用于图表上的图例。def __init__(self, save_dir=Path("."), plot=False, on_plot=None, names=()) -> None:"""Initialize an OBBMetrics instance with directory, plotting, callback, and class names."""# 将构造函数的参数赋值给实例变量。self.save_dir = save_dirself.plot = plotself.on_plot = on_plotself.names = names# 创建一个 Metric 类的实例,用于存储和计算性能指标。self.box = Metric()# 初始化一个字典来存储不同处理阶段的速度。self.speed = {"preprocess": 0.0, "inference": 0.0, "loss": 0.0, "postprocess": 0.0}# 定义了一个名为 process 的方法,用于处理预测结果并更新指标。•# 1.tp :真实阳性数组。# 2.conf :置信度数组。# 3.pred_cls :预测类别数组。# 4.target_cls :目标类别数组。def process(self, tp, conf, pred_cls, target_cls):"""Process predicted results for object detection and update metrics."""# 调用 ap_per_class 函数计算每个类别的 AP 值和其他指标。results = ap_per_class(tp,conf,pred_cls,target_cls,plot=self.plot,save_dir=self.save_dir,names=self.names,on_plot=self.on_plot,)[2:]self.box.nc = len(self.names)# 更新 Metric 实例的状态。self.box.update(results)# 定义了一个名为 keys 的属性装饰器,返回一个列表,包含用于访问特定指标的键。@propertydef keys(self):"""Returns a list of keys for accessing specific metrics."""return ["metrics/precision(B)", "metrics/recall(B)", "metrics/mAP50(B)", "metrics/mAP50-95(B)"]# 定义了一个名为 mean_results 的方法,计算并返回模型的平均精确度、召回率、mAP@0.5 和 mAP@0.5-0.95。def mean_results(self):"""Calculate mean of detected objects & return precision, recall, mAP50, and mAP50-95."""return self.box.mean_results()# 定义了一个名为 class_result 的方法,返回特定类别的性能评估结果。def class_result(self, i):"""Return the result of evaluating the performance of an object detection model on a specific class."""return self.box.class_result(i)# 定义了一个名为 maps 的属性装饰器,返回每个类别的 mAP 分数。@propertydef maps(self):"""Returns mean Average Precision (mAP) scores per class."""return self.box.maps# 定义了一个名为 fitness 的属性装饰器,返回模型的适应度。@propertydef fitness(self):"""Returns the fitness of box object."""return self.box.fitness()# 定义了一个名为 ap_class_index 的属性装饰器,返回每个类别的 AP 索引。@propertydef ap_class_index(self):"""Returns the average precision index per class."""return self.box.ap_class_index# 定义了一个名为 results_dict 的属性装饰器,返回一个字典,包含计算出的性能指标和统计数据。@propertydef results_dict(self):"""Returns dictionary of computed performance metrics and statistics."""return dict(zip(self.keys + ["fitness"], self.mean_results() + [self.fitness]))# 定义了一个名为 curves 的属性装饰器,返回一个空列表,表示没有特定的度量曲线。@propertydef curves(self):"""Returns a list of curves for accessing specific metrics curves."""return []# 定义了一个名为 curves_results 的属性装饰器,返回一个空列表,表示没有特定的度量曲线结果。@propertydef curves_results(self):"""Returns a list of curves for accessing specific metrics curves."""return []
# 这个类提供了一个完整的框架来计算和存储面向对象检测模型的性能指标,包括精确度、召回率、F1分数和平均精度。它还提供了方法来绘制度量曲线和返回性能指标的字典。

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com