Skip to main content
本指南描述了如何在 Qualcomm IM SDK 管线中添加模型后处理支持。 当 Qualcomm IM SDK 插件不支持某个模型的后处理时, 这是必要的。
有关后处理在管线中的作用背景,请参阅 IM SDK 概述。有关完整的 qtimlpostprocess 参考和自定义插件构建详细信息,请参阅 Discover SDKs → IM SDKs。
本节涵盖以下主题。
  1. AI IM SDK 管线概述。
  2. qtimlpostprocess 插件简介。
  3. 如何编写后处理模块。
  4. 如何编译后处理模块。
  5. 如何部署和测试后处理模块。
本示例说明了向 qtimlpostprocess 插件添加自定义 YOLOv8 模型后处理的步骤。 下图显示了添加自己的后处理模型的流程, 从开发和集成模型到运行参考应用程序。 向 Qualcomm IM SDK 添加自定义模型后处理的流程

AI IM SDK 管线概述

Qualcomm Intelligent Multimedia SDK (IM SDK) 包含构建 AI、多媒体和 计算机视觉管线所需的构建模块, 用于构建应用程序。 使用 IM SDK 构建 AI 工作流涉及三个关键的 GStreamer 插件。
  1. 预处理元素:将传入的数据流转换为适合 AI 推理的 张量格式。
  2. 推理元素:使用 AI 模型执行推理,并对输出张量应用 反量化。除反量化之外,此元素不执行任何 预处理或后处理。
  3. 后处理元素:解析输出张量并生成包含机器学习元数据的 缓冲区。此元素以以下方式之一输出 元数据。
  • 使用 qtimetamuxer 将其附加到源流
  • 将其直接流式传输到 RTSP、RTMP 或 Redis 等端点。
  • 作为图像掩码,使用 qtivcomposer 叠加到源视频帧上。
包含预处理、推理和后处理元素的 Qualcomm IM SDK AI 管线

示例:直接使用 ML 元数据

在以下示例中,源流在推理插件之后不再传播。 IM SDK 管线示例:直接使用 ML 元数据,不传播源流

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

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

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

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

IM SDK 中的 AI 后处理插件简介

qtimlpostprocess 是一个可自定义的插件,为推理插件的张量输出后处理 提供库接口。后处理库 负责张量解析,并输出预测结果列表。 后处理 (PP) 模块处理一种类型的机器学习 (ML) 模型。 每个 PP 模块处理特定类型的模型及其变体,例如 所有 YOLOv8 检测模型变体。该插件负责管理模块的执行、 输出生成 (ML 元数据或图像掩码)、批处理、ML 暂存以及其他相关任务。 下图显示了输入、输出、后处理 模块和后处理插件之间的关系。 显示后处理模块输入和输出的图片。 后处理插件支持以下模型类型:
  • 目标检测
  • 图像分类
  • 图像分割
  • 超分辨率
  • 姿态估计
  • 音频分类
后处理插件接收张量列表作为输入。 这些张量封装在 GST Buffer 中。机器学习元数据附加到 每个缓冲区,指定诸如张量数量、张量形状、模型输入 张量形状、每个输入张量中有多少被流数据填充、 时间戳和批处理索引等详细信息。 后处理插件可以生成以下格式之一:
  • 文本:后处理插件将机器学习元数据序列化为文本。此 元数据可被其他插件直接使用,或使用 qtimetamuxer 附加到源流。
  • 图像掩码:后处理插件可以生成带有叠加文本、 边界框、点、线和其他可视元素的图像掩码。这是一个仅包含 机器学习结果的透明帧。 例如,如果后处理类型是目标检测,插件会绘制带标签的 边界框。然后,qtivcomposer 插件可以将图像掩码叠加到 源视频流上。
  • 张量:后处理插件可以生成张量。当下一个推理 阶段需要当前推理阶段的输出张量,但张量形状 不完全匹配时使用此格式。 例如,第一阶段产生四个输出张量,而下一阶段 需要其中三个。
GStreamer 管线的 caps 协商决定输出格式。系统会自动协商 最合适的格式,但您可以使用 GStreamer caps 过滤器手动指定。 该插件仅支持一个源 pad。如果管线需要同时使用两种或更多 支持的格式,请在管线中添加并运行后处理插件 两次。 后处理插件配置由以下内容组成 (GStreamer 属性):
  • Module:(必需)后处理模块名称。此 GStreamer 属性指定如何 解析张量。它不定义插件输出类型。输出类型在 管线 caps 协商期间确定。
  • Settings:(可选)JSON 字符串或 JSON 文件的路径。此配置仅适用 于模块而非插件。它向后处理模块传递任意配置, 因为每个模块都有特定需求。 例如,使用它传递置信度阈值 (confidence-threshold)、关键点、NMS 阈值和 token。
  • Labels:(可选)标签文件的路径。您可以将标签文件的路径直接传递 给模块,使用换行分隔的标签列表、JSON 格式的标签 或自定义格式。前两种格式的解析器已在头文件中提供, 对于自定义格式,您可以在后处理模块中实现自己的解析器。
  • Results:(可选)例如,如果模型检测到 7 个结果但最多允许 4 个,则 会丢弃置信度得分最低的 3 个结果。此功能由插件实现,因此 模块开发者无需自行处理。

