首页 > 其他分享 >YOLOv6-4.0部分代码阅读笔记-anchor_generator.py

YOLOv6-4.0部分代码阅读笔记-anchor_generator.py

时间:2024-10-28 22:45:26浏览次数:7  
标签:YOLOv6 4.0 generator shift torch 张量 坐标 anchor 锚点

anchor_generator.py

yolov6\assigners\anchor_generator.py

目录

anchor_generator.py

1.所需的库和模块

2.def generate_anchors(feats, fpn_strides, grid_cell_size=5.0, grid_cell_offset=0.5,  device='cpu', is_eval=False, mode='af'): 


1.所需的库和模块

import torch

2.def generate_anchors(feats, fpn_strides, grid_cell_size=5.0, grid_cell_offset=0.5,  device='cpu', is_eval=False, mode='af'): 

# 1. feats:一个列表,包含了模型中每个特征层(feature map)的尺寸。这些尺寸通常由模型的网络结构决定,用于确定在每个特征层上生成锚点的数量和尺寸。
# 2. fpn_strides:一个列表,包含了每个特征层的步幅(stride)。步幅决定了特征图上每个单元对应原始图像的尺寸,这对于将锚点从特征图尺度转换到原始图像尺度至关重要。
# 3. grid_cell_size(默认值为 5.0 ):一个浮点数,表示每个网格单元的尺寸。这个参数用于确定在特征图的每个单元上生成多少个锚点。
# 4. grid_cell_offset(默认值为 0.5 ):一个浮点数,表示网格单元的偏移量。这个参数通常用于确定锚点在特征图单元内的确切位置。
# 5. device(默认值为 'cpu' ):一个字符串,指定了锚点将被生成在哪个设备上,例如 'cpu' 或  'cuda' 。这决定了生成的锚点张量将存储在 CPU 还是 GPU 上。
# 6. is_eval(默认值为 False ):一个布尔值,指示当前是否处于评估(evaluation)模式。在评估模式下,某些参数的处理方式可能会有所不同。
# 7. mode(默认值为 'af' ):一个字符串,指定了生成锚点的模式。 'af' 代表 "anchor-free",表示 YOLOv6 使用无锚(anchor-free)范式。在这种模式下,可能会根据 feature map 的大小自动生成先验框,而不是使用预先定义的锚点集。
def generate_anchors(feats, fpn_strides, grid_cell_size=5.0, grid_cell_offset=0.5,  device='cpu', is_eval=False, mode='af'):    # grid_cell网格单元
    # 根据特征生成锚点。
    '''Generate anchors from features.'''
    anchors = []
    anchor_points = []
    stride_tensor = []
    num_anchors_list = []
    assert feats is not None    # 如果有特征图。    feats :指的是特征图(feature maps)。
    if is_eval:
        for i, stride in enumerate(fpn_strides):
            _, _, h, w = feats[i].shape
            # torch.arange(start=0, end, step=1, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) -> Tensor
            # 返回大小为(end-start)/strp的一维张量,其值介于区间 [ start , end ),以 step 为步长等间隔取值。
            # dtype :期望的返回张量的数据类型。
            # device :返回张量的期望设备。

            # 1. torch.arange(end=w) :生成一个从0到 w-1 的一维张量,其中 w 是特征图的宽度。这个张量将被用作特征图上每个单元格的x坐标。
            # 2. device :指定了生成的张量应该位于哪个设备上(例如,CPU或GPU)。这样可以确保计算可以在正确的设备上执行,从而提高性能。
            # 3. + grid_cell_offset :将 grid_cell_offset 加到每个x坐标上。 grid_cell_offset 可能是一个偏移量,用于将网格点的坐标从网格单元的中心移动到网格单元的左上角或其他位置。这个偏移量通常用于确保预测的边界框坐标与实际的边界框坐标对齐。
            # 最终, shift_x 将包含特征图上每个单元格的x坐标,这些坐标可以用于计算边界框的中心点坐标。
            # 在目标检测模型中,通常会对特征图的每个维度(宽度和高度)都生成这样的坐标,然后使用 torch.meshgrid 函数将它们组合成一个二维网格。
            shift_x = torch.arange(end=w, device=device) + grid_cell_offset    # shift_x 将包含特征图上每个单元格的x坐标,这些坐标可以用于计算边界框的中心点坐标。
            shift_y = torch.arange(end=h, device=device) + grid_cell_offset    # 同上, shift_y 将包含特征图上每个单元格的y坐标,这些坐标可以用于计算边界框的中心点坐标。
            # torch.meshgrid(*tensors, indexing='xy') -> Sequence[Tensor]
            # torch.meshgrid   函数用于创建一个坐标网格。这个函数的主要用途是在多维空间中生成一个坐标矩阵,这在图像处理、机器学习模型的输入数据准备等方面非常有用。
            # tensors :一个或多个张量,它们将被用来生成网格。
            # indexing :指定索引的顺序,可以是'xy'(笛卡尔坐标系,默认值)或'ij'(矩阵索引)。
            # 输出 :两个 tensor 数据(两个tensor的行数为第一个输入张量的元素个数,列数为第二个输入张量的元素个数)。
            # 1. 参数 indexing='‘ij’'时:
            # 当两个输入tensor数据类型不同或维度不是一维时会报错。其中第一个输出张量填充第一个输入张量中的元素,各行元素相同;第二个输出张量填充第二个输入张量中的元素,各列元素相同。
            # 2. 参数 indexing='‘xy’'时:
            # 则输出两个 tensor 的第一个维度对应于第二个输入的元素个数,第二个维度对应于第一个输入的元素个数。
            # 其中第一个输出张量填充第一个输入张量中的元素,各列元素相同;第二个输出张量填充第二个输入张量中的元素,各行元素相同,与 indexing='‘ij’' 输出结果情况相反。

            # 当使用 torch.meshgrid 函数来组合 shift_x 和 shift_y 时,你实际上是在创建一个坐标网格,这个网格可以用来索引特征图上的每个位置。这个网格对于计算边界框的预测是非常有用的,因为它允许模型为每个单元格生成多个边界框预测。
            # 在YOLOv6中,这些坐标可能还会加上一个偏移量( grid_cell_offset ),以确保边界框的中心点与实际目标的中心对齐。这个偏移量通常是单元格大小的一半,因为特征图的坐标通常是从每个单元格的左上角开始计算的。
            shift_y, shift_x = torch.meshgrid(shift_y, shift_x)
            # torch.stack(tensors, dim=0, out=None) → Tensor
            # torch.stack 函数用于将一系列张量沿着一个新的维度连接起来。与 torch.cat (concatenate)不同, torch.stack 会创建一个新的维度来存放输入张量,而不是在已有的维度上进行连接。
            # tensors :一个序列(如元组或列表)的张量,它们需要有相同的形状。
            # dim :沿着哪个维度堆叠张量。默认为0,表示在最前面添加一个新的维度。
            # out :一个可选的张量,用于存储输出结果。
            # 返回值:
            # 返回一个新的张量,它是输入张量沿着 dim 维度堆叠的结果。
            anchor_point = torch.stack(
                    [shift_x, shift_y], axis=-1).to(torch.float)
            # 这一行检查一个名为 mode 的变量是否等于字符串 'af' 。这可能是一个标志,用来指示当前处理的是与“anchor free”(无锚点)相对的“anchor based”(基于锚点)的方法。
            if mode == 'af': # anchor-free    无锚框
                # anchor_points.append(anchor_point.reshape([-1, 2])):  
                #  这里, anchor_point 是一个张量,它包含了在当前特征图上的锚点坐标。 reshape([-1, 2]) 将 anchor_point 张量重塑为一个二维张量,其中 -1 表示让PyTorch自动计算这一维度的大小,以便保持总元素数量不变。 2 表示每个锚点有两个坐标(通常是x和y坐标)。
                # 然后,这个重塑后的张量被添加到  anchor_points 列表中。
                anchor_points.append(anchor_point.reshape([-1, 2]))
                # torch.full(size, fill_value, *, out=None, dtype=None, layout=torch.strided, device=None, requires_grad=False) → Tensor
                # 返回创建 size 大小的维度,里面元素全部填充为 fill_value 。

                # 这里, torch.full 创建了一个填充有特定值 stride 的新张量。 h * w 计算了特征图上的单元格数量, stride 是当前特征图的步长,表示特征图上每个单元格对应原始图像上的大小。
                # 这个新创建的张量的形状是 (h * w, 1) ,其中 h 和 w 分别是特征图的高度和宽度。 dtype=torch.float 指定了张量的数据类型为浮点数, device 参数确保张量被创建在正确的设备上(例如CPU或GPU)。然后,这个张量被添加到 stride_tensor 列表中。

                # 这段代码是在构建一个目标检测模型的特征图上锚点和步长的表示,这将用于后续的边界框(bounding box)预测。
                stride_tensor.append(
                torch.full(
                    (h * w, 1), stride, dtype=torch.float, device=device))
            elif mode == 'ab': # anchor-based    基于锚框
                anchor_points.append(anchor_point.reshape([-1, 2]).repeat(3,1))    # 如果基于锚框,则需要将锚框重复3遍。
                stride_tensor.append(
                    torch.full(
                        (h * w, 1), stride, dtype=torch.float, device=device).repeat(3,1))
        # anchor_points 是一个包含多个张量的列表,每个张量都包含了特定特征图层上所有锚点(anchor points)的坐标。这些锚点用于定义在特征图的每个位置可能存在的边界框的中心。
        anchor_points = torch.cat(anchor_points)
        stride_tensor = torch.cat(stride_tensor)
        # 2. anchor_points : 这是一个张量,包含了所有特征图层上每个单元格的中心点坐标。这些坐标用于确定锚点的中心位置,通常用于anchor-free的检测方法中。每个点由两个值组成: (x_center, y_center) 。
        # 4. stride_tensor : 这是一个张量,包含了每个特征图层的步长(stride)。步长定义了特征图上每个单元格对应于输入图像的实际像素大小。这个信息对于将特征图坐标转换为原始图像坐标至关重要。
        return anchor_points, stride_tensor
    else:    # 没有特征图。
        for i, stride in enumerate(fpn_strides):
            _, _, h, w = feats[i].shape
            cell_half_size = grid_cell_size * stride * 0.5
            # 1. torch.arange(end=w, device=device) : 这个函数生成一个从0到 w-1 的一维张量,其中 w  是特征图的宽度。 device 参数确保张量被创建在正确的设备上(例如CPU或GPU)。
            # 2.  + grid_cell_offset : grid_cell_offset 是一个偏移量,用于将网格点的坐标从网格单元的中心移动到网格单元的左上角或其他位置。 这个偏移量通常用于确保预测的边界框坐标与实际的边界框坐标对齐。
            # 3. * stride : stride 是特征图的步长,表示特征图上每个单元格对应原始图像上的大小。 将偏移后的坐标乘以步长,将特征图的坐标转换为原始图像的坐标。
            # 最终, shift_x 将包含特征图上每个单元格的中心点的x坐标,这些坐标可以用于计算边界框的中心点坐标。在目标检测模型中,通常会对特征图的每个维度(宽度和高度)都生成这样的坐标,然后使用  torch.meshgrid  函数将它们组合成一个二维网格。
            shift_x = (torch.arange(end=w, device=device) + grid_cell_offset) * stride    # shift_x 将包含特征图上每个单元格的中心点的x坐标。
            shift_y = (torch.arange(end=h, device=device) + grid_cell_offset) * stride    # 同理,shift_y 将包含特征图上每个单元格的中心点的y坐标。
            # 当使用 torch.meshgrid 函数来组合 shift_x 和 shift_y 时,你实际上是在创建一个坐标网格,这个网格可以用来索引特征图上的每个位置。这个网格对于计算边界框的预测是非常有用的,因为它允许模型为每个单元格生成多个边界框预测。
            shift_y, shift_x = torch.meshgrid(shift_y, shift_x)
            anchor = torch.stack(
                [
                    shift_x - cell_half_size, shift_y - cell_half_size,
                    shift_x + cell_half_size, shift_y + cell_half_size
                ],
                axis=-1).clone().to(feats[0].dtype)
            # 生成锚框。
            anchor_point = torch.stack(
                [shift_x, shift_y], axis=-1).clone().to(feats[0].dtype)

            if mode == 'af': # anchor-free    无锚框
                # 在"anchor free"模式下,每个锚点 anchor 被重塑为 [-1, 4] 的形状,其中 -1 表示自动计算行数以保持总元素数量不变, 4 表示每个锚点有四个坐标(通常是边界框的x、y、宽度和高度)。
                # 同样,每个锚点位置 anchor_point 被重塑为 [-1, 2] 的形状,其中 2 表示每个锚点位置有两个坐标(通常是x和y坐标)。
                # 些重塑后的张量被添加到 anchors 和 anchor_points 列表中。
                anchors.append(anchor.reshape([-1, 4]))
                anchor_points.append(anchor_point.reshape([-1, 2]))
            elif mode == 'ab': # anchor-based    基于锚框    "anchor based"(AB)
                # 在"anchor based"模式下,每个锚点 anchor 同样被重塑为 [-1, 4] 的形状,但随后使用 .repeat(3,1) 在第一个维度(锚点数量)上重复3次。这意味着每个锚点被复制3次,通常是为了适应不同尺度或比例的边界框。
                # 同样,每个锚点位置 anchor_point 被重塑为 [-1, 2] 的形状,并使用 .repeat(3,1) 在第一个维度上重复3次。
                # 这些重复后的张量被添加到 anchors 和 anchor_points 列表中。
                anchors.append(anchor.reshape([-1, 4]).repeat(3,1))    # 如果基于锚框,则需要将锚点重复3遍。
                anchor_points.append(anchor_point.reshape([-1, 2]).repeat(3,1))
            num_anchors_list.append(len(anchors[-1]))
            stride_tensor.append(
                torch.full(
                    [num_anchors_list[-1], 1], stride, dtype=feats[0].dtype)) 
        anchors = torch.cat(anchors)
        anchor_points = torch.cat(anchor_points).to(device)
        stride_tensor = torch.cat(stride_tensor).to(device)
        # 1. anchors : 这是一个张量,包含了所有特征图层上每个单元格的锚点的宽度和高度。在YOLOv6中,由于采用了anchor-free的设计,这些锚点可能是动态生成的,而不是预先定义的。
            # 每个锚点通常由四个值组成: (x_center, y_center, width, height) ,其中  (x_center, y_center)  是锚点的中心坐标, width 和 height 是锚点的宽度和高度。
        # 2. anchor_points : 这是一个张量,包含了所有特征图层上每个单元格的中心点坐标。这些坐标用于确定锚点的中心位置,通常用于anchor-free的检测方法中。每个点由两个值组成: (x_center, y_center) 。
        # 3. num_anchors_list : 这是一个列表,包含了每个特征图层上每个单元格的锚点数量。在多尺度特征图层中,不同的层可能有不同的锚点数量,这个列表记录了这些信息。
        # 4. stride_tensor : 这是一个张量,包含了每个特征图层的步长(stride)。步长定义了特征图上每个单元格对应于输入图像的实际像素大小。这个信息对于将特征图坐标转换为原始图像坐标至关重要。
        return anchors, anchor_points, num_anchors_list, stride_tensor

