VPI - 视觉编程接口

3.2 版本

递归高斯滤波器

概述

递归高斯滤波器是一种低通 IIR(无限脉冲响应)高斯滤波器,它通过串联低阶因果和反因果递归滤波器来平滑图像。它很好地近似了宽支持高斯滤波器,即那些具有较大标准偏差(sigma)的滤波器,同时提供比直接卷积 高斯滤波器 更优越的性能。它的优势在于,无论 sigma 有多大,滤波图像的计算时间都相同,因为它不依赖于内核支持大小,也没有内核支持大小的限制。

它仅支持一种操作模式

  • 用户提供滤波器标准偏差 (sigma)。

下图显示了一个使用示例。整个输入图像使用递归高斯滤波器以较大的 sigma 进行模糊处理,用作背景,同时使用掩码分割并保留中间的苍鹭。

输入和掩码高斯 sigma输出

\[ \sigma=17 \]

实现

递归高斯滤波器实现为对输入图像的行和列进行前向(因果)滤波器和后向(反因果)滤波器序列。为了更好地理解它们,让我们首先将线性时不变 (LTI) 滤波器定义为

\[ \sum_{i=-r}^{r} a_i z[k-i] = \sum_{i=-s}^{s} b_i w[k-i] \]

\(a_i\) 和 \(b_i\) 是滤波器设计参数。\ (w[k]\) 和 \(z[k]\) 分别是输入和输出信号。此 LTI 滤波器可以分解为卷积过程以及因果和反因果递归滤波器过程的组合

\[ x[k] = \sum_{i=-s}^{s} c_i w[k-i] \]

\[ y[k] = x[k] - \sum_{i=1}^{r} d_i y[k-i] \]

\[ z[k] = y[k] - \sum_{i=1}^{r} e_i z[k-i] \]

卷积具有有限脉冲响应 (FIR),由 \(c_i\) 系数给出,\(s\) 是卷积核支持。此外,递归滤波器具有无限脉冲响应 (IIR),由 \(d_i\) 和 \(e_i\) 系数给出,\(r\) 是滤波器阶数。\ (x[k]\) 和 \(y[k]\) 分别是 FIR 和 IIR 的中间输出信号。通过独立地滤波所有列,然后滤波所有结果行,可以将此过程从 1D 信号扩展到 2D 图像。

可以使用三阶递归滤波器来近似高斯滤波,而不是直接卷积,它在与标准偏差无关的线性时间内运行。就性能、质量和简单性而言,它们是最佳替代方案,特别是对于宽支持滤波器。在上面的示例中,需要 \(101x101\) 支持大小的直接卷积核来容纳指定的 \(\sigma=17\) 并获得相同的模糊效果。

该实现将因果-反因果处理与行-列处理重叠。重叠的工作方式类似于融合,但在更深层次的、阶段内的算法级别。有关更多信息,请参阅 [1]

C API 函数

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

函数描述
vpiCreateRecursiveGaussianFilter vpiSubmitRecursiveGaussianFilter 创建负载。
vpiSubmitRecursiveGaussianFilter 在图像上运行递归高斯滤波器。

用法

语言
  1. 导入 VPI 模块
    import vpi
  2. 使用递归高斯滤波器以 \(\sigma=17\) 模糊输入图像,在 CUDA 后端中使用 REFLECT 边界条件。输入和输出均为 VPI 图像。
    with vpi.Backend.CUDA
    output = input.recursive_gaussian_filter(17, border=vpi.Border.REFLECT)
  1. 初始化阶段
    1. 包含定义递归高斯滤波器函数的头文件。
      声明实现递归高斯滤波器算法的函数。
    2. 定义输入图像对象。
      VPIImage input = /*...*/;
      struct VPIImageImpl * VPIImage
      图像句柄。
      定义: Types.h:256
    3. 创建输出图像。它从输入图像获取其尺寸和格式。
      int32_t w, h;
      vpiImageGetSize(input, &w, &h);
      vpiImageGetFormat(input, &type);
      VPIImage output;
      vpiImageCreate(w, h, type, 0, &output);
      uint64_t VPIImageFormat
      预定义的图像格式。
      VPIStatus vpiImageGetFormat(VPIImage img, VPIImageFormat *format)
      获取图像格式。
      VPIStatus vpiImageCreate(int32_t width, int32_t height, VPIImageFormat fmt, uint64_t flags, VPIImage *img)
      使用指定的标志创建空的图像实例。
      VPIStatus vpiImageGetSize(VPIImage img, int32_t *width, int32_t *height)
      以像素为单位获取图像尺寸。
    4. 创建将在其中提交算法以执行的流。
      VPIStream stream;
      vpiStreamCreate(0, &stream);
      struct VPIStreamImpl * VPIStream
      流的句柄。
      定义: Types.h:250
      VPIStatus vpiStreamCreate(uint64_t flags, VPIStream *stream)
      创建流实例。
    5. 创建递归高斯滤波器负载。宽度和高度是可以由提交递归高斯滤波器使用的最大图像尺寸。
      VPIPayload payload;
      struct VPIPayloadImpl * VPIPayload
      算法负载的句柄。
      定义: Types.h:268
      VPIStatus vpiCreateRecursiveGaussianFilter(uint64_t backends, int32_t maxWidth, int32_t maxHeight, VPIPayload *payload)
      为 vpiSubmitRecursiveGaussianFilter 创建负载。
      @ VPI_BACKEND_CUDA
      CUDA 后端。
      定义: Types.h:93
  2. 处理阶段
    1. 将递归高斯滤波器算法与其他参数一起提交到流。它将由 CUDA 后端执行。它定义了一个 \(\sigma=17\) 的高斯滤波器,以及反射边界扩展。
      vpiSubmitRecursiveGaussianFilter(stream, VPI_BACKEND_CUDA, payload, input, output, 17, 17, VPI_BORDER_REFLECT);
      VPIStatus vpiSubmitRecursiveGaussianFilter(VPIStream stream, uint64_t backend, VPIPayload payload, VPIImage input, VPIImage output, float sigmaX, float sigmaY, VPIBorderExtension border)
      在图像上运行递归高斯滤波器。
      @ VPI_BORDER_REFLECT
      edcba|abcde|edcba
      定义: Types.h:280
    2. 可选地,等待直到处理完成。
      vpiStreamSync(stream);
      VPIStatus vpiStreamSync(VPIStream stream)
      阻塞调用线程,直到此流队列中的所有提交命令完成(队列为空)。。。
  3. 清理阶段
    1. 释放流、输入和输出图像以及算法负载所持有的资源。
      vpiImageDestroy(output);
      void vpiImageDestroy(VPIImage img)
      销毁图像实例。
      void vpiPayloadDestroy(VPIPayload payload)
      释放负载对象和所有关联的资源。
      void vpiStreamDestroy(VPIStream stream)
      销毁流实例并释放所有硬件资源。

有关更多信息,请参阅 VPI - 视觉编程接口 的“C API 参考”部分中的 递归高斯滤波器

性能

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

 - 

参考

  1. D. Nehab 和 A. Maximo,“无限输入扩展的并行递归滤波”。
    ACM Transactions on Graphics,第 35 卷,第 6 期,第 204 条,2016 年。