概述
最小值/最大值位置算法对输入图像执行 2D 搜索操作。该算法查找像素的最小值和最大值,从而得到最小值和最大值的两组像素位置。这些位置是与全局最小值或最大值完全匹配的像素的 \((x,y)\) 坐标。此操作可用于定位图像上的峰值,无论是最高峰值、最低峰值还是两者兼有。
此示例显示了左侧的输入图像,以及右侧对应的最小值(蓝色)和最大值(红色)位置。
输入 | 输出 |
| |
实现
该算法在输入图像中搜索最小值和最大值。每个与最小值匹配的像素的位置都存储在输出数组中。最大值的操作在第二个输出数组中完成。可能会找到同一值的多个位置,无论是最小值还是最大值。
图像中的位置是一个关键点,其坐标为 \((x, y)\),分别对应于基于矩阵的坐标 \((j, i)\)。位置存储在用户提供的输出数组中,直到达到数组容量,该容量在数组创建时定义。最小值和最大值输出数组都这样做。每个数组返回的最大位置数可能不同,因为它们对应的容量可能不同。用户可以选择不提供输出数组(通过在参数中传递 NULL
),在这种情况下,将不会搜索相应的位置。
C API 函数
有关实现该算法的限制、约束和后端的列表,请查阅以下函数的参考文档
用法
语言
- 导入 VPI 模块
- 使用 CPU 后端在输入图像上运行 MinMaxLoc 搜索。输入是 VPI 图像。
with vpi.Backend.CPU
min_coords, max_coords = input.minmaxloc(min_capacity=10000, max_capacity=10000)
- (可选)检索最小值和最大值。
- 锁定输入图像和最小值/最大值输出数组,以高效访问其内容。
with input.rlock_cpu() as in_data, min_coords.rlock_cpu() as min_data, max_coords.rlock_cpu() as max_data
- 检索具有最小值和最大值的第一个像素的坐标。 (x,y) 坐标被交换为 (y,x) 并转换为元组,适用于 2D numpy 数组索引。
min_loc = tuple(min_data[0].astype(int)[::-1])
max_loc = tuple(max_data[0].astype(int)[::-1])
- 使用这些坐标中的第一个来检索最小值/最大值像素值。
min_value = in_data[min_loc]
max_value = in_data[max_loc]
- 初始化阶段
- 包含定义所需函数的头文件。
- 定义输入图像对象。
struct VPIImageImpl * VPIImage
图像的句柄。
- 创建将包含处理所需的所有临时缓冲区的有效载荷。有效载荷创建需要输入的尺寸和格式。
int width, height;
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
算法有效载荷的句柄。
- 创建用于存储最小值和最大值坐标的输出数组。在此示例中,它们的容量设置为 10,000,这限制了要查找的位置数量。
VPIStatus vpiArrayCreate(int32_t capacity, VPIArrayType type, uint64_t flags, VPIArray *array)
创建一个空数组实例。
struct VPIArrayImpl * VPIArray
数组的句柄。
@ VPI_ARRAY_TYPE_KEYPOINT_F32
VPIKeypointF32 元素。
- 创建将在其中提交算法以供执行的流。
struct VPIStreamImpl * VPIStream
流的句柄。
VPIStatus vpiStreamCreate(uint64_t flags, VPIStream *stream)
创建一个流实例。
- 处理阶段
- 将算法提交到流,传递输入图像和输出数组。在此示例中,它将由 CPU 后端执行。
VPIStatus vpiSubmitMinMaxLoc(VPIStream stream, uint64_t backend, VPIPayload payload, VPIImage input, VPIArray minCoords, VPIArray maxCoords)
在图像中查找最小值和最大值位置。
- (可选)检索最小值和最大值。
- 同步流以确保操作完成
VPIStatus vpiStreamSync(VPIStream stream)
阻塞调用线程,直到此流队列中的所有提交命令完成(队列为空)...
- 锁定输入图像和最小值/最大值输出数组。
VPIStatus vpiArrayLockData(VPIArray array, VPILockMode mode, VPIArrayBufferType bufType, VPIArrayData *data)
获取数组对象的锁并返回数组内容。
@ VPI_ARRAY_BUFFER_HOST_AOS
主机可访问的结构体数组。
VPIStatus vpiImageLockData(VPIImage img, VPILockMode mode, VPIImageBufferType bufType, VPIImageData *data)
获取图像对象的锁并返回图像内容。
@ VPI_IMAGE_BUFFER_HOST_PITCH_LINEAR
主机可访问,平面采用 pitch-linear 内存布局。
@ VPI_LOCK_READ
仅锁定内存以进行读取。
- 检索找到的第一个最小值和最大值的坐标。
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;
VPIArrayBuffer buffer
存储数组内容。
VPIArrayBufferAOS aos
以结构体数组布局存储的数组。
存储 float32 关键点坐标。坐标相对于图像的左上角。
- 使用这些坐标作为输入图像内容的 2D 索引,以检索最小值/最大值像素值。这里假设输入图像格式为 VPI_IMAGE_FORMAT_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 位无符号值。
VPIImageBuffer buffer
存储图像内容。
VPIImagePlanePitchLinear planes[VPI_MAX_PLANE_COUNT]
pitch-linear 布局中所有图像平面的数据。
VPIImageBufferPitchLinear pitch
以 pitch-linear 布局存储的图像。
VPIPixelType pixelType
此平面内每个像素的类型。
int32_t pitchBytes
一行开头与前一行开头之间的字节差。
- 由于不再需要图像和数组内容,因此必须解锁它们。
VPIStatus vpiArrayUnlock(VPIArray array)
释放数组对象上的锁。
VPIStatus vpiImageUnlock(VPIImage img)
释放图像对象上的锁。
- 清理阶段
- 释放流、有效载荷以及输入图像和输出数组所持有的资源。
void vpiArrayDestroy(VPIArray array)
销毁数组实例。
void vpiImageDestroy(VPIImage img)
销毁图像实例。
void vpiPayloadDestroy(VPIPayload payload)
释放有效载荷对象和所有相关资源。
void vpiStreamDestroy(VPIStream stream)
销毁流实例并释放所有硬件资源。
有关更多信息,请参阅 VPI - 视觉编程接口 的 “C API 参考” 部分中的 MinMaxLoc。
性能
有关如何使用下表中的性能表的信息,请参阅算法性能表。
在比较测量结果之前,请查阅比较算法运行时间。
有关性能基准测试方式的更多信息,请参阅性能基准。
-