Skip to main content
本页介绍当内置 qtimlpostprocess 模块不支持您的模型输出格式时,如何将自定义后处理模块集成到 QIM SDK 管线中。 当您的模型可以使用现有 QIM SDK 推理插件运行,但其输出张量需要经过自定义处理才能转换为标签、边界框、掩码、关键点、原始张量或其他应用特定元数据时,请使用此工作流。本指南以基于 YOLOv8 的目标检测模型作为端到端示例,演示集成过程的每个步骤。
应用开发工作流的步骤 3a。 当接入的新模型输出格式不受任何内置后处理模块支持时,请使用此路径。如果您尚未确认是否需要自定义后处理模块,请先完成步骤 2a。

开始之前

在创建自定义后处理模块之前,请确认满足以下前提条件。只有当所有内置 qtimlpostprocess 模块都无法处理您的模型输出格式时,才需要自定义实现。
一个模块服务于多个模型的情况非常常见。例如,yolov8 模块可处理输出结构相同的多个 YOLO 系列检测器。在断定需要自定义模块之前,请仔细检查报告的张量形状。
下图显示了添加自己的后处理支持的整体流程,从开发和集成模块到运行参考应用程序。 添加自定义后处理支持的流程概览

AI 管线概述

Qualcomm Intelligent Multimedia SDK (QIM SDK) 提供构建 AI、多媒体和计算机视觉管线所需的构建模块。AI 工作流由三个关键的 GStreamer 阶段构成,自定义后处理模块仅扩展第三个阶段。 后处理阶段可以通过以下方式之一输出元数据:
  • 使用 qtimetamuxer 将其附加到源流。
  • 将其直接流式传输到 RTSP、RTMP 或 Redis 等端点。
  • 将其转换为图像掩码,并使用 qtivcomposer 叠加到源视频帧上。
AI IM SDK 管线阶段
您只需负责后处理模块。预处理、推理和元数据使用均为标准 QIM SDK 元素,qtimlpostprocess 插件会围绕您的模块处理批处理、输出格式协商和结果数量限制。

示例:直接使用 ML 元数据

在此示例中,源流在推理插件之后不再传播,元数据被直接使用。 直接使用 ML 元数据的管线

示例:将 ML 元数据附加到源视频

在此示例中,ML 元数据附加到源视频。叠加层使用附加的元数据绘制边界框、文本和其他可视元素。结果显示在屏幕上,或通过网络流式传输。 将 ML 元数据附加到源视频的管线

示例:将 ML 元数据转换为图像掩码

在此示例中,ML 元数据被转换为图像掩码,然后叠加 (blit) 到源流之上。 将 ML 元数据转换为图像掩码的管线

qtimlpostprocess 插件行为

qtimlpostprocess 是一个可自定义的插件,为推理插件的张量输出后处理提供库接口。后处理模块负责张量解析,并生成预测结果列表。 每个后处理模块处理一种类型的 ML 模型及其变体,例如所有 YOLOv8 检测变体。该插件负责管理模块执行、输出生成(ML 元数据、图像掩码或张量)、批处理、ML 暂存以及其他相关任务。 输入、输出、后处理模块与插件之间的关系 该插件接收封装在 GStreamer 缓冲区中的张量列表作为输入。附加到每个缓冲区的 ML 元数据指定了张量数量、张量形状、模型输入张量形状、每个输入张量中有多少被流数据填充、时间戳以及批处理索引。

插件属性

输出格式

输出格式通过 GStreamer 管线协商确定。系统会自动协商最合适的格式,但您也可以使用 GStreamer caps 过滤器手动指定。该插件仅支持一个源 pad,因此如果应用需要同时使用多种输出格式,请在管线中再添加一个 qtimlpostprocess 实例。 该插件支持以下模型类型:
  • 目标检测
  • 图像分类
  • 图像分割
  • 超分辨率
  • 姿态估计
  • 音频分类

编写后处理模块

后处理模块是一个共享库,用于解析推理插件输出的张量。qtimlpostprocess 插件在运行时加载并运行该模块。QIM SDK 提供了种类丰富的开箱即用模块。 在目标设备上运行 gst-inspect-1.0 qtimlpostprocess,可查看支持的模块及其支持的张量形状的完整列表。以下示例显示了部分输出。
如果没有内置模块适合您的模型,请自行实现。模块可以独立于 QIM SDK 构建,您只需要接口头文件和工具链。将模块构建为共享库,复制到设备上的 /usr/lib/imsdk/qtimlpostprocess/modules/,插件会自动检测到它,从而可以在管线中选择该模块。

