VPI - 视觉编程接口

3.2 版本

最小值/最大值位置

概述

最小值/最大值位置算法对输入图像执行 2D 搜索操作。该算法查找像素的最小值和最大值,从而得到最小值和最大值的两组像素位置。这些位置是与全局最小值或最大值完全匹配的像素的 \((x,y)\) 坐标。此操作可用于定位图像上的峰值,无论是最高峰值、最低峰值还是两者兼有。

此示例显示了左侧的输入图像,以及右侧对应的最小值(蓝色)和最大值(红色)位置。

输入输出

实现

该算法在输入图像中搜索最小值和最大值。每个与最小值匹配的像素的位置都存储在输出数组中。最大值的操作在第二个输出数组中完成。可能会找到同一值的多个位置,无论是最小值还是最大值。

图像中的位置是一个关键点,其坐标为 \((x, y)\),分别对应于基于矩阵的坐标 \((j, i)\)。位置存储在用户提供的输出数组中,直到达到数组容量,该容量在数组创建时定义。最小值和最大值输出数组都这样做。每个数组返回的最大位置数可能不同,因为它们对应的容量可能不同。用户可以选择不提供输出数组(通过在参数中传递 NULL),在这种情况下,将不会搜索相应的位置。

C API 函数

有关实现该算法的限制、约束和后端的列表,请查阅以下函数的参考文档

函数描述
vpiCreateMinMaxLoc vpiSubmitMinMaxLoc 创建有效载荷。
vpiSubmitMinMaxLoc 在图像中查找最小值和最大值位置。

用法

