YOLOE

15 downloads 0 likes on ModelScope updated

Model card

YOLOE

1. 摘要

  1. 身份编号:fwb0042

  2. 类型与序号:YOLOE 方案1

  3. 进展:

    item status detail
    方案选择与硬件资源划分 1
    模型导出 1
    ~导出模型精度一致,提供python验证脚本 1
    cpu处理部分c++工程移植 0
    ~c++工程精度一致,提供验证脚本 0
    ~c++工程性能优化 0
    icraft编译通过 0 算子不支持
    ~存在量化精度调优工作 0
    ~完成基本pyrtcrt搭建与结果验证 0
    ~完成pyrtcrt精度测试与对齐 0
    完成上板耗时测试 0
    ~使用运行时提供的api进行基本性能优化 0
    ~存在整体方案各环节优化或优化方案的设计 0
    提出bug数 0

2. 方案简介

2.1 算法流程介绍

模型或算法背景:

  • YOLOE (You Only Look Once with open prompts, effectively) 是一个高效、统一的开放世界目标检测与分割框架,旨在实现“实时看见任何事物”。
  • 源仓库链接:https://github.com/THU-MIG/yoloe
  • 开发团队:清华大学智能产业研究院(MIG) (Ao Wang, Lihao Liu 等人主导开发)
  • 发布时间:2025年3月 (根据论文arXiv v1版本日期)
  • 性能水平:YOLOE 创新地将多种开放提示机制(文本、视觉、无提示)集成到一个高效模型中。它基于成熟的YOLOv8等架构,通过引入创新的模块,在几乎不增加推理开销的情况下,实现了强大的零样本(zero-shot)检测和分割能力,且训练成本远低于同类方法。
YOLOE在LVIS上的性能

在LVIS数据集上与YOLO-Worldv2的性能对比:

Model 提示类型 Params 训练数据 训练时间 FPS (T4 / iPhone12) AP APr (rare) APc (common) APf (frequent)
YWorldv2-S T 13M OG 41.7h 216.4 / 48.9 24.4 17.1 22.5 27.3
YOLOE-v8-S T / V 12M / 13M OG 12.0h 305.8 / 64.3 27.9 / 26.2 22.3 / 21.3 27.8 / 27.7 29.0 / 25.7
YWorldv2-M T 29M OG 60.0h 117.9 / 34.2 32.4 28.4 29.6 35.5
YOLOE-v8-M T / V 27M / 30M OG 17.0h 156.7 / 41.7 32.6 / 31.0 26.9 / 27.0 31.9 / 31.7 34.4 / 31.1
YWorldv2-L T 48M OG 80.0h 80.0 / 22.1 35.5 25.6 34.6 38.1
YOLOE-v8-L T / V 45M / 50M OG 22.5h 102.5 / 27.2 35.9 / 34.2 33.2 / 33.2 34.8 / 34.6 37.3 / 34.1

注:T/V表示文本/视觉提示。OG表示Objects365和GoldG数据集。

YOLOE与YOLO-Worldv2对比图

算法流程梳理

YOLOE 的整体架构继承了YOLO系列的高效设计,但在其上融入了针对开放世界场景的核心模块,使其能够理解并响应不同形式的提示。

数据输入(图像/提示) ——> 主干网络(Backbone)——> 颈部网络(Neck)——> 头部网络(Head) ——> 开放提示处理 ——> 输出结果

yoloe模型结构

YOLOE在标准的YOLOv8等模型(包含Backbone, PAN, 回归/分割头)的基础上,针对三种开放提示场景,引入了三大核心组件:

1. 文本提示 (Text Prompts): RepRTA (Re-parameterizable Region-Text Alignment)

  • 目的:在不增加推理成本的前提下,提升视觉特征与文本嵌入的对齐质量。
  • 方法:在训练时,使用一个轻量级的辅助网络来优化预先提取好的文本特征(如CLIP embedding)。训练完成后,这个辅助网络的权重可以被无缝地“重参数化”合并到检测头的分类卷积层中。
  • 优势:推理时架构与原始YOLO完全相同,实现了“零开销”的性能提升。

2. 视觉提示 (Visual Prompts): SAVPE (Semantic-Activated Visual Prompt Encoder)

  • 目的:高效地编码视觉提示(如框、点、掩码),并将其转化为与文本提示兼容的嵌入向量。
  • 方法:设计了一个解耦的双分支结构。语义分支提取提示无关的通用语义特征;激活分支则将视觉提示与图像特征进行低成本交互,生成一个“注意力权重”,用以加权聚合语义特征。
  • 优势:避免了复杂的Transformer或额外的视觉编码器,复杂度极低,部署友好。

