> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# qtimlqnn

> 使用 QNN 运行时执行神经网络模型的 GStreamer 推理元素。

<Note>
  qtimlqnn 仅在 `qcom-multimedia-proprietary-image` 中可用  <br />
  有关 QLI 镜像的更多信息，请参阅 [Qualcomm Linux 发行版](https://qualcomm-staging.mintlify.app/Key-Documents/Yocto-Guide/qualcomm-linux-yocto-overview#qualcomm-linux-release)
</Note>

# 概述

**qtimlqnn** 是一个 GStreamer 推理元素，使用 **Qualcomm AI Engine Direct（QNN）**运行时执行神经网络模型。该元素完全以**张量模式**运行：它在 sink pad 上接收输入张量，并根据模型声明的输入和输出规范在 source pad 上生成输出张量。

**qtimlqnn** 设计用于运行为 QNN 运行时准备的模型，通常为 \*\*QNN 上下文二进制文件（context binary）\*\*形式。要使用此元素，必须先使用 **Qualcomm AI Runtime（QAIRT）SDK** 将模型导出为与 QNN 兼容的格式。更多详细信息，请参阅 [QAIRT 文档](https://docs.qualcomm.com)。

该元素仅限于**模型执行**。它不执行预处理、张量重塑、批处理、布局转换或特定于模型的后处理。这些功能应由流水线中的相邻元素处理。

**qtimlqnn** 支持多种 QNN 执行后端，包括 **CPU**、**GPU** 和 **NPU** 目标。这使得相同的流水线结构可以部署到不同的硬件配置，并针对不同的性能、延迟和功耗需求进行调优。该元素面向**实时和嵌入式 AI 流水线**，其中推理是更大的模块化处理流程中的一个阶段。

### 主要职责

**qtimlqnn** 负责：

* 加载并执行 QNN 模型构件，例如模型库（`.so`）或缓存的二进制文件（`.bin`）
* 接收来自上游元素的预格式化输入张量
* 生成与模型输出签名匹配的输出张量
* 与相邻流水线元素协商张量数据类型和维度
* 传播下游元素所需的张量元数据
* 通过 `GstMLBufferPool` 管理 DMA 后备缓冲区，以减少不必要的内存复制

在实际使用中，**qtimlqnn** 充当流水线中的推理阶段，而张量准备和结果解释则由外部处理。

<img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/SDKs/IMSDK/plugin-reference/images/qtimlqnn1.png" alt="" />

## 示例流水线

<Steps>
  <Step title="下载所需文件">
    | 文件                | 下载                                                                                                                           | 保存为                         |
    | ----------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------- |
    | Yolov8 检测 W8A8 模型 | [从 Qualcomm AI Hub 导出](https://aihub.qualcomm.com/iot/models/yolov8_det)                                                     | `yolov8_det_w8a8.bin`       |
    | 检测标签              | <a href="/SDKs/IMSDK/labels/yolov8.json" download="yolov8.json">yolov8.json</a>                                              | `yolov8.json`               |
    | 示例视频              | <a href="https://github.com/qualcomm/sample-apps-for-qualcomm-linux/raw/refs/heads/main/artifacts/videos/video.mp4">输入视频</a> | `Draw_1080p_180s_30FPS.mp4` |
  </Step>

  <Step title="将文件复制到设备">
    <CodeGroup>
      ```bash SCP (SSH) theme={null}
      # Replace $HOME to the appropriate device path before running the commands.
      # For QLI:    /root
      # For Ubuntu: /home/ubuntu
      # Modify this based on your platform and ensure files are copied to the correct location on the device.
      # Run from your host machine — replace <user> and <device-ip>

      ssh <user>@<device-ip> "mkdir -p $HOME/{models,labels,media,media/output}"
      scp yolov8_det_w8a8.bin          <user>@<device-ip>:$HOME/models/
      scp yolov8.json                  <user>@<device-ip>:$HOME/labels/
      scp Draw_1080p_180s_30FPS.mp4    <user>@<device-ip>:$HOME/media/
      ```
    </CodeGroup>
  </Step>

  <Step title="连接到设备">
    <CodeGroup>
      ```bash SCP (SSH) theme={null}
      # Run from your host machine — replace <user> and <device-ip>
      ssh <user>@<device-ip>
      ```
    </CodeGroup>
  </Step>

  <Step title="设置环境变量">
    在设备上运行以下命令

    ```bash theme={null}
    mkdir -p $HOME/{models,labels,media,media/output}
    export MODEL_NAME=yolov8_det_w8a8.bin
    export LABELS_NAME=yolov8.json
    export SRC_VIDEO_NAME=Draw_1080p_180s_30FPS.mp4
    ```
  </Step>

  <Step title="运行流水线">
    ```bash theme={null}
    gst-launch-1.0 -e --gst-debug=2 \
    filesrc location=$HOME/media/$SRC_VIDEO_NAME ! qtdemux ! h264parse ! \
    v4l2h264dec capture-io-mode=4 output-io-mode=4 ! video/x-raw,format=NV12 ! queue ! \
    tee name=t ! queue ! qtimetamux name=obj_mux ! qtivoverlay ! waylandsink fullscreen=true sync=false \
    t. ! queue ! qtimlvconverter ! queue ! \
    qtimlqnn model=$HOME/models/$MODEL_NAME backend=/usr/lib/libQnnHtp.so tensors="<boxes,scores,class_idx>" ! queue ! \
    qtimlpostprocess module=yolov8 labels=$HOME/labels/$LABELS_NAME settings="{\"confidence\": 51.0}" ! text/x-raw ! queue ! obj_mux.
    ```
  </Step>
</Steps>

# 层次结构

[GObject](https://docs.gtk.org/gobject/)<br />
   <Icon icon="arrow-turn-down-right" iconType="solid" />[GstObject](https://gstreamer.freedesktop.org/documentation/gstreamer/gstobject.html?gi-language=c)<br />
      <Icon icon="arrow-turn-down-right" iconType="solid" />[GstElement](https://gstreamer.freedesktop.org/documentation/gstreamer/gstelement.html?gi-language=c)<br />
         <Icon icon="arrow-turn-down-right" iconType="solid" />[GstBaseTransform](https://gstreamer.freedesktop.org/documentation/base/gstbasetransform.html?gi-language=c)<br />
            <Icon icon="arrow-turn-down-right" iconType="solid" />qtimlqnn

# Pad 模板

### sink

| 能力                       |                                                                           |
| ------------------------ | ------------------------------------------------------------------------- |
| `neural-network/tensors` | `format: { INT8, UINT8, INT16, UINT16, INT32, UINT32, FLOAT16, FLOAT32 }` |
| 可用性：*Always*             |                                                                           |
| 方向：*sink*                |                                                                           |

### src

| 能力                       |                                                                           |
| ------------------------ | ------------------------------------------------------------------------- |
| `neural-network/tensors` | `format: { INT8, UINT8, INT16, UINT16, INT32, UINT32, FLOAT16, FLOAT32 }` |
| 可用性：*Always*             |                                                                           |
| 方向：*source*              |                                                                           |

# 元素属性

| 属性                  | 描述                                                                                                                                                                    |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `backend`           | QNN 后端库的路径。选择用于推理的执行后端。根据所使用的库，支持的后端包括 CPU、HTP 或 NPU、GPU 以及 DSP 实现。<br /><br />`Type: String`<br />`Default: "/usr/lib/libQnnCpu.so"`<br />`Flags: readable/writable` |
| `backend-device-id` | 后端设备选择器。依赖于平台，用于某些 DSP 或 HTP 变体以选择特定的硬件实例。<br /><br />`Type: Unsigned Integer`<br />`Default: 0`<br />`Flags: readable/writable`                                      |
| `model`             | QNN 模型文件的路径。该属性为必填项，且必须引用有效的 `.so` 模型或缓存的 `.bin` 文件。<br /><br />`Type: String`<br />`Default: NULL`<br />`Flags: readable/writable`                                   |
| `system`            | QNN 运行时初始化所需的 QNN 系统库的路径。<br /><br />`Type: String`<br />`Default: "/usr/lib/libQnnSystem.so"`<br />`Flags: readable/writable`                                        |
| `tensors`           | 输出张量过滤器。设置后，仅在 source pad 上发出指定名称的输出张量。为空时，发出所有模型输出。<br /><br />`Type: GstValueArray of type gchararray`<br />`Default: "< >"`<br />`Flags: readable/writable`        |

# 输入与输出行为

### 输入张量

**qtimlqnn** 暴露单个 sink pad，但同时支持单输入和多输入模型。对于多输入模型，所有所需张量以张量集的形式通过同一个 sink pad 传递。

输入张量必须在到达 **qtimlqnn** 之前完全准备好。预期的张量布局、形状、数据类型和批量大小由以下因素决定：

* QNN 模型输入签名
* 与上游元素的 caps 协商

典型的上游元素包括：

* [`qtimlvconverter`](qtimlvconverter) — 用于缩放、颜色转换、归一化和量化（如需要）

**qtimlqnn** 不会修改、重塑、批处理或重新解释传入的张量。它按接收到的原样将其传递给 QNN 运行时。

### 输出张量

**qtimlqnn** 暴露单个 source pad，并生成符合模型声明的输出签名的输出张量。完全支持具有多个输出张量的模型，所有输出会在 source pad 上一起发出。

支持的输出行为包括：

* 单张量和多张量输出
* 任意张量形状和秩，包括批量维度和深度维度
* 量化和浮点张量类型
* 使用 `tensors` 属性选择性地发出输出张量

生成的输出张量供下游后处理阶段使用，后者负责解码特定于模型的结果，例如分类输出、检测结果、分割掩码、关键点数据以及其他结构化推理输出。

# 支持的数据类型

**qtimlqnn** 支持 QNN 运行时和所选执行后端提供的张量数据类型，具体取决于与相邻元素的 caps 协商。

支持的数据类型包括：

* `INT8`
* `UINT8`
* `INT16`
* `UINT16`
* `INT32`
* `UINT32`
* `FLOAT16`
* `FLOAT32`

除了运行时、所选后端以及协商的流水线 caps 所要求的限制之外，该元素不会施加额外的数据类型限制。

# 后端

QNN **后端**定义了运行模型所使用的硬件目标。后端使 **qtimlqnn** 能够将推理从默认的 CPU 解释器卸载到经过优化的硬件加速器。通过 `backend` 属性选择后端，它控制 QNN 运行时在推理期间如何分派模型操作。

### NPU — libQnnHtp.so

在 AI 加速器（NPU）上运行模型。

* **后端**：Qualcomm AI 加速器 / NPU
* **使用场景**：如果可用则为首选后端。对量化模型具有最佳的性能和能效。
* **附加配置**：设置 `backend=libQnnHtp.so`；对于多设备平台，可选设置 `backend-device-id`

### GPU — libQnnGpu.so

通过 QNN GPU 后端运行受支持的操作。

* **后端**：GPU
* **使用场景**：浮点模型以及受益于 GPU 并行性的工作负载。
* **附加配置**：设置 `backend=/usr/lib/libQnnGpu.so`

### CPU — libQnnCpu.so

在默认的 QNN CPU 后端上运行模型。

* **后端**：CPU
* **使用场景**：参考执行、调试、启动验证（bring-up）或没有硬件加速的系统。
* **附加配置**：无需

# 运行时内存行为与 GAP 处理

### QNN 内存模型

**qtimlqnn** 在 QNN 运行时的内存模型内运行。该元素通过 `GstMLBufferPool` 使用 DMA 缓冲区，以最大限度地减少内存复制，并尽可能保持零拷贝传输。

QNN 使用运行时管理的内存来分配：

* 输入张量
* 中间激活张量
* 输出张量

元素在模型加载时发现输入/输出张量元数据（数量、形状、类型），并相应地配置缓冲池。

### GAP 缓冲区处理

**qtimlqnn** 支持 GAP 感知，能够正确处理标记了 `GST_BUFFER_FLAG_GAP` 的输入缓冲区。

当收到 GAP 缓冲区时，元素跳过推理并将缓冲区向下游转发。这在保持时序和同步的同时，明确表明该时间戳没有可用的有效推理输入。

GAP 缓冲区常见于条件式 AI 流水线，例如级联工作流，其中只有当前面的阶段产生有效的感兴趣区域时，后续推理阶段才会运行。

# 用法

### 实时摄像头流上的单阶段 AI 推理（HTP）

本示例演示了使用带 HTP 后端的单个 **qtimlqnn** 实例，在实时摄像头流上进行实时推理。推理结果作为 `MLMeta` 附加到每个 `GstBuffer`，使下游元素可以直接从帧中访问同步的元数据。叠加阶段随后使用此元数据在显示或进一步处理之前渲染边界框、标签或关键点等注释。

<img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/SDKs/IMSDK/plugin-reference/images/qtimlqnn2.png" alt="" />

<Steps>
  <Step title="下载所需文件">
    | 文件                | 下载                                                                              | 保存为                   |
    | ----------------- | ------------------------------------------------------------------------------- | --------------------- |
    | Yolov8 检测 W8A8 模型 | [从 Qualcomm AI Hub 导出](https://aihub.qualcomm.com/iot/models/yolov8_det)        | `yolov8_det_w8a8.bin` |
    | 检测标签              | <a href="/SDKs/IMSDK/labels/yolov8.json" download="yolov8.json">yolov8.json</a> | `yolov8.json`         |
  </Step>

  <Step title="将文件复制到设备">
    <CodeGroup>
      ```bash SCP (SSH) theme={null}
      # Run from your host machine — replace <user> and <device-ip>
      ssh <user>@<device-ip> "mkdir -p $HOME/{models,labels}"
      scp yolov8_det_w8a8.bin   <user>@<device-ip>:$HOME/models/
      scp yolov8.json           <user>@<device-ip>:$HOME/labels/
      ```
    </CodeGroup>
  </Step>

  <Step title="连接到设备">
    <CodeGroup>
      ```bash SCP (SSH) theme={null}
      # Run from your host machine — replace <user> and <device-ip>
      ssh <user>@<device-ip>
      ```
    </CodeGroup>
  </Step>

  <Step title="设置环境变量">
    在设备上运行以下命令

    ```bash theme={null}
    mkdir -p $HOME/{models,labels}
    export MODEL_NAME=yolov8_det_w8a8.bin
    export LABELS_NAME=yolov8.json
    ```
  </Step>

  <Step title="运行流水线">
    ```bash Run the pipeline theme={null}
    gst-launch-1.0 -e --gst-debug=2 \
    qticamsrc name=camsrc ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! queue ! \
    tee name=t ! queue ! qtimetamux name=obj_mux ! qtivoverlay ! waylandsink fullscreen=true sync=false \
    t. ! queue ! qtimlvconverter ! queue ! \
    qtimlqnn model=$HOME/models/$MODEL_NAME backend=/usr/lib/libQnnHtp.so tensors="<boxes,scores,class_idx>" ! queue ! \
    qtimlpostprocess module=yolov8 labels=$HOME/labels/$LABELS_NAME settings="{\"confidence\": 51.0}" ! text/x-raw ! queue ! obj_mux.
    ```
  </Step>
</Steps>

### 实时摄像头流上的单阶段 AI 推理（GPU）

本示例演示了相同的单阶段推理工作流，但使用 GPU 后端而非 HTP。适用于浮点模型或受益于 GPU 并行性的工作负载。

<img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/SDKs/IMSDK/plugin-reference/images/qtimlqnn2.png" alt="" />

<Steps>
  <Step title="下载所需文件">
    | 文件            | 下载                                                                              | 保存为                    |
    | ------------- | ------------------------------------------------------------------------------- | ---------------------- |
    | Yolov8 检测浮点模型 | [从 Qualcomm AI Hub 导出](https://aihub.qualcomm.com/iot/models/yolov8_det)        | `yolov8_det_float.bin` |
    | 检测标签          | <a href="/SDKs/IMSDK/labels/yolov8.json" download="yolov8.json">yolov8.json</a> | `yolov8.json`          |
  </Step>

  <Step title="将文件复制到设备">
    <CodeGroup>
      ```bash SCP (SSH) theme={null}
      # Run from your host machine — replace <user> and <device-ip>
      ssh <user>@<device-ip> "mkdir -p $HOME/{models,labels}"
      scp yolov8_det_float.bin   <user>@<device-ip>:$HOME/models/
      scp yolov8.json            <user>@<device-ip>:$HOME/labels/
      ```
    </CodeGroup>
  </Step>

  <Step title="连接到设备">
    <CodeGroup>
      ```bash SCP (SSH) theme={null}
      # Run from your host machine — replace <user> and <device-ip>
      ssh <user>@<device-ip>
      ```
    </CodeGroup>
  </Step>

  <Step title="设置环境变量">
    在设备上运行以下命令

    ```bash theme={null}
    mkdir -p $HOME/{models,labels}
    export MODEL_NAME=yolov8_det_float.bin
    export LABELS_NAME=yolov8.json
    ```
  </Step>

  <Step title="运行流水线">
    ```bash Run the pipeline theme={null}
    gst-launch-1.0 -e --gst-debug=2 \
    qticamsrc name=camsrc ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! queue ! \
    tee name=t ! queue ! qtimetamux name=obj_mux ! qtivoverlay ! waylandsink fullscreen=true sync=false \
    t. ! queue ! qtimlvconverter ! queue ! \
    qtimlqnn model=$HOME/models/$MODEL_NAME backend=/usr/lib/libQnnGpu.so tensors="<boxes,scores,class_idx>" ! queue ! \
    qtimlpostprocess module=yolov8 labels=$HOME/labels/$LABELS_NAME settings="{\"confidence\": 51.0}" ! text/x-raw ! queue ! obj_mux.
    ```
  </Step>
</Steps>
