概述
此算法实现了 Harris 关键点检测算子,该算子常用于检测图像的关键点和推断图像的特征。
首先应用标准 Harris 检测器算法,如 [1] 中所述。之后,对结果应用非极大值抑制剪枝过程,以去除多个或伪关键点。
输入 | 参数 | 输出关键点 |
| \begin{align*} \mathit{gradientSize} &= 5 \\ \mathit{blockSize} &= 5 \\ \mathit{strengthThresh} &= 20 \\ \mathit{sensitivity} &= 0.01 \\ \mathit{minNMSDistance} &= 8 \end{align*}
| |
实现
- 使用以下滤波器之一计算输入的空间梯度,具体取决于 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*}
在块窗口内,为每个像素计算梯度协方差矩阵(结构张量),如下所述:
\[ 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 \)
使用灵敏度因子计算 Harris 响应得分
\[ R = \mathit{det}(M) - k \cdot \mathit{trace}^2(M ) \]
其中 k 是灵敏度因子
- 应用阈值强度标准,剪枝响应 <= VPIHarrisCornerDetectorParams::strengthThresh 的关键点。
应用非极大值抑制剪枝过程。
此过程将输入图像分割成 2D 单元格网格。它选择单元格内响应得分最高的单个角点。如果单元格内有多个角点具有相同的响应得分,则选择右下角的角点。
C API 函数
有关实现该算法的限制、约束和后端列表,请查阅以下函数的参考文档
用法
语言
- 导入 VPI 模块
- 使用 CUDA 后端在输入图像上执行算法。返回两个 VPI 数组,一个包含关键点位置,另一个包含得分。关键点数组的类型为
vpi.Type.KEYPOINT
,得分数组的类型为 vpi.Type.U32
。with vpi.Backend.CUDA
keypoints, scores = input.harriscorners(sensitivity=0.01)
- 初始化阶段
- 包含定义 Harris 角点检测器函数的头文件。
- 定义输入图像对象。
struct VPIImageImpl * VPIImage
图像的句柄。
- 创建将存储关键点及其得分的输出数组。
VPIStatus vpiArrayCreate(int32_t capacity, VPIArrayType type, uint64_t flags, VPIArray *array)
创建空数组实例。
struct VPIArrayImpl * VPIArray
数组的句柄。
@ VPI_ARRAY_TYPE_U32
无符号 32 位。
@ VPI_ARRAY_TYPE_KEYPOINT_F32
VPIKeypointF32 元素。
- 由于此算法需要临时内存缓冲区,因此在 CUDA 后端为其创建有效负载。
int32_t w, h;
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
算法有效负载的句柄。
@ VPI_BACKEND_CUDA
CUDA 后端。
- 创建将在其中提交算法以执行的流。
struct VPIStreamImpl * VPIStream
流的句柄。
VPIStatus vpiStreamCreate(uint64_t flags, VPIStream *stream)
创建流实例。
- 处理阶段
- 使用默认参数初始化配置结构,并将灵敏度设置为新值。
float sensitivity
指定 Harris-Stephens 方程的灵敏度阈值。
VPIStatus vpiInitHarrisCornerDetectorParams(VPIHarrisCornerDetectorParams *params)
使用默认值初始化 VPIHarrisCornerDetectorParams。
定义 vpiSubmitHarrisCornerDetector 参数的结构体。
- 将算法及其参数提交到流。它将由与有效负载关联的 CUDA 后端执行。
VPIStatus vpiSubmitHarrisCornerDetector(VPIStream stream, uint64_t backend, VPIPayload payload, VPIImage input, VPIArray outFeatures, VPIArray outScores, const VPIHarrisCornerDetectorParams *params)
将 Harris 角点检测器操作提交到流。
- 可选地,等待直到处理完成。
VPIStatus vpiStreamSync(VPIStream stream)
阻塞调用线程,直到此流队列中的所有提交命令完成(队列为空)...
- 清理阶段
- 释放流、有效负载、输入图像和输出数组所持有的资源。
void vpiArrayDestroy(VPIArray array)
销毁数组实例。
void vpiImageDestroy(VPIImage img)
销毁图像实例。
void vpiPayloadDestroy(VPIPayload payload)
释放有效负载对象和所有关联的资源。
void vpiStreamDestroy(VPIStream stream)
销毁流实例并释放所有硬件资源。
有关更多信息,请参阅《VPI - 视觉编程接口》的“C API 参考”部分中的“Harris 角点”。
性能
有关如何使用下表中的性能信息,请参阅“算法性能表”。
在比较测量结果之前,请查阅“比较算法运行时间”。
有关性能基准测试方式的更多信息,请参阅“性能基准测试”。
-
参考
- C. Harris, M. Stephens (1988), “组合角点和边缘检测器”
Alvey 视觉会议论文集,第 147-151 页。