> ## 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.

# qtimlvconverter

> AI 预处理插件

# 概述

**qtimlvconverter** 元素是 AI 管道中的关键组件，负责 AI 预处理——具体来说，就是为神经网络推理准备视频帧数据。它高效地处理 YUV 或 RGB 格式的输入缓冲区，并将其转换为与机器学习模型兼容的张量。

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

这一转换包含以下几项关键操作：

* **裁剪（Cropping）**：选择输入帧中的特定区域进行聚焦处理。该操作使用提供的 ROI 元数据来确定每一帧的裁剪区域。
* **缩放（Rescaling）**：调整输入帧的空间尺寸，使其与目标模型期望的张量尺寸匹配，以确保兼容性和一致的性能。
* **格式转换（Format Conversion）**：在支持的格式之间转换像素数据（例如从 YUV 到 RGB），以满足目标模型的输入要求。
* **批处理（Batching）**：将多个帧或图像聚合成批次，以优化推理吞吐量并利用并行处理能力。
* **归一化（Normalization）**：应用像素值缩放和归一化技术（如均值减法和标准差除法），对输入数据进行标准化以提升模型精度。
* **时间批处理（Temporal Batching）**：通过沿深度维度堆叠多个时间上连续的帧，生成形状为 NDHWC 的输入张量。这使其能够兼容需要跨帧时间上下文的基于视频的模型。

为了高效执行转换，**qtimlvconverter** 在 GPU 上运行，并以链式方式执行这些步骤。它将整个输入帧或裁剪区域调整为目标张量尺寸，同时保留完整的视野。在此步骤中，只有分辨率发生变化，格式和数据范围保持不变。默认情况下，它会保持原始宽高比，确保输出中物体的几何形状不失真。如果输入帧的宽高比与目标张量的宽高比不同，调整大小后的帧会被放置在左上角，其余区域则填充为黑色背景。这种方法确保整个张量都被填充，保留原始图像内容的完整性，并避免裁剪或失真。这使其非常适合需要一致空间表示的模型。

该插件还会智能地分析维度顺序、数量和大小，以自动选择合适的张量布局。输出张量可以以交错（*NHWC*）或平面（*NCHW*）格式生成，支持 *RGBA*、*RGB* 或 *GRAYSCALE* 像素排列。此选择由插件无缝完成，无需手动配置。

除了传统的四维张量输出外，该插件还支持五维张量，其中第五个维度表示深度（*NDHWC*）。这种高级配置的检测和应用是自动管理的，进一步增强了对复杂推理模型的灵活性。

为了适配使用其他像素排列方式训练的模型，可以通过 subpixel-layout 属性修改默认的张量格式——通常为 *RGBA*、*RGB* 或 *GRAYSCALE*。此功能支持 *BGRA* 或 *BGR* 等格式，确保与各种神经网络架构和训练方法兼容。

通过这种自动化且高度可配置的方式，该插件简化了将视频数据转换为神经网络就绪张量的过程，为各种部署场景提供稳健且高效的推理支持。
<Tip>关于张量选项的更多详细信息，请参见本页末尾</Tip>

## 示例管道