模块和库命名

为避免名称冲突,模块共享库必须遵循 libml-postprocess-<module-name>.so 命名约定。<module-name> 必须与传递给 qtimlpostprocess module 属性的值一致。例如,YOLOv8 模块命名为 libml-postprocess-yolov8.so,并通过 module=yolov8 选择。

实现后处理模块接口

后处理模块提供 C++ API。由于无法直接从共享库加载 C++ API,类的实例化被封装在一个 C 函数中,该函数已在头文件中实现,您无需自行处理实例化。请在派生自 IModule 接口的模块类中实现以下方法。

使用 Caps() 定义模块能力

Caps() 以 JSON 字符串形式返回模块类型和支持的张量形状。张量维度可以是固定值,也可以使用方括号定义范围。例如,[1, [21, 42840], 4] 表示第二个维度可以在 21 到 42840 之间变化。 以下示例声明了目标检测后处理、FLOAT32 张量格式,以及对一个、两个或三个张量输出的支持。
您可以同时指定多种张量格式,例如 "format": ["FLOAT32", "INT8"]。

使用 Configure() 配置模块设置

使用 Process() 解析张量

张量输出是一种特殊情况,此时插件和模块生成的是张量而非预测结果。仅当两个 ML 模型串联,且第一个模型的输出张量必须经过修改后才能被下一个模型使用时,才使用此方式。如果不需要修改,请直接连接两个推理插件,省略后处理阶段。

了解后处理模块输入

后处理模块输入分为两个字段。 tensors 保存推理输出张量并描述其结构。每个输出张量是向量中的一个条目。例如,YOLOv8 产生三个输出张量(边界框、得分、类别索引)。
  • 类型: float、uint8 等。
  • 名称: 张量名称,当两个或更多输出张量具有相同形状时用于识别。名称是唯一的,可确保选中确切的张量。
  • 维度: 张量形状。例如,具有三个输出张量的 YOLOv8:[1,8400,4]、[1,8400]、[1,8400]。
  • 数据: 指向张量的指针。
mlparams 为张量处理提供附加参数,这些参数不一定适用于所有模块。它描述管线如何处理输入流,当流的分辨率和宽高比与输入张量形状不匹配时非常有用。它是使用 std::any 实现的字典,因此您必须知道预期的键及其返回类型。
支持的键
  • 键:"input-tensor-region"
    类型:video::Region
    描述:指示输入张量中哪一部分由来自流的实际数据填充。其余区域视为填充 (padding)。
  • 键:"input-tensor-dimensions"
    类型:video::Resolution
    描述:指定输入张量的大小。由于模块必须输出相对坐标,当算法生成绝对坐标时,需要使用此值将绝对坐标转换为相对坐标。

生成后处理模块输出

输出是一个由结果数组组成的数组。数组采用嵌套形式以支持批处理;在没有批处理时仅填充内层数组,其大小与找到的结果数量一致。结果始终使用相对尺寸,结果类型取决于模块类型。
  • 图像/音频分类
    • 名称:预测的类别。
    • 置信度:类别概率或置信度得分。
    • 颜色:用于在叠加插件中可视化的 RGBA8888 颜色。
    • Xtraparams:(可选)用于向下游导出任意结果的额外键值对。
  • 目标检测
    • Left、top、right、bottom:边界框坐标。
    • 名称:预测的类别。
    • 特征点:(可选)关键点列表;例如,人脸检测模型可以同时输出人脸关键点和边界框。
    • 置信度:类别概率或置信度得分。
    • 颜色:用于在叠加插件中可视化的 RGBA8888 颜色。
    • Xtraparams:(可选)用于向下游导出任意结果的额外键值对。
  • 姿态估计
    • 名称:预测的类别。
    • 置信度:类别概率或置信度得分。
    • 关键点:关键点向量。
    • 连接:(可选)关键点之间的连接向量。
    • 颜色:用于在叠加插件中可视化的 RGBA8888 颜色。
    • Xtraparams:(可选)用于向下游导出任意结果的额外键值对。
  • 图像分割和超分辨率
    • 输出为图像帧或掩码。
  • 张量
    • 张量列表。

批处理

插件会自动将张量批次拆分为单个张量,因此您无需在模块中处理批处理。例如,如果批大小为 4,则每个批次会自动调用模块四次。

模块辅助工具