3. 无提示 (Prompt-Free): LRPC (Lazy Region-Prompt Contrast)

  • 目的:在没有明确指令时,自动检测并识别图像中的所有物体。
  • 方法:将该问题重新定义为一个高效的“检索”任务。首先,使用一个专门训练的、用于“寻找所有物体”的嵌入向量,找出图中所有可能的目标。然后,仅对这些找到的目标,在内置的大型词汇库中进行“懒惰”的对比匹配,从而检索出类别名称。
  • 优势:无需依赖昂贵的大型语言模型进行实时生成,速度极快,实现了高效的“看到一切”。

基本组件: RepRTA:一个可重参数化的文本嵌入优化模块,训练时增强对齐,推理时零成本。 SAVPE:一个解耦的、轻量级的视觉提示编码器,高效且易于部署。 LRPC:一种懒惰对比策略,通过“先找到,后识别”的两阶段方法,高效实现无提示下的全目标检测。

数据集

  • YOLOE的训练主要依赖于大规模的检测和视觉定位数据集,如 Objects365 和 GoldG(包含GQA, Flickr30k等)。
  • 分割数据:利用先进的分割模型(如SAM-2.1)为检测框生成高质量的伪标签(pseudo masks),用于联合训练分割任务。
  • 数据多样性:训练数据覆盖了海量类别,这为模型的强大零样本泛化能力奠定了基础。
  • 提示数据:文本提示直接使用数据集中的类别名;视觉提示使用标注框;无提示场景则将所有物体标注为同一个“物体”类别进行学习。

模型选择

  • YOLOE提供了基于YOLOv8和YOLO11架构的S/M/L多种尺寸模型,用户可根据速度和精度的需求灵活选择。
  • 起点:模型从标准的YOLOv8/v11权重开始,加载其主干和颈部,然后在其上进行开放词汇能力的训练。
  • 适用场景:YOLOE尤其适用于类别多变、需求不固定、需要与用户交互的场景。

前后处理

前处理:

  • 图像处理:与标准YOLO一致,包括读取图像、缩放到模型输入尺寸(如640x640)、归一化、通道转换(HWC to NCHW)等。
  • 提示处理:
    • 文本提示:使用预训练的文本编码器(如MobileCLIP-B)将输入文本转换为嵌入向量。这些向量在训练前可以被缓存,以加速训练。
      from ultralytics import YOLOE
      # Initialize a YOLOE model
      model = YOLOE("yoloe-11l-seg.pt")  # or select yoloe-11s/m-seg.pt for different sizes
      # Set text prompt to detect person and bus. You only need to do this once after you load the model.
      names = ["person", "bus"]
      model.set_classes(names, model.get_text_pe(names))
      # Run detection on the given image
      results = model.predict("path/to/image.jpg")
      # Show results
      results[0].show()
      
    • 视觉提示:将用户输入的框、点等转换为掩码(Mask)格式,送入SAVPE。
      import numpy as np
      
      from ultralytics import YOLOE
      from ultralytics.models.yolo.yoloe import YOLOEVPSegPredictor
      
      # Initialize a YOLOE model
      model = YOLOE("yoloe-11l-seg.pt")
      
      # Define visual prompts using bounding boxes and their corresponding class IDs.
      # Each box highlights an example of the object you want the model to detect.
      visual_prompts = dict(
          bboxes=np.array(
              [
                  [221.52, 405.8, 344.98, 857.54],  # Box enclosing person
                  [120, 425, 160, 445],  # Box enclosing glasses
              ],
          ),
          cls=np.array(
              [
                  0,  # ID to be assigned for person
                  1,  # ID to be assigned for glassses
              ]
          ),
      )
      
      # Run inference on an image, using the provided visual prompts as guidance
      results = model.predict(
          "ultralytics/assets/bus.jpg",
          visual_prompts=visual_prompts,
          predictor=YOLOEVPSegPredictor,
      )
      
      # Show results
      results[0].show()
      
    • 无提示:提前将编码器等信息嵌入到模型中,无需在进行
      from ultralytics import YOLOE
      # Initialize a YOLOE model
      model = YOLOE("yoloe-11l-seg-pf.pt")
      # Run prediction. No prompts required.
      results = model.predict("path/to/image.jpg")
      # Show results
      results[0].show()
      

