VPI - 视觉编程接口

3.2 版本

Harris 角点检测器

概述

此算法实现了 Harris 关键点检测算子,该算子常用于检测图像的关键点和推断图像的特征。

首先应用标准 Harris 检测器算法,如 [1] 中所述。之后,对结果应用非极大值抑制剪枝过程,以去除多个或伪关键点。

输入参数输出关键点

\begin{align*} \mathit{gradientSize} &= 5 \\ \mathit{blockSize} &= 5 \\ \mathit{strengthThresh} &= 20 \\ \mathit{sensitivity} &= 0.01 \\ \mathit{minNMSDistance} &= 8 \end{align*}

实现

  1. 使用以下滤波器之一计算输入的空间梯度,具体取决于 VPIHarrisCornerDetectorParams::gradientSize 的值
    • 对于 gradientSize = 3

      \begin{align*} \mathit{sobel}_x &= \frac{1}{4} \cdot \begin{bmatrix} 1 \\ 2 \\ 1 \end{bmatrix} \cdot \begin{bmatrix} -1 & 0 & 1 \end{bmatrix} \\ \mathit{sobel}_y &= (\mathit{sobel}_x)^\intercal \end{align*}

    • 对于 gradientSize = 5

      \begin{align*} \mathit{sobel}_x &= \frac{1}{16} \cdot \begin{bmatrix} 1 \\ 4 \\ 6 \\ 4 \\ 1 \end{bmatrix} \cdot \begin{bmatrix} -1 & -2 & 0 & 2 & 1 \end{bmatrix} \\ \mathit{sobel}_y &= (\mathit{sobel}_x)^\intercal \end{align*}

    • 对于 gradientSize = 7

      \begin{align*} \mathit{sobel}_x &= \frac{1}{64} \cdot \begin{bmatrix} 1 \\ 6 \\ 15 \\ 20 \\ 15 \\ 6 \\ 1 \end{bmatrix} \cdot \begin{bmatrix} -1 & -4 & -5 & 0 & 5 & 4 & 1 \end{bmatrix} \\ \mathit{sobel}_y &= (\mathit{sobel}_x)^\intercal \end{align*}

  2. 在块窗口内,为每个像素计算梯度协方差矩阵(结构张量),如下所述:

    \[ M = \sum_{p \in B}\begin{bmatrix}I_x^2(p) & I_x(p) I_y(p) \\ I_x(p) I_y(p) & I_y^2(p) \end{bmatrix} \]

    其中

    • p 是 B 内的像素坐标,B 是大小为 3x3、5x5 或 7x7 的块窗口。
    • \(I(p)\) 是输入图像
    • \( I_x(p) = I(p) * \mathit{sobel}_x \)
    • \( I_y(p) = I(p) * \mathit{sobel}_y \)
  3. 使用灵敏度因子计算 Harris 响应得分

    \[ R = \mathit{det}(M) - k \cdot \mathit{trace}^2(M ) \]

    其中 k 是灵敏度因子

  4. 应用阈值强度标准,剪枝响应 <= VPIHarrisCornerDetectorParams::strengthThresh 的关键点。
  5. 应用非极大值抑制剪枝过程。

    此过程将输入图像分割成 2D 单元格网格。它选择单元格内响应得分最高的单个角点。如果单元格内有多个角点具有相同的响应得分,则选择右下角的角点。

C API 函数

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

函数描述
vpiInitHarrisCornerDetectorParams 使用默认值初始化 VPIHarrisCornerDetectorParams
vpiCreateHarrisCornerDetector 创建 Harris 角点检测器 有效负载。
vpiSubmitHarrisCornerDetector Harris 角点检测器 操作提交到流。

用法