<Steps>
  <Step title="下载所需文件">
    | 文件            | 下载                                                                                                                           | 保存为                         |
    | ------------- | ---------------------------------------------------------------------------------------------------------------------------- | --------------------------- |
    | YOLOX W8A8 模型 | [Qualcomm AI Hub — YOLOX](https://aihub.qualcomm.com/iot/models/yolox)                                                       | `yolo_x_w8a8.tflite`        |
    | 检测标签          | <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` |

    <Note>
      如果下载的任何文件是 `.zip` 压缩包，请在复制前先在主机上解压：
      `unzip filename.zip`
    </Note>
  </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 yolo_x_w8a8.tflite           <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}
    export MODEL_NAME=yolo_x_w8a8.tflite
    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 ! qtimetamux name=obj_mux ! qtivoverlay ! waylandsink fullscreen=true sync=false \
    t. ! queue ! qtimlvconverter ! queue ! \
    qtimltflite model=$HOME/models/$MODEL_NAME delegate=external external-delegate-path=libQnnTFLiteDelegate.so \
    external-delegate-options="QNNExternalDelegate,backend_type=htp,log_level=(string)1;" ! 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" />qtimlvconverter

# Pad 模板

### sink

| 能力            |                                                                                                                                                                                                          |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `video/x-raw` | `format: { RGBA, BGRA, ABGR, ARGB, RGBx, BGRx, xRGB, xBGR, BGR, RGB, GRAY8, NV12, NV21, YUY2, UYVY, NV12_Q08C }` <br /> `width: [1, 32767]` <br /> `height: [1, 32767]` <br /> `framerate: [0/1, 255/1]` |
| 可用性：*Always*  |                                                                                                                                                                                                          |
| 方向：*sink*     |                                                                                                                                                                                                          |

### src

| 能力                       |                                                                                                                                                                                  |
| ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `neural-network/tensors` | `format: { INT8, UINT8, INT16, UINT16, INT32, UINT32, INT64, UINT64, FLOAT16, FLOAT32 }` <br /> `width: [1, 32767]` <br /> `height: [1, 32767]` <br /> `framerate: [0/1, 255/1]` |
| 可用性：*Always*             |                                                                                                                                                                                  |
| 方向：*source*              |                                                                                                                                                                                  |

# 元素属性

| 属性                  | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `engine`            | 用于转换操作的引擎后端。<br /><br />`Type: Enum `<br />`Default: 2, "gles"`<br />`Range:`<br />    `(0): none - No backend used`<br />    `(2): gles - Use OpenGLES based video converter`<br />    `(3): fev - Use FastCV based video converter`<br />    `(4): ocv - Use OpenCV based video converter`<br />`Flags: readable/writable`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
| `image-disposition` | 图像在输出张量中的宽高比与放置方式。<br /><br />`Type: Enum `<br />`Default: 0, "top-left"`<br />`Range:`<br />    `(0): top-left - Preserve aspect ratio during resize  and place it in the top-left corner of the output tensor`<br />    `(1): centre - Preserve aspect ratio during resize and place it in the centre of the output tensor`<br />    `(2): stretch - Ignore aspect ratio and if required stretch it's AR in order to fit completely inside the output tensor`<br />    `(3): centre-crop - Ignore the aspect ratio and if required crop the source around its center to fit completely inside the output tensor` <br /> `Flags: readable/writable`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `mean`              | FLOAT 张量的通道均值减法值，例如 `{R, G, B}`、`{R, G, B, A}` 或 `{<G>}`。<br /><br />`Type: GstValueArray of type gdouble`<br /> `Default: "<  >"` <br /> `Flags: readable/writable`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `mode`              | 转换模式。<br /><br />`Type: Enum `<br />`Default: 0, "image-batch-non-cumulative"`<br />`Range:`<br />    `(0): image-batch-non-cumulative - ROI metadata is ignored.Immediately process incoming buffers irrelevant of whether there are enough image memory blocks to fill the requested tensor batch size.`<br />    `(1): image-batch-cumulative - ROI metadata is ignored. Accumulate buffers until there are enough image memory blocks to fill the requested tensor batch size. Accumulation is interrupted early if a GAP buffer is received.`<br />    `(2): roi-batch-non-cumulative - Use only ROI metas to fill tensor batch size. Immediately process incoming buffers irrelevant of whether there are enough ROI metas to fill the requested tensor batch size. In case no ROI meta is present a GAP buffer will be produced.`<br />    `(3): roi-batch-cumulative - Use only ROI metas to fill tensor batch size. Accumulate buffers until there are enough ROI metas to fill the requested tensor batch size. Accumulation is interrupted early if a GAP buffer is received or if there are no ROI metas present inside the received buffer.`<br />`Flags: readable/writable` |
| `sigma`             | FLOAT 张量的通道除数值，例如 `{R, G, B}`、`{R, G, B, A}` 或 `{<G>}`。<br /><br />`Type: GstValueArray of type gdouble`<br /> `Default: "<  >"` <br /> `Flags: readable/writable`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
| `subpixel-layout`   | 输出张量中图像像素的排列方式。<br /><br />`Type: Enum `<br />`Default: 0, "regular"`<br />`Range:`<br />    `(0): regular - RGB, RGBA, RGBx`<br />    `(1): reverse - BGR, BGRA, BGRx`<br />`Flags: readable/writable`                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |

# 图像/视频张量特性

图像或视频张量具有若干关键特性，这些特性定义了机器学习管道中数据的表示和处理方式：

```bash theme={null}
🛈 Layouts
 N - Tensor batch size. How many frames can be processed at the same time by the model.
 D - Tensor depth. Represent the number of history frames from single source/stream.
 H - Tensor height in pixels.
 W - Tensor width in pixels.
 C - Number of pixel components(4 == RGBA/BGRA, 3 == RGB/BGR, 1 == GRAYSCALE).

```

**张量维度 / 描述符**

这定义了张量的形状和布局。常见的描述符包括：

* **NCHW（批次、通道、高度、宽度）**：
  一个通道的所有像素连续存储。许多深度学习框架（如 PyTorch、Caffe）偏好这种格式，因为它可以优化 GPU 上的卷积运算。
  以 RGB 为例：
  * 首先是整幅图像的所有红色（Red）值
  * 然后是所有绿色（Green）值
  * 最后是所有蓝色（Blue）值
    <img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/SDKs/IMSDK/plugin-reference/images/nchw.png" alt="NCHW" />

* **NHWC（批次、高度、宽度、通道）**
  通道按像素交错排列。在 TensorFlow 和 IM SDK 中很常见，因为它更符合某些硬件加速器的内存访问模式。
  以 RGB 为例：
  * 像素 1：R、G、B
  * 像素 2：R、G、B
  * 依此类推
    <img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/SDKs/IMSDK/plugin-reference/images/nhwc.png" alt="NHWC" />

* **NDHWC（批次、深度、高度、宽度、通道）**
  该格式在 NHWC 布局的基础上增加了深度（D）维度，使其适用于视频序列或体数据（例如用于动作识别的时间堆叠）。
  帧按顺序存储，每一帧内的像素按 NHWC 顺序排列（每个像素的通道交错存储）。
  例如：
  * 帧 1：每个像素的 R、G、B
  * 帧 2：每个像素的 R、G、B
  * 依此类推。
    <img src="https://mintlify.s3.us-west-1.amazonaws.com/qualcomm-prod/zh/SDKs/IMSDK/plugin-reference/images/ndhwc.png" alt="NDHWC" />

**NCHW** 和 **NHWC** 格式包含相同的数据，但**组织方式不同**。字母的顺序表示数据在张量中的排列方式。以 **\[1,3,480,640]** 和 **\[1,480,640,3]** 张量为例。两种情况下，批次大小均为 1，宽度为 640，高度为 480，通道数为 3。假设图像格式为 RGB。这两种格式的关键区别在于 RGB 像素在缓冲区中的排列方式。

**数据格式**

指定张量中存储的值的类型，例如 **UINT8、INT8、UINT16、FLOAT32、FLOAT16** 等

**数据范围**

定义张量元素的期望取值范围：

* 0-255 - 原始 **UINT8** 图像数据的典型范围
* -128-127 - 原始 **INT8** 图像数据的典型范围
* 0.0-1.0 - FLOAT16 和 FLOAT32 张量常用的**归一化浮点**数据范围
* -1.0-1.0 - 部分期望中心化数据的模型使用，用户必须显式配置归一化参数（偏移和缩放）
* 根据模型的训练设置，也可能使用自定义范围

**颜色格式**

指示颜色信息的表示方式：

* RGB – 红、绿、蓝（大多数模型的标准格式）
* BGR – 蓝、绿、红（部分基于 OpenCV 的模型使用）
* Grayscale – 用于单色图像的单通道格式

**qtimlvconverter 支持的张量**

| 属性   | 描述                         |
| ---- | -------------------------- |
| 张量形状 | NHWC、NCHW、NDHWC            |
| 数据格式 | uint8、int8、float32、float16 |
| 数据范围 | 任意                         |
| 颜色格式 | RGB、BGR、Grayscale          |

# 图像放置方式对模型性能的影响

在使用计算机视觉模型时，我们通常关注图像的内容——但图像在输入张量中的放置位置同样会产生重大影响。默认情况下，它会保持原始宽高比，确保输出中物体的几何形状不失真。如果输入帧的宽高比与目标张量的宽高比不同，调整大小后的帧会被放置在左上角，其余区域填充为黑色背景。这种方法确保整个张量都被填充，保留原始图像内容的完整性，并避免裁剪或失真，非常适合需要一致空间表示的模型。

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

然而，某些模型在图像**居中或拉伸**以填满整个张量而不留填充区时表现更好。为支持此类用例，**qtimlvconverter** 提供了三种可配置的放置模式：

* **top-left**（默认）- 保持图像的原始宽高比，并将其放置在输出张量的**左上角**。
* **centre** - 同样保持宽高比，但将图像在张量中居中。这是期望主要目标位于中间的模型的常用选择。
* **stretch** - 忽略原始宽高比，将图像拉伸以完全填满张量。这可能引入失真，但确保完全覆盖，某些模型需要这种方式
* **centre-crop** - 忽略源图像的宽高比（AR，Aspect Ratio），必要时围绕中心裁剪源图像，使其完全适配输出张量。

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

**如果需要裁剪怎么办？**

在某些情况下，与其调整或重新定位整幅图像，你可能需要**裁剪特定区域**——例如输入图像的随机或目标部分——并只将该部分送入模型。当模型被训练为关注局部特征时，这种方法非常有用。虽然 **image-disposition** 有助于处理放置和宽高比，但裁剪是一个独立的预处理步骤，可以让你更精确地控制模型看到图像的**哪个部分**。

为实现这一点，你可以在 **qtimlvconverter** 之前插入一个 [qtivtransform](https://qualcomm-confluence.atlassian.net/wiki/spaces/VAISDK/pages/1669368059/qtivtransform) 步骤。它允许你在输入图像到达转换器之前执行必要的裁剪操作。这使你能够精确控制使用图像的哪个部分。

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

各组件的工作方式如下：

* **source**：这是你的输入流。
* [qtivtransform](https://qualcomm-confluence.atlassian.net/wiki/spaces/VAISDK/pages/1669368059/qtivtransform)：此阶段允许你对图像应用变换，例如裁剪、缩放或旋转。在此上下文中，你可以通过直接传递给 **qtivtransform** 的属性定义一个**裁剪区域**，从而在图像到达模型之前提取输入图像的特定部分。

```bash theme={null}
⚠️ Important: The output resolution of qtivtransform must be specified manually.
To avoid stretching or distortion, the aspect ratio of the output resolution
must match the aspect ratio of the crop window. If you're unsure what
resolution to choose, you can simply set the crop width and height as
the output resolution - this ensures a 1:1 mapping without scaling.
```

* **qtimlvconverter**：裁剪之后，该组件为推理准备图像。它根据 **image-disposition** 属性（例如 **top-left、centre、stretch**）处理缩放、颜色转换、归一化和定位
* **sink** - 这是张量传递到的下一个元素

通过将 **qtivtransform 的输入裁剪**与 qtimlvconverter 中 **image-disposition** 的放置控制相结合，你可以实现任何所需的变换——无论是聚焦特定区域、保持宽高比，还是在张量内对齐图像。在适配不同的模型需求或优化推理性能时，这种灵活性尤其宝贵

下图演示了如何将输入图像的特定区域转换为张量。

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

此示例展示了如何转换预定义区域。虽然 [qtivtransform](https://qualcomm-confluence.atlassian.net/wiki/spaces/VAISDK/pages/1669368059/qtivtransform) 支持运行时更新裁剪窗口，但这种方案并不总是可扩展的。

在更高级的用例中，**qtimlvconverter** 可以自行执行裁剪，而无需依赖 [qtivtransform](https://qualcomm-confluence.atlassian.net/wiki/spaces/VAISDK/pages/1669368059/qtivtransform)。例如，如果你有**两个顺序工作的模型**——检测模型后接姿态估计模型——**qtimlvconverter** 可以自动为第一阶段检测到的每个边界框裁剪并生成张量。

# 归一化

像素值的归一化会根据协商的张量数据类型自动执行。对于浮点张量类型 **（FLOAT16、FLOAT32）**，像素值被归一化到 (0,1) 范围。对于有符号和无符号整数类型（如 **INT8、UINT8、INT16、UINT16**），归一化根据每种类型的完整取值范围进行——例如，INT8 归一化到 \[−128 , 127]，UINT8 归一化到 \[0 , 255]，INT16 归一化到 \[−32,768 , 32,767]。

除了这种自动归一化外，插件还通过 **mean** 和 **sigma** 属性提供进一步的自定义功能，使用以下公式实现按通道归一化：

```bash theme={null}
🛈 Normalization

normalized_value = (<Pixel Channel Value> - mean​) * sigma
```

```bash theme={null}
🛈 Example

An INT16 RGB image with values R=2000, G=-344, B=0 and property values 
mean="<1280.0, 1560.0, -1240.0>" and sigma="<0.75, 0.34, 0.02>" would
have the following channel transformations:
R=(2000 - 1280.0) x 0.75, G=(-324 - 1560.0) x 0.34, B=(0 + 1240.0) x 0.02.
```

这种自定义归一化在初始的基于范围的归一化之后应用，可以精确调整像素值，以满足特定神经网络模型或训练方案的要求。这种双阶段归一化方法确保张量数据既符合类型要求，又为推理进行了最优调整，在各种部署场景中支持稳健且准确的模型性能。

# 批处理

批处理是 AI 推理管道中的一项关键优化技术，允许同时处理多个帧。这可以提高吞吐量，并支持在硬件加速器上并行执行。

在 **qtimlvconverter** 的上下文中，输入视频缓冲区可能来自：

* 单个源（例如一个摄像头或视频文件），其中每个 **GstBuffer** 包含一个 **GstMemory** 块。
* 多路复用流（例如多个摄像头或视频文件），其中每个 **GstBuffer** 包含多个 **GstMemory** 块。此配置通过 **qtibatch** 插件启用，该插件将来自不同源的帧聚合成单个批处理缓冲区。

批处理在使用被训练为同时处理多个输入的模型（例如批次大小 = 4）时尤其有用。它使推理引擎能够更高效地利用 GPU 资源，并减少逐帧处理的开销。

**工作原理：**

* 缓冲区中的每个 **GstMemory** 块代表一帧
* \**qtimlvconverter* 遍历所有内存块，并对每一帧分别应用预处理步骤（裁剪、缩放、格式转换、归一化）。
* 处理后的帧随后被打包成形状为 **\[N, H, W, C] 或 \[N, C, H, W]** 的单个张量，具体取决于所选布局。
* 批次大小 **N** 由缓冲区中内存块的数量推断得出。

**优势**：

* 并行推理：使模型能够同时处理多个帧，提高吞吐量并降低延迟。
* 高效的 GPU 利用：减少逐帧开销，最大化硬件加速能力。
* 灵活的输入处理：支持单流和多流场景，无需手动配置。

**张量布局**：

根据模型和配置，输出张量可能使用：

* **NHWC：** 交错布局（例如 \[4, 480, 640, 3]，批次大小为 4，RGB）。
* **NCHW：** 平面布局（例如 \[4, 3, 480, 640]），常用于 CNN。
* **NDHWC：** 用于需要时间深度的模型（例如 \[1, 4, 480, 640, 3]），其中 D 表示历史帧。

**qtimlvconverter** 会根据模型的输入签名和批次中的帧数自动选择合适的布局。

# 时间批处理

时间批处理扩展了标准批处理的概念，将同一流中随时间产生的多个帧分组到单个张量中。这种方法对于需要时间上下文的模型至关重要，例如：

* 动作识别（例如跨连续帧检测手势或活动）。
* 目标跟踪（例如跨帧保持身份）。
* 处理序列而非单张图像的 3D CNN 或基于 RNN 的视觉模型。

**工作原理：**

* 时间批处理不是聚合来自不同源的帧，而是收集来自同一流的 D 个连续帧。
* 这些帧被打包成形状如下的张量：
  * NDHWC：\[N, D, H, W, C]
    * N = 批次大小（同时处理的序列数量）
    * D = 深度（每个序列的帧数）
    * H、W = 空间维度
    * C = 通道（例如 RGB）
* qtimlvconverter 自动处理：
  * 根据配置的深度（D）进行帧累积。
  * 每帧的预处理（缩放、归一化、格式转换）。
  * 按模型所需的正确布局组装张量。

**优势：**

* 保留时间连续性，使模型能够学习运动模式。
* 提高依赖帧间关系的任务的推理准确性。
* 通过并行处理序列充分利用 GPU 资源。

**示例：**

* 对于期望 4 帧序列的模型：
  * 张量形状：\[1, 4, 480, 640, 3]（批次大小 = 1，深度 = 4，RGB）。
  * 各帧分别进行归一化和缩放，然后按时间顺序堆叠。

# 基于 ROI 处理的多阶段推理管道

在高级 AI 管道中，推理通常分多个阶段执行——每个阶段由预处理、推理和后处理组成。这些阶段可以在完整图像上运行，也可以在由前面阶段识别的特定感兴趣区域（ROI）上运行。

为支持这一点，**qtimlvconverter** 可以处理包含多个 **GstVideoRegionOfInterestMeta** 条目的缓冲区。这些 ROI 通常由上游 ML 组件或自定义插件生成，代表输入帧中需要进一步分析的目标区域。
默认情况下，**qtimlvconverter** 处理整幅图像，忽略任何 ROI 元数据。但是，通过 **mode** 属性进行配置后，它可以切换到基于 ROI 的处理，从而仅对标记为需要进一步推理的区域进行选择性变换。

**ROI 处理模式**

**mode** 属性定义了输入区域在转换为张量之前的处理和批处理方式。主要分为两大类：

* 图像批处理模式：
  * **image-batch-non-cumulative：** 立即处理每个缓冲区，无论批次大小如何。
  * **image-batch-cumulative：** 累积全帧输入，直到满足批次大小。
* ROI 批处理模式：
  * **roi-batch-non-cumulative：** 立即处理 ROI 元数据，丢弃多余条目。
  * **roi-batch-cumulative：** 累积 ROI 条目，直到满足批次大小。

这些模式可以根据模型的批次大小（N）和预期的输入速率，对延迟和资源利用率进行细粒度控制。

**子模式行为**

* **非累积（Non-Cumulative）**：
  在非累积子模式下，输入缓冲区在收到后立即处理，无论图像内存块或 ROI 元数据条目的数量是否满足模型指定的张量批次大小（N）。当多路复用流和/或 ROI 元数据的数量预计不会超过模型的批次大小（N）时，推荐使用此方式。超过批次大小（N）的任何 ROI 元数据或多路复用 GstMemory 块都将被丢弃。此子模式的一个潜在缺点是，如果批次未被完全填满——例如批次大小设置为 N=4 但只填充了三个位置——**推理**插件仍会处理整个批次，因未利用的位置导致资源效率降低。然而，非累积子模式的主要优势是**消除了处理延迟**：缓冲区不会为了积累额外输入以满足批次大小要求而被延后处理。这确保了及时处理和快速生成预测结果，使其适合对延迟要求极低的实时应用。
* **累积（Cumulative）：**
  在累积子模式下，输入缓冲区会被聚合，直到 ROI 元数据条目和/或多路复用的 **GstMemory** 块的数量满足模型所需的张量批次大小（N）。如果收到 GAP 缓冲区，或在 ROI 批处理模式下输入缓冲区不包含 ROI 元数据，累积可能会提前中断。这种累积策略会给处理管道引入可变的延迟，受帧生成间隔以及每个缓冲区接收到的 ROI 或多路复用图像数量等因素影响。累积子模式的主要优势在于所有输入的 ROI 元数据和多路复用 **GstMemory** 块都会被处理，确保没有任何数据因批次大小限制而被丢弃。当模型的批次大小（N）大于 1 且推理处理时间足够短时，特别推荐使用此模式，以便高效利用资源并全面处理可用的输入区域。

**非累积：**

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

**累积：**

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

# 预处理元数据

在某些情况下，后处理需要了解每个输入帧的预处理方式——例如它在输入张量中的位置、其尺寸，或批次中哪些帧是有效的。为支持这一点，**qtimlvconverter** 使用 **GstProtectionMeta** 将描述预处理详情的元数据附加到每个张量。推理插件随后将此元数据从其输入传播到输出，使后处理插件能够访问关于每一帧在预处理期间如何被处理的必要信息。

**GstProtectionMeta** 包含以下字段：

* **输入张量维度：**
  * input-tensor-width \[G\_TYPE\_UINT] - 指定帧被映射到的张量宽度（以像素为单位）。这是 qtimlvconverter 执行任何缩放操作后的最终宽度。
  * input-tensor-height \[G\_TYPE\_UINT] - 指定预处理后张量的高度（以像素为单位）。此值反映目标模型期望的输入尺寸。
* **输入张量中实际数据占据的区域：**
  * input-region-x \[G\_TYPE\_INT] - 张量中放置实际图像数据的区域的 X 坐标（水平偏移）。在保持宽高比时，可用于确定填充或定位。
  * input-region-y \[G\_TYPE\_INT] - 张量中图像数据起始区域的 Y 坐标（垂直偏移）。
  * input-region-width \[G\_TYPE\_INT] - 张量内实际图像内容的宽度。如果应用了填充，该值可能与 input-tensor-width 不同。
  * input-region-height \[G\_TYPE\_INT] - 张量内实际图像内容的高度。指示张量中有多少被真实图像数据占据。
* **批次序列信息：**
  * sequence-index \[G\_TYPE\_UINT] - 此条目在当前批次中的索引。例如，在大小为 4 的批次中，有效值为 0–3。
  * sequence-num-entries \[G\_TYPE\_UINT] - 批次中的条目总数。这有助于后处理插件理解批次上下文。
* **缓冲区的时间戳：**
  * timestamp \[G\_TYPE\_UINT64] - 缓冲区被 qtimlvconverter 处理时的时间戳。用于同步和延迟测量。
* **生成此批次条目的流 ID：**
  * stream-id \[G\_TYPE\_INT] \[可选] - 标识生成此批次条目的源流。在多流管道中，可用于将推理结果与其来源关联起来。
* **生成此批次条目的流缓冲区的时间戳：**
  * stream-timestamp \[G\_TYPE\_UINT64] \[可选] - 帧在预处理前来自源流的原始时间戳。为跟踪或分析保留时间上下文。
* **生成此批次条目的 ROI 元数据的 ID：**
  * source-region-id \[G\_TYPE\_INT] \[可选] - 如果帧来源于某个 ROI，此字段包含定义裁剪区域的 GstVideoRegionOfInterestMeta 条目的 ID。使下游组件能够将推理结果关联回原始 ROI。

# 用法

### 单摄像头流 — 将张量保存到文件

单摄像头流，手动设置 UINT8 ML GstCaps，输出张量保存到单独的文件中。

常见数据类型：

* `UINT8` — 量化模型的典型类型，范围 0–255
* `INT8` — 用于有符号量化模型，范围 −128 到 127
* `FLOAT16` / `FLOAT32` — 用于需要高精度的模型，归一化到 0.0–1.0 或 −1.0–1.0（需要偏移和缩放）

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

<Steps>
  <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/media/output
    ```
  </Step>

  <Step title="运行管道">
    ```bash Run the pipeline theme={null}
    gst-launch-1.0 -e --gst-debug=2 \
    qticamsrc ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! queue ! \
    qtimlvconverter ! neural-network/tensors,type=UINT8,dimensions="<<1,300,300,3>>" ! multifilesink location=$HOME/media/output/tensor_u8_%d.bin
    ```
  </Step>
</Steps>

### 实时摄像头流上的两阶段人体检测与姿态估计

在实时摄像头流上运行两个 ML 阶段的演示管道。第一阶段执行人体检测，并将结果附加到每一帧。[`qtiobjtracker`](qtiobjtracker) 随后跨帧关联检测到的人员，并添加持久的跟踪 ID。第二阶段使用基于 ROI 的预处理裁剪每个被跟踪的人员并运行姿态估计，生成叠加在显示器上的骨架关键点。

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

<Steps>
  <Step title="下载所需文件">
    | 文件                | 下载                                                                                                                                    | 保存为                            |
    | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ |
    | 人体足部检测模型          | [Qualcomm AI Hub — Person Foot Detection](https://aihub.qualcomm.com/iot/models/foot_track_net)                                       | `foot_track_net_w8a8.tflite`   |
    | 人体检测标签            | <a href="/SDKs/IMSDK/labels/foot_track_net.json" download="foot_track_net.json">foot\_track\_net.json</a>                             | `foot_track_net.json`          |
    | Foot track net 设置 | <a href="/SDKs/IMSDK/labels/foot_track_net_settings.json" download="foot_track_net_settings.json">foot\_track\_net\_settings.json</a> | `foot_track_net_settings.json` |
    | HRNet 姿态模型        | [Qualcomm AI Hub — HRNet Pose](https://aihub.qualcomm.com/iot/models/hrnet_pose)                                                      | `hrnet_pose_w8a8.tflite`       |
    | 姿态标签              | <a href="/SDKs/IMSDK/labels/hrnet.json" download="hrnet.json">hrnet.json</a>                                                          | `hrnet.json`                   |
    | HRNet 设置          | <a href="/SDKs/IMSDK/labels/hrnet_settings.json" download="hrnet_settings.json">hrnet\_settings.json</a>                              | `hrnet_settings.json`          |

    <Note>
      如果下载的任何文件是 `.zip` 压缩包，请在复制前先在主机上解压：
      `unzip filename.zip`
    </Note>
  </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 foot_track_net_w8a8.tflite         <user>@<device-ip>:$HOME/models/
      scp foot_track_net.json                <user>@<device-ip>:$HOME/labels/
      scp foot_track_net_settings.json       <user>@<device-ip>:$HOME/labels/
      scp hrnet_pose_w8a8.tflite             <user>@<device-ip>:$HOME/models/
      scp hrnet.json                         <user>@<device-ip>:$HOME/labels/
      scp hrnet_settings.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}
    export MODEL_NAME_1=foot_track_net_w8a8.tflite
    export LABELS_NAME_1=foot_track_net.json
    export LABELS_NAME_2=foot_track_net_settings.json
    export MODEL_NAME_2=hrnet_pose_w8a8.tflite
    export LABELS_NAME_3=hrnet.json
    export LABELS_NAME_4=hrnet_settings.json
    ```
  </Step>

  <Step title="运行管道">
    ```bash Run the pipeline theme={null}
    gst-launch-1.0 -e --gst-debug=2 \
    qtimlvconverter name=stage_01_preproc mode=image-batch-non-cumulative \
    qtimltflite name=stage_01_inference delegate=external external-delegate-path=libQnnTFLiteDelegate.so \
    external-delegate-options="QNNExternalDelegate,backend_type=htp,log_level=(string)1;" \
    model=$HOME/models/$MODEL_NAME_1 \
    qtimlpostprocess name=stage_01_postproc results=10 module=qpd labels=$HOME/labels/$LABELS_NAME_1 \
    settings=$HOME/labels/$LABELS_NAME_2 \
    qtimlvconverter name=stage_02_preproc image-disposition=centre mode=roi-batch-cumulative \
    qtimltflite name=stage_02_inference delegate=external external-delegate-path=libQnnTFLiteDelegate.so \
    external-delegate-options="QNNExternalDelegate,backend_type=htp,htp_performance_mode=(string)2,log_level=(string)1;" \
    model=$HOME/models/$MODEL_NAME_2 \
    qtimlpostprocess name=stage_02_postproc results=1 module=hrnet labels=$HOME/labels/$LABELS_NAME_3 \
    settings=$HOME/labels/$LABELS_NAME_4 \
    qticamsrc ! video/x-raw,format=NV12,width=1920,height=1080,framerate=30/1 ! queue ! tee name=t_split_1 \
    t_split_1. ! queue ! metamux_1. \
    t_split_1. ! queue ! stage_01_preproc. stage_01_preproc. ! queue ! stage_01_inference. stage_01_inference. ! queue ! \
    stage_01_postproc. stage_01_postproc. ! text/x-raw ! queue ! metamux_1. \
    qtimetamux name=metamux_1 ! queue ! tee name=t_split_2 \
    t_split_2. ! queue ! metamux_2. \
    t_split_2. ! queue ! stage_02_preproc. stage_02_preproc. ! queue ! stage_02_inference. stage_02_inference. ! queue ! \
    stage_02_postproc. stage_02_postproc. ! text/x-raw ! queue ! metamux_2. \
    qtimetamux name=metamux_2 ! queue ! qtivoverlay ! queue ! waylandsink fullscreen=true sync=false async=false
    ```
  </Step>
</Steps>

### 使用合成器的四源批处理目标检测

对 4 个源进行批处理的演示管道。运行检测推理，并通过合成器将结果叠加到屏幕上。

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

<Steps>
  <Step title="下载所需文件">
    | 文件                     | 下载                                                                                                                            | 保存为                              |
    | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -------------------------------- |
    | Yolov8 检测 W8A8 批次 4 模型 | [从 Qualcomm AI Hub 导出](https://github.com/qualcomm/ai-hub-models/blob/v0.55.0/src/qai_hub_models/models/yolov8_det/README.md) | `yolov8_det_w8a8_batch_4.tflite` |
    | 检测标签                   | <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_batch_4.tflite        <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}
    export MODEL_NAME=yolov8_det_w8a8_batch_4.tflite
    export LABELS_NAME=yolov8.json
    export SRC_VIDEO_NAME_1=Draw_1080p_180s_30FPS.mp4
    export SRC_VIDEO_NAME_2=Draw_1080p_180s_30FPS.mp4
    export SRC_VIDEO_NAME_3=Draw_1080p_180s_30FPS.mp4
    export SRC_VIDEO_NAME_4=Draw_1080p_180s_30FPS.mp4
    ```
  </Step>

  <Step title="运行管道">
    ```bash Run the pipeline theme={null}
    gst-launch-1.0 -e --gst-debug=2 \
    qtimltflite name=inference delegate=external external-delegate-path=libQnnTFLiteDelegate.so external-delegate-options="QNNExternalDelegate,backend_type=htp,htp_performance_mode=(string)2;" model=$HOME/models/$MODEL_NAME \
    filesrc location=$HOME/media/$SRC_VIDEO_NAME_1 ! qtdemux ! queue ! h264parse ! v4l2h264dec capture-io-mode=4 output-io-mode=4 ! video/x-raw ! qtivtransform ! video/x-raw,format=NV12,width=640,height=360 ! queue ! tee name=tee_0 \
    filesrc location=$HOME/media/$SRC_VIDEO_NAME_2 ! qtdemux ! queue ! h264parse ! v4l2h264dec capture-io-mode=4 output-io-mode=4 ! video/x-raw ! qtivtransform ! video/x-raw,format=NV12,width=640,height=360 ! queue ! tee name=tee_1 \
    filesrc location=$HOME/media/$SRC_VIDEO_NAME_3 ! qtdemux ! queue ! h264parse ! v4l2h264dec capture-io-mode=4 output-io-mode=4 ! video/x-raw ! qtivtransform ! video/x-raw,format=NV12,width=640,height=360 ! queue ! tee name=tee_2 \
    filesrc location=$HOME/media/$SRC_VIDEO_NAME_4 ! qtdemux ! queue ! h264parse ! v4l2h264dec capture-io-mode=4 output-io-mode=4 ! video/x-raw ! qtivtransform ! video/x-raw,format=NV12,width=640,height=360 ! queue ! tee name=tee_3 \
    tee_0. ! video/x-raw,format=NV12 ! mixer. \
    tee_0. ! video/x-raw,format=NV12 ! batch. \
    tee_1. ! video/x-raw,format=NV12 ! mixer. \
    tee_1. ! video/x-raw,format=NV12 ! batch. \
    tee_2. ! video/x-raw,format=NV12 ! mixer. \
    tee_2. ! video/x-raw,format=NV12 ! batch. \
    tee_3. ! video/x-raw,format=NV12 ! mixer. \
    tee_3. ! video/x-raw,format=NV12 ! batch. \
    qtibatch name=batch ! queue ! qtimlvconverter ! queue ! inference. inference. ! queue ! qtimldemux name=mldemux \
    mldemux. ! queue ! qtimlpostprocess results=10 module=yolov8 labels=$HOME/labels/$LABELS_NAME settings="{\"confidence\": 70.0}" ! video/x-raw,width=640,height=360 ! queue ! mixer. \
    mldemux. ! queue ! qtimlpostprocess results=10 module=yolov8 labels=$HOME/labels/$LABELS_NAME settings="{\"confidence\": 70.0}" ! video/x-raw,width=640,height=360 ! queue ! mixer. \
    mldemux. ! queue ! qtimlpostprocess results=10 module=yolov8 labels=$HOME/labels/$LABELS_NAME settings="{\"confidence\": 70.0}" ! video/x-raw,width=640,height=360 ! queue ! mixer. \
    mldemux. ! queue ! qtimlpostprocess results=10 module=yolov8 labels=$HOME/labels/$LABELS_NAME settings="{\"confidence\": 70.0}" ! video/x-raw,width=640,height=360 ! queue ! mixer. \
    qtivcomposer name=mixer \
    sink_0::position="<0, 0>" sink_0::dimensions="<960, 540>" \
    sink_1::position="<960,  0>" sink_1::dimensions="<960, 540>" \
    sink_2::position="<0, 540>" sink_2::dimensions="<960, 540>" \
    sink_3::position="<960, 540>" sink_3::dimensions="<960, 540>" \
    sink_4::position="<0, 0>" sink_4::dimensions="<960, 540>" \
    sink_5::position="<960, 0>" sink_5::dimensions="<960, 540>" \
    sink_6::position="<0, 540>" sink_6::dimensions="<960, 540>" \
    sink_7::position="<960, 540>" sink_7::dimensions="<960, 540>" \
    mixer. ! video/x-raw,format=NV12 ! queue ! waylandsink sync=false fullscreen=true
    ```
  </Step>
</Steps>