后处理:

  1. 阈值筛选与NMS:
    • 根据分类得分和置信度筛选高质量的检测框。
    • 应用标准的非极大值抑制(NMS)来消除冗余框。
  2. 无提示检索 (LRPC):
    • 在无提示模式下,后处理分为两步:首先用专用提示Ps找出所有得分超过阈值δ的物体,然后仅对这些物体进行类别词汇库的匹配,极大地降低了计算量。

2.2 硬件资源分配

yolo plin模式:摄像头输入数据直接传给pl部分

前处理:fpga,做在数据流上

网络主体:npu

后处理阈值筛选:fpga

后处理nms:fpga

后处理计算框数值等:cpu

可视化:cpu

4. 模型导出说明

与YOLOV8-SEG类似,在导出的时候,导出到最后一步卷积,将后处理部分去除掉交给更适合的FPGA或者CPU处理进行处理。

def lrpc_head_forward(self, cls_feat, loc_feat, conf):
  if self.enabled:
      pf_score = self.pf(cls_feat)[0, 0].flatten(0)
      mask = pf_score.sigmoid() > conf
      cls_feat = cls_feat.flatten(2).transpose(-1, -2)
      cls_feat = self.vocab(cls_feat[:,mask] if conf else cls_feat * mask.unsqueeze(-1).int())
      return self.loc(loc_feat), cls_feat.transpose(-1, -2), mask
  else:
      cls_feat = self.vocab(cls_feat)
      loc_feat = self.loc(loc_feat)
      return loc_feat, cls_feat.flatten(2), torch.ones(
          cls_feat.shape[2] * cls_feat.shape[3], device=cls_feat.device, dtype=torch.bool
      )
LRPCHead.__call__ = lrpc_head_forward

def yoloe_seg_forward(self, x, cls_pe=None):
  """修改后的前向传播,仅输出卷积层结果(不包含后处理).
  输入:
      x (List[Tensor]): 多尺度特征图 [P3, P4, P5]
      cls_pe (Optional[Tensor]): 文本/视觉提示嵌入 (B, N, D)
  返回:
      Tuple: 所有中间卷积输出(用于 TorchScript 导出)
  """
  # 1. 原型掩码分支
  p = self.proto(x[0])  # shape=(B, nm, H, W)
  masks = []
  # 2. 掩码系数分支(cv5层输出)
  seg_outputs = []
  for i in range(self.nl):
      seg_outputs.append(self.cv5[i](x[i]))  # shape=(B, nm, H, W)
  # 3. 检测分支(cv2/cv3/cv4层输出)
  cls_dfl_outputs = []
  for i in range(self.nl):
      cls_feat = self.cv3[i](x[i])  # 区域特征 (B, embed, H, W)
      loc_feat = self.cv2[i](x[i])  # 定位特征 (B, reg_max*4, H, W)
      assert isinstance(self.lrpc[i], LRPCHead)
      loc_output,cls_output, mask = self.lrpc[i](
          cls_feat, loc_feat, 0 if self.export and not self.dynamic else getattr(self, "conf", 0.001)
      )
      masks.append(mask)
      cls_dfl_outputs.extend([loc_output,cls_output])
  # 合并所有输出(顺序:loc_feat, cls_feat, mask, seg_feat , proto)
  mask = torch.cat(masks)
  outputs = []
  for i in range(self.nl):
      outputs.extend([
          cls_dfl_outputs[2 * i],   # loc_feat (P3)
          cls_dfl_outputs[2 * i + 1],  # cls_feat (P3)
          seg_outputs[i]  # seg_feat (P3)
      ])
  outputs.append(mask)  # 最后追加原型
  outputs.append(p)  # 最后追加原型
    # 最后追加原型
  return tuple(outputs)


YOLOESegment.__call__ = yoloe_seg_forward

5. cpu处理部分c++工程移植说明

暂无实现

6. ICRAFT编译

编译未通过 alt text

不支持点:

  • 算子不支持

    在icraft logs中找到不支持的算子序列、在源码中定位对应的源码、实现的功能

    算子序列 对应源码 实现的功能
    NonZero,Gather alt text mask_select函数

7. 上板测试与优化

  1. 优化前各环节耗时统计(表格)

  2. 优化后耗时统计(表格)

  3. 优化项与效果

    分条描述做了哪些性能优化,提升了多少

  4. 运行时工程的整体介绍(最好带流程图)

8. 人员分工与心得(可选)