qtimlpostprocess 模块不支持您的模型输出格式时,如何将自定义后处理模块集成到 QIM SDK 管线中。
当您的模型可以使用现有 QIM SDK 推理插件运行,但其输出张量需要经过自定义处理才能转换为标签、边界框、掩码、关键点、原始张量或其他应用特定元数据时,请使用此工作流。本指南以基于 YOLOv8 的目标检测模型作为端到端示例,演示集成过程的每个步骤。
开始之前
在创建自定义后处理模块之前,请确认满足以下前提条件。只有当所有内置 qtimlpostprocess 模块都无法处理您的模型输出格式时,才需要自定义实现。
下图显示了添加自己的后处理支持的整体流程,从开发和集成模块到运行参考应用程序。

AI 管线概述
Qualcomm Intelligent Multimedia SDK (QIM SDK) 提供构建 AI、多媒体和计算机视觉管线所需的构建模块。AI 工作流由三个关键的 GStreamer 阶段构成,自定义后处理模块仅扩展第三个阶段。
后处理阶段可以通过以下方式之一输出元数据:
- 使用
qtimetamuxer将其附加到源流。 - 将其直接流式传输到 RTSP、RTMP 或 Redis 等端点。
- 将其转换为图像掩码,并使用
qtivcomposer叠加到源视频帧上。

您只需负责后处理模块。预处理、推理和元数据使用均为标准 QIM SDK 元素,
qtimlpostprocess 插件会围绕您的模块处理批处理、输出格式协商和结果数量限制。示例:直接使用 ML 元数据
在此示例中,源流在推理插件之后不再传播,元数据被直接使用。
示例:将 ML 元数据附加到源视频
在此示例中,ML 元数据附加到源视频。叠加层使用附加的元数据绘制边界框、文本和其他可视元素。结果显示在屏幕上,或通过网络流式传输。
示例:将 ML 元数据转换为图像掩码
在此示例中,ML 元数据被转换为图像掩码,然后叠加 (blit) 到源流之上。
qtimlpostprocess 插件行为
qtimlpostprocess 是一个可自定义的插件,为推理插件的张量输出后处理提供库接口。后处理模块负责张量解析,并生成预测结果列表。
每个后处理模块处理一种类型的 ML 模型及其变体,例如所有 YOLOv8 检测变体。该插件负责管理模块执行、输出生成(ML 元数据、图像掩码或张量)、批处理、ML 暂存以及其他相关任务。

插件属性
输出格式
输出格式通过 GStreamer 管线协商确定。系统会自动协商最合适的格式,但您也可以使用 GStreamer caps 过滤器手动指定。该插件仅支持一个源 pad,因此如果应用需要同时使用多种输出格式,请在管线中再添加一个qtimlpostprocess 实例。
该插件支持以下模型类型:
- 目标检测
- 图像分类
- 图像分割
- 超分辨率
- 姿态估计
- 音频分类
编写后处理模块
后处理模块是一个共享库,用于解析推理插件输出的张量。qtimlpostprocess 插件在运行时加载并运行该模块。QIM SDK 提供了种类丰富的开箱即用模块。
在目标设备上运行
gst-inspect-1.0 qtimlpostprocess,可查看支持的模块及其支持的张量形状的完整列表。以下示例显示了部分输出。
/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
安装所需工具
2
3
将 IM SDK 头文件和模块源文件放在同一文件夹中
4
创建 CMakeLists.txt 文件
例如:
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。故障排除
模块未出现在 gst-inspect-1.0 qtimlpostprocess 中
模块未出现在 gst-inspect-1.0 qtimlpostprocess 中
请按顺序检查以下各项:
- 库文件名严格遵循
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 宏,确认模块正在被调用,并检查其计算出的值。后续步骤
您的模型现已完成接入:模块会解析其输出,管线会生成可用的元数据。这与后处理已受支持的模型所达到的状态相同,因此两条路径都会进入同一个最终步骤。步骤 4 · 构建集成自定义 AI 模型的应用程序
选择开发路径,并按照从管线验证到生产应用程序的推荐顺序进行操作。
相关信息
qtimlpostprocess插件参考:完整的属性、信号和接口参考。- 故障排除:AI 管线的通用调试指南。