为自定义模型编写后处理模块

后处理模块是一个共享库,用于解析推理插件的张量输出。 后处理 GST 插件 (qtimlpostprocess) 加载并运行该模块。IM SDK 提供了种类丰富的开箱即用后处理模块:
  • image-detection (yolov5、yolov8、yolonas、ssd-mobilenet、qfd、qpd、east-textdt)
  • classification (mobilnet、mobilenet-softmax)
  • pose-estimation (hrnet、lite-3dmm、posenet)
  • segmentation (deeplab-argmax、midas-v2)
  • super-resolution (srnet)
使用 gst-inspect-1.0 qtimlpostprocess 可查看设备上支持的模块的完整列表。 以下日志显示了示例输出。
如果找不到适合您模型的后处理模块,您可以实现自己的模块。 您可以独立于 IM SDK 构建后处理模块。 要在不使用 IM SDK 的情况下构建后处理模块,您需要接口 头文件和一个工具链。构建模块后,将其部署到设备上的 /usr/lib/aarch64-linux-gnu/imsdk/qtimlpostprocess/modules/。 后处理插件会自动检测到它,用户可以在 GStreamer 管线中选择它。

模块与库命名

为避免后处理模块名称重复,后处理模块共享库 必须遵循 libml-postprocess-<module-name>.so 命名约定。 例如,YoloV8 模块的共享库必须命名为 libml-postprocess-yolov8.so。 在配置后处理插件时使用相同的 <module-name>。例如,module=yolov8。

运行 gstreamer 管线

AI 后处理模块推理

AI 后处理模块暴露一个 C++ API。由于 C++ API 无法直接从共享库加载, 因此类的实例化被封装在一个 C 函数中。此机制已在头文件中实现, 所以您无需手动处理 C++ 类的实例化。您只需在模块类 (派生自 IModule 接口)中实现以下 API。
  • 构造函数/析构函数:构造函数不接受任何参数,是开发者的 通用入口点。
  • Caps():以 JSON 格式返回模块类型和支持的张量维度。
  • Configure():接受一个标签文件路径和一个包含模块特定设置的 JSON 字符串。 用户通过后处理 GStreamer 插件的 settings 属性提供这些设置。
  • Process():解析输入张量并基于模型输出生成预测。

std::string Caps()

以 JSON 字符串形式返回模块类型和支持的张量形状。张量形状并非固定, 而是在一个范围内定义,用方括号表示。 例如,[1, [21, 42840], 4] 表示第二个维度可以在 21 和 42840 之间变化。 以下代码片段是后处理模块能力定义的示例。该示例实现 目标检测后处理,以 FLOAT32 作为张量格式,并支持一个、两个或三个张量输出。
支持的后处理模块类型
  • object-detection
  • image-classification
  • image-segmentation
  • super-resolution
  • pose-estimation
  • audio-classification
  • tensor
支持的张量类型
  • FLOAT32
  • FLOAT16
  • INT8
  • UINT8
  • INT16
  • UINT16
  • INT32
  • UINT32
  • INT64
  • UINT64
您可以同时指定多种格式。例如:

bool Configure(const std::string& labels_file, const std::string& json_settings)

参数

bool Process(const Tensors& tensors, Dictionary& mlparams, std::any& output)

参数
张量输出是一种特殊情况,后处理插件和模块生成的是张量 而不是预测。当两个机器学习模型链接在一起,并且第一个模型的输出 张量需要在传递给下一个模型之前进行修改时使用。如果输出张量不需要修改,两个推理插件可以直接 一个接一个地链接,不需要后处理插件。

理解后处理模块的输入

后处理模块的输入分为两个字段:
  • tensor:此字段保存推理输出张量并描述其结构。向量 将每个输出张量表示为一个条目。例如,对于 YOLOv8,它产生 三个输出张量(boxes、scores、class indices),向量包含四个条目。
    • Type:float、uint8 等。
    • Name:张量名称,当两个或多个输出张量具有相同形状时用于识别。 张量名称是唯一的,可保证选择准确的张量。
    • Dimensions:描述张量形状。 例如,具有三个输出张量的 YoloV8: [1,8400,4], [1,8400], [1,8400]
    • Data:指向张量的指针。
  • mlparams:用于张量处理的附加参数,可能并不适用于所有子模块。 此字段提供有关管线如何处理输入流的信息,在流的分辨率和 纵横比与输入张量的形状不匹配时可提供帮助。 此字段是使用 std::any 实现的字典。您必须知道预期的键 及其对应的返回类型。使用 std::any 可确保返回值与 给定键关联的类型相匹配。用法示例:
    支持的键
    • Key:“input-tensor-region” Type:video::Region 描述:此参数指示输入张量中哪一部分被来自流的实际数据填充。 其余区域被视为填充。
    • Key:“input-tensor-dimensions” Type:video::Resolution 描述:指定输入张量的大小。当后处理算法以绝对坐标产生输出时, 需要将绝对坐标转换为相对坐标,因为后处理模块必须 输出相对坐标。