语言
  1. 导入 VPI 模块
    import vpi
  2. 使用 CPU 后端在输入图像上运行 MinMaxLoc 搜索。输入是 VPI 图像。
    with vpi.Backend.CPU
    min_coords, max_coords = input.minmaxloc(min_capacity=10000, max_capacity=10000)
  3. (可选)检索最小值和最大值。
    1. 锁定输入图像和最小值/最大值输出数组,以高效访问其内容。
      with input.rlock_cpu() as in_data, min_coords.rlock_cpu() as min_data, max_coords.rlock_cpu() as max_data
    2. 检索具有最小值和最大值的第一个像素的坐标。 (x,y) 坐标被交换为 (y,x) 并转换为元组,适用于 2D numpy 数组索引。
      min_loc = tuple(min_data[0].astype(int)[::-1])
      max_loc = tuple(max_data[0].astype(int)[::-1])
    3. 使用这些坐标中的第一个来检索最小值/最大值像素值。
      min_value = in_data[min_loc]
      max_value = in_data[max_loc]
  1. 初始化阶段
    1. 包含定义所需函数的头文件。
      声明在图像中执行最小值和最大值位置查找的函数。
    2. 定义输入图像对象。
      VPIImage input = /*...*/;
      struct VPIImageImpl * VPIImage
      图像的句柄。
      定义: Types.h:256
    3. 创建将包含处理所需的所有临时缓冲区的有效载荷。有效载荷创建需要输入的尺寸和格式。
      vpiImageGetFormat(input, &format);
      int width, height;
      vpiImageGetSize(input, &width, &height);
      VPIPayload payload;
      vpiCreateMinMaxLoc(VPI_BACKEND_CPU, width, height, format, &payload);
      uint64_t VPIImageFormat
      预定义的图像格式。
      VPIStatus vpiImageGetFormat(VPIImage img, VPIImageFormat *format)
      获取图像格式。
      VPIStatus vpiImageGetSize(VPIImage img, int32_t *width, int32_t *height)
      获取图像尺寸(以像素为单位)。
      VPIStatus vpiCreateMinMaxLoc(uint64_t backends, int32_t imageWidth, int32_t imageHeight, VPIImageFormat imageFormat, VPIPayload *payload)
      为 vpiSubmitMinMaxLoc 创建有效载荷。
      struct VPIPayloadImpl * VPIPayload
      算法有效载荷的句柄。
      定义: Types.h:268
      @ VPI_BACKEND_CPU
      CPU 后端。
      定义: Types.h:92
    4. 创建用于存储最小值和最大值坐标的输出数组。在此示例中,它们的容量设置为 10,000,这限制了要查找的位置数量。
      VPIArray minCoords;
      VPIArray maxCoords;
      VPIStatus vpiArrayCreate(int32_t capacity, VPIArrayType type, uint64_t flags, VPIArray *array)
      创建一个空数组实例。
      struct VPIArrayImpl * VPIArray
      数组的句柄。
      定义: Types.h:232
      @ VPI_ARRAY_TYPE_KEYPOINT_F32
      VPIKeypointF32 元素。
      定义: ArrayType.h:77
    5. 创建将在其中提交算法以供执行的流。
      VPIStream stream;
      vpiStreamCreate(0, &stream);
      struct VPIStreamImpl * VPIStream
      流的句柄。
      定义: Types.h:250
      VPIStatus vpiStreamCreate(uint64_t flags, VPIStream *stream)
      创建一个流实例。
  2. 处理阶段
    1. 将算法提交到流,传递输入图像和输出数组。在此示例中,它将由 CPU 后端执行。
      vpiSubmitMinMaxLoc(stream, VPI_BACKEND_CPU, payload, input, minCoords, maxCoords);
      VPIStatus vpiSubmitMinMaxLoc(VPIStream stream, uint64_t backend, VPIPayload payload, VPIImage input, VPIArray minCoords, VPIArray maxCoords)
      在图像中查找最小值和最大值位置。
    2. (可选)检索最小值和最大值。
      1. 同步流以确保操作完成
        vpiStreamSync(stream);
        VPIStatus vpiStreamSync(VPIStream stream)
        阻塞调用线程,直到此流队列中的所有提交命令完成(队列为空)...
      2. 锁定输入图像和最小值/最大值输出数组。
        VPIImageData inputImageData;
        VPIArrayData minCoordsData, maxCoordsData;
        VPIStatus vpiArrayLockData(VPIArray array, VPILockMode mode, VPIArrayBufferType bufType, VPIArrayData *data)
        获取数组对象的锁并返回数组内容。
        @ VPI_ARRAY_BUFFER_HOST_AOS
        主机可访问的结构体数组。
        定义: Array.h:146
        存储有关数组特性和内容的信息。
        定义: Array.h:168
        VPIStatus vpiImageLockData(VPIImage img, VPILockMode mode, VPIImageBufferType bufType, VPIImageData *data)
        获取图像对象的锁并返回图像内容。
        @ VPI_IMAGE_BUFFER_HOST_PITCH_LINEAR
        主机可访问,平面采用 pitch-linear 内存布局。
        定义: Image.h:172
        存储有关图像特性和内容的信息。
        定义: Image.h:234
        @ VPI_LOCK_READ
        仅锁定内存以进行读取。
        定义: Types.h:617
      3. 检索找到的第一个最小值和最大值的坐标。
        VPIKeypointF32 *min_coords = (VPIKeypointF32 *)minCoordsData.buffer.aos.data;
        VPIKeypointF32 *max_coords = (VPIKeypointF32 *)maxCoordsData.buffer.aos.data;
        int min_i = min_coords[0].y;
        int min_j = min_coords[0].x;
        int max_i = max_coords[0].y;
        int max_j = max_coords[0].x;
        void * data
        指向数组的第一个元素。
        定义: Array.h:135
        VPIArrayBuffer buffer
        存储数组内容。
        定义: Array.h:175
        VPIArrayBufferAOS aos
        以结构体数组布局存储的数组。
        定义: Array.h:162
        float x
        关键点的 x 坐标。
        定义: Types.h:335
        float y
        关键点的 y 坐标。
        定义: Types.h:336
        存储 float32 关键点坐标。坐标相对于图像的左上角。
        定义: Types.h:334
      4. 使用这些坐标作为输入图像内容的 2D 索引,以检索最小值/最大值像素值。这里假设输入图像格式为 VPI_IMAGE_FORMAT_U8。对于其他格式,必须采用不同的索引方法。
        // 假设输入图像是灰度图像(只有一个平面)。
        assert(inputImageData.buffer.pitch.numPlanes == 1);
        void *imgData = inputImageData.buffer.pitch.planes[0].data;
        int imgPitchBytes = inputImageData.buffer.pitch.planes[0].pitchBytes;
        // 假设该平面具有 8 位无符号整数类型。
        assert(inputImageData.buffer.pitch.planes[0].pixelType == VPI_PIXEL_TYPE_U8);
        typedef unsigned char Pixel;
        typedef unsigned char Byte;
        const Pixel *min_row = (const Pixel *)((const Byte *)imgData + min_i * imgPitchBytes);
        const Pixel *max_row = (const Pixel *)((const Byte *)imgData + max_i * imgPitchBytes);
        unsigned char min_value = min_row[min_j];
        unsigned char max_value = max_row[max_j];
        #define VPI_PIXEL_TYPE_U8
        单通道 8 位无符号值。
        定义: PixelType.h:88
        VPIImageBuffer buffer
        存储图像内容。
        定义: Image.h:241
        VPIImagePlanePitchLinear planes[VPI_MAX_PLANE_COUNT]
        pitch-linear 布局中所有图像平面的数据。
        定义: Image.h:160
        VPIImageBufferPitchLinear pitch
        以 pitch-linear 布局存储的图像。
        定义: Image.h:210
        void * data
        指向此平面的第一行。
        定义: Image.h:141
        int32_t numPlanes
        平面数量。
        定义: Image.h:156
        VPIPixelType pixelType
        此平面内每个像素的类型。
        定义: Image.h:115
        int32_t pitchBytes
        一行开头与前一行开头之间的字节差。
        定义: Image.h:134
      5. 由于不再需要图像和数组内容,因此必须解锁它们。
        vpiArrayUnlock(maxCoords);
        vpiArrayUnlock(minCoords);
        VPIStatus vpiArrayUnlock(VPIArray array)
        释放数组对象上的锁。
        VPIStatus vpiImageUnlock(VPIImage img)
        释放图像对象上的锁。
  3. 清理阶段
    1. 释放流、有效载荷以及输入图像和输出数组所持有的资源。
      vpiArrayDestroy(minCoords);
      vpiArrayDestroy(maxCoords);
      void vpiArrayDestroy(VPIArray array)
      销毁数组实例。
      void vpiImageDestroy(VPIImage img)
      销毁图像实例。
      void vpiPayloadDestroy(VPIPayload payload)
      释放有效载荷对象和所有相关资源。
      void vpiStreamDestroy(VPIStream stream)
      销毁流实例并释放所有硬件资源。

有关更多信息,请参阅 VPI - 视觉编程接口 的 “C API 参考” 部分中的 MinMaxLoc

性能

有关如何使用下表中的性能表的信息,请参阅算法性能表
在比较测量结果之前,请查阅比较算法运行时间
有关性能基准测试方式的更多信息,请参阅性能基准

 -