标签:YOLOv6,4.0,generator,shift,torch,张量,坐标,anchor,锚点
From: https://blog.csdn.net/m0_58169876/article/details/143315729

相关文章

  • YOLOv6-4.0部分代码阅读笔记-assigner_utils.py
    assigner_utils.pyyolov6\assigners\assigner_utils.py目录assigner_utils.py1.所需的库和模块2.defdist_calculator(gt_bboxes,anchor_bboxes): 3.defselect_candidates_in_gts(xy_centers,gt_bboxes,eps=1e-9): 4.defselect_highest_overlaps(mask_pos,overl......
  • 给虚拟机挂载一块硬盘(以ubuntu24.04为例)
    一、新增、分区、格式化新盘1、首先在虚拟机中增加一块新硬盘(500G)例如:Vmware、Exsi软件,增加完成后,查看一下:root@ubuntu:~#lsblk-fNAMEFSTYPEFSVERLABELUUIDFSAVAILFSUSE%MOUNTPOINTSsda......
  • ubuntu24.04安装完以后发现硬盘空间少一半
    1、查看现在硬盘情况root@ubuntu:~#df-hFilesystemSizeUsedAvailUse%Mountedontmpfs1.6G1.1M1.6G1%/runefivarfs256K64K188K26%/sys/firmware/efi/efivars/dev......
  • VS2022 添加旧版本.NET Framework 3.5/4.0支持
    鉴于vs2022最旧只支持到.netframework4.6.2有些项目.netframework版本比较低,又想要用新版本vs以3.5为例要使vs2022支持低版本.netframework项目,可参考以下步骤实现下载.netframeworknuget包下载链接如下,可根据需要下载对应版本v3.5v4.0v4.5修改后缀为zip或直接......
  • chatGpt4.0Plus,Claude3最新保姆级教程开通升级
     如何使用WildCard服务注册Claude3随着Claude3的震撼发布,最强AI模型的桂冠已不再由GPT-4独揽。Claude3推出了三个备受瞩目的模型:Claude3Haiku、Claude3Sonnet以及Claude3Opus,每个模型都展现了卓越的性能与特色。其中,Claude3Opus更是实现了对GPT-4的全......
  • Redis4.0.12集群搭建
    服务器:节点1:10.10.175.55 端口:6379/7379节点2:10.10.175.56 端口:6379/7379节点3:10.10.175.57 端口:6379/7379以下操作均需在每台服务器上执行安装依赖关系yuminstallmakezlibopenssl*ImageMagick-develgcc*rubygems-y2、创建节点目录mkdir-p/usr/local/redis-cl......
  • 使用RazorGenerator.MsBuild自定义razor页
    创建控制台项目使用类库项目,.netstandard.2.0nuget安装RazorGenerator.MsBuild这样在项目的packages目录能看到RazorGenerator.MsBuild.2.5.0razor页类定义namespaceRazorLib{publicabstractclassRazorPage{publicvirtualvoidExecute()......
  • IObit Uninstaller Pro v14.0.0.17 解锁版 (强悍的驱动级软件卸载)
    IObitUninstallerProv14.0.0.17解锁版(强悍的驱动级软件卸载)IObitUninstaller,软件卸载程序。IObitUninstaller是款强悍的驱动级软件卸载工具,有强制卸载、批量卸载、安装监视器、文件粉碎、软件健康检查、卸载Windows更新补丁、移除浏览器工具栏和插件等功能。一、下载地址链......
  • koa2 入门(1)koa-generator 脚手架和 mongoose 使用
    koa2入门(1)koa-generator脚手架和mongoose使用 项目地址:https://github.com/caochangkui/demo/tree/koa2-learn1构建项目1.1安装koa-generator$npminstall-gkoa-generator1.2使用koa-generator生成koa2项目$koa2-eproject(项目名称)(-e代表使用模板引......
  • 自动执行generator生成器函数
    自动执行generator函数◼目前我们的写法有两个问题:第一,我们不能确定到底需要调用几层的Promise关系;第二,如果还有其他需要这样执行的函数,我们应该如何操作呢?◼所以,我们可以封装一个工具函数execGenerator自动执行生成器函数<script>//封装一个请求方法......