生成后处理模块输出

输出是一个由结果数组组成的数组。 数组嵌套是为了支持批处理用例。 在没有批处理的情况下,只填充内部数组。内部数组大小与找到的结果数量匹配。 结果始终以相对维度表示,结果类型取决于模块类型。
  • 图像/音频分类
    • Name:类别标签;预测的图像/音频所属的类别或分类。
    • Confidence:类别概率或置信度得分。
    • Color:用于叠加插件中可视化的 RGBA8888 颜色。
    • Xtraparams:(可选)字典中的额外参数 (键/值对),用于从模块导出任意额外结果以传递到下游。
  • 目标检测
    • Left、top、right、bottom:边界框坐标。
    • Name:类别标签;预测的图像/音频所属的类别或分类。
    • Landmarks:(可选)关键点列表;例如,人脸检测模型可以输出带边界框的人脸关键点。
    • Confidence:类别概率或置信度得分。
    • Color:用于叠加插件中可视化的 RGBA8888 颜色。
    • Xtraparams:(可选)字典中的额外参数 (键/值对),用于从模块导出任意额外结果以传递到下游。
  • 姿态估计
    • Name:类别标签;预测的图像/音频所属的类别或分类。
    • Confidence:类别概率或置信度得分。
    • Keypoints:关键点的向量。
    • Links:(可选)关键点之间的连接向量。
    • Color:用于叠加插件中可视化的 RGBA8888 颜色。
    • Xtraparams:(可选)字典中的额外参数 (键/值对),用于从模块导出任意额外结果以传递到下游。
  • 图像分割和超分辨率
    • 输出为图像帧/掩码。
  • 张量
    • 张量列表。

批处理

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

模块辅助工具

标签和 JSON 解析器包含在接口头文件中。 您不必使用它们,但为方便起见提供了它们。 您可以使用任何标签或 JSON 解析器,但模块必须与其静态链接。
  • 标签解析器:此解析器支持两种格式,接受标签文件的路径,并自动检测格式。
    • 换行分隔格式:行号即为类别 ID。
    • JSON 格式:您应在此格式中设置类别索引、标签和可视化颜色。 此格式更为灵活,因为您可以只传递部分类别,其余类别将被自动过滤掉。
  • JSON 解析器:设置以 JSON 字符串传递。此工具用于解析设置,在 JSON 格式的情况下,此实现 也用于 Qualcomm 提供的标签解析器。

日志记录

后处理模块可以将日志输出到 GStreamer 日志系统,而无需直接依赖 GStreamer。 构造函数将一个日志对象传递给模块。 此对象连同 LOG 宏,可用于将日志直接输出到 GStreamer 日志。 支持的日志级别包括:Error、Warning、Info、Debug、Trace 和 Log。 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

下载所需的脚本和工件

3

将模块部署到目标设备

1

将模块传输到目标设备

从主机上的终端:
2

通过 SSH 登录到目标设备

从主机上的终端:
3

出现提示时输入密码

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

以读写权限重新挂载 /

在 Ubuntu 目标设备上 (SSH 登录后):
5

将模块复制到 GStreamer 插件目录

在目标设备上 (SSH 登录后):
4

在目标设备上运行 GST inspect

确认您的模块出现在支持的模块列表中。您必须看到您的后处理模块出现在支持的模块列表中,并显示支持的张量形状。
5

下载模型、标签和媒体以运行 GStreamer 管线

1

下载 yolox.json

下载 yolox.json。
2

将 yolox.json 复制到目标设备

3

下载 video1.mp4

下载 video1.mp4。
4

将 video1.mp4 复制到目标设备

5

下载 yolox_quantized.tflite

6

将 yolox_quantized.tflite 复制到目标设备

6

构建带有后处理模块的 GStreamer 管线

使用 qtimlpostprocess 插件的 module 属性选择您的后处理模块。如果您的模块需要标签文件或配置,请使用 label 和 settings 属性传递它们。在以下运行 YOLO-X 模型的示例管线中:
  • 该管线使用离线视频作为源。
  • 该管线使用 v4l2h264dec 解码器将视频解码为 YUV 格式。
  • qtimlvconverter 插件对 YUV 帧进行预处理。
  • qtimltflite 插件使用 LiteRT YOLO-X 模型运行推理。
  • 后处理插件加载 YOLO-X 模块并传递 JSON 格式的标签文件。
  • 该管线在 Wayland 上显示结果。