接口头文件中包含标签解析器和 JSON 解析器。您不必使用它们,但它们为方便起见而提供。您可以使用任何解析器,但模块必须与其静态链接。
  • 标签解析器: 接收标签文件的路径并自动检测格式。
    • 换行分隔格式:行号即类别 ID。
    • JSON 格式:设置类别索引、标签和可视化颜色。此格式更灵活,因为您可以传递类别的子集,其余类别会被自动过滤掉。
  • JSON 解析器: 解析以 JSON 字符串形式传递的设置。Qualcomm 提供的标签解析器也使用它来解析 JSON 格式的标签。

日志记录

模块可以将日志输出到 GStreamer 日志系统,而无需直接依赖 GStreamer。构造函数会向模块传递一个日志对象,您可以将其与 LOG 宏一起使用。支持的日志级别有 Error、Warning、Info、Debug、Trace 和 Log。

在主机上编译后处理模块

前提条件
  • Ubuntu 22.04 或 Ubuntu 24.04 主机。
1

安装所需工具

3

将 IM SDK 头文件和模块源文件放在同一文件夹中

4

创建 CMakeLists.txt 文件

例如:
后处理模块共享库必须遵循 libml-postprocess-<module-name>.so 命名约定。例如,YOLOv8 模块库应命名为 libml-postprocess-yolov8.so。
5

创建工具链文件

例如,aarch64-toolchain.cmake:
6

配置并构建模块

部署和测试后处理模块

1

在主机上设置用户环境变量

2

将模块部署到目标设备

1

将模块传输到目标设备

在主机的终端中执行:
2

通过 SSH 登录目标设备

在主机的终端中执行:
3

根据提示输入密码

出现提示时,输入密码:oelinux123。
4

以写权限重新挂载 /

5

将模块复制到 GStreamer 插件目录

6

在目标设备上运行 GST inspect

3

下载运行 GStreamer 管线所需的模型、标签和媒体文件

1

创建工件目录

2

下载标签文件

下载 yolox.json,然后将其复制到目标设备。
3

下载媒体文件

下载 video1.mp4,然后将其复制到目标设备。
4

下载模型文件

下载 yolox_quantized.tflite,然后将其复制到目标设备。
4

构建并运行 GStreamer 管线

构建并运行一个 GStreamer 管线,通过 qtimlpostprocess 的 module 属性选择您的模块,并根据需要传递标签文件和设置。在以下运行 YOLO-X 模型的示例管线中:
  • 管线使用离线视频作为源。
  • 使用 v4l2h264dec 解码器将视频解码为 YUV 格式。
  • qtimlvconverter 插件对 YUV 帧进行预处理。
  • qtimltflite 插件使用 LiteRT YOLO-X 模型运行推理。
  • 后处理插件加载 YOLO-X 模块并传递 JSON 标签文件。
  • 管线在 Wayland 上显示结果。
对于 Dragonwing™ IQ-615 和 Dragonwing™ IQ-2390,请将 backend_type 更改为 dsp,因为 hexagon v66 架构不支持 htp backend_type。

故障排除

请按顺序检查以下各项:
  • 库文件名严格遵循 libml-postprocess-<module-name>.so 约定。
  • 库已复制到设备上的 /usr/lib/imsdk/qtimlpostprocess/modules/。
  • 库是使用工具链文件(而非主机编译器)为 aarch64 构建的。
  • 模块导出了 C 兼容的入口点,以便在运行时加载共享库。
Caps() 声明必须与模型实际生成的张量相匹配。将 Caps() 返回的模块类型、张量格式和维度与模型报告的输出张量进行比较,仅在维度确实会变化时才将其放宽为范围。同时确认 module 属性值与库文件名中的 <module-name> 一致。
后处理模块必须输出相对坐标。如果您的算法生成的是绝对坐标,请使用 input-tensor-dimensions 进行转换,并使用 input-tensor-region 考虑填充区域。当宽高比不同时,流通常会以信箱 (letter-box) 方式放入输入张量。
首先验证后处理之前的各个阶段:确认推理正在生成输出张量,然后检查 settings 阈值是否过滤掉了所有结果,以及 results 是否设置得低于预期。在 Process() 中使用 LOG 宏,确认模块正在被调用,并检查其计算出的值。
要在测试时查看模块日志和管线警告,请在运行管线之前在设备上启用 GStreamer 调试输出:
有关更多选项,请参阅故障排除。

后续步骤

您的模型现已完成接入:模块会解析其输出,管线会生成可用的元数据。这与后处理已受支持的模型所达到的状态相同,因此两条路径都会进入同一个最终步骤。

步骤 4 · 构建集成自定义 AI 模型的应用程序

选择开发路径,并按照从管线验证到生产应用程序的推荐顺序进行操作。

相关信息