语言
  1. 导入 VPI 模块
    import vpi
  2. 使用 CUDA 后端在输入图像上执行算法。返回两个 VPI 数组,一个包含关键点位置,另一个包含得分。关键点数组的类型为 vpi.Type.KEYPOINT,得分数组的类型为 vpi.Type.U32
    with vpi.Backend.CUDA
    keypoints, scores = input.harriscorners(sensitivity=0.01)
  1. 初始化阶段
    1. 包含定义 Harris 角点检测器函数的头文件。
      声明实现 Harris 角点检测器算法的函数。
    2. 定义输入图像对象。
      VPIImage input = /*...*/;
      struct VPIImageImpl * VPIImage
      图像的句柄。
      Definition: Types.h:256
    3. 创建将存储关键点及其得分的输出数组。
      VPIArray keypoints;
      VPIArray scores;
      vpiArrayCreate(8192, VPI_ARRAY_TYPE_U32, 0, &scores);
      VPIStatus vpiArrayCreate(int32_t capacity, VPIArrayType type, uint64_t flags, VPIArray *array)
      创建空数组实例。
      struct VPIArrayImpl * VPIArray
      数组的句柄。
      Definition: Types.h:232
      @ VPI_ARRAY_TYPE_U32
      无符号 32 位。
      Definition: ArrayType.h:76
      @ VPI_ARRAY_TYPE_KEYPOINT_F32
      VPIKeypointF32 元素。
      Definition: ArrayType.h:77
    4. 由于此算法需要临时内存缓冲区,因此在 CUDA 后端为其创建有效负载。
      int32_t w, h;
      vpiImageGetSize(input, &w, &h);
      VPIPayload harris;
      VPIStatus vpiCreateHarrisCornerDetector(uint64_t backends, int32_t inputWidth, int32_t inputHeight, VPIPayload *payload)
      创建 Harris 角点检测器有效负载。
      VPIStatus vpiImageGetSize(VPIImage img, int32_t *width, int32_t *height)
      获取图像尺寸(以像素为单位)。
      struct VPIPayloadImpl * VPIPayload
      算法有效负载的句柄。
      Definition: Types.h:268
      @ VPI_BACKEND_CUDA
      CUDA 后端。
      Definition: Types.h:93
    5. 创建将在其中提交算法以执行的流。
      VPIStream stream;
      vpiStreamCreate(0, &stream);
      struct VPIStreamImpl * VPIStream
      流的句柄。
      Definition: Types.h:250
      VPIStatus vpiStreamCreate(uint64_t flags, VPIStream *stream)
      创建流实例。
  2. 处理阶段
    1. 使用默认参数初始化配置结构,并将灵敏度设置为新值。
      params.sensitivity = 0.01;
      float sensitivity
      指定 Harris-Stephens 方程的灵敏度阈值。
      Definition: HarrisCorners.h:97
      VPIStatus vpiInitHarrisCornerDetectorParams(VPIHarrisCornerDetectorParams *params)
      使用默认值初始化 VPIHarrisCornerDetectorParams。
      定义 vpiSubmitHarrisCornerDetector 参数的结构体。
      Definition: HarrisCorners.h:82
    2. 将算法及其参数提交到流。它将由与有效负载关联的 CUDA 后端执行。
      vpiSubmitHarrisCornerDetector(stream, 0, harris, input, keypoints, scores, &params);
      VPIStatus vpiSubmitHarrisCornerDetector(VPIStream stream, uint64_t backend, VPIPayload payload, VPIImage input, VPIArray outFeatures, VPIArray outScores, const VPIHarrisCornerDetectorParams *params)
      将 Harris 角点检测器操作提交到流。
    3. 可选地,等待直到处理完成。
      vpiStreamSync(stream);
      VPIStatus vpiStreamSync(VPIStream stream)
      阻塞调用线程,直到此流队列中的所有提交命令完成(队列为空)...
  3. 清理阶段
    1. 释放流、有效负载、输入图像和输出数组所持有的资源。
      vpiArrayDestroy(keypoints);
      vpiArrayDestroy(scores);
      void vpiArrayDestroy(VPIArray array)
      销毁数组实例。
      void vpiImageDestroy(VPIImage img)
      销毁图像实例。
      void vpiPayloadDestroy(VPIPayload payload)
      释放有效负载对象和所有关联的资源。
      void vpiStreamDestroy(VPIStream stream)
      销毁流实例并释放所有硬件资源。

有关更多信息,请参阅《VPI - 视觉编程接口》的“C API 参考”部分中的“Harris 角点”。

性能

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

 - 

参考

  1. C. Harris, M. Stephens (1988), “组合角点和边缘检测器”
    Alvey 视觉会议论文集,第 147-151 页。