VPI - 视觉编程接口

3.2 版本

双边滤波器

概述

双边滤波器是一种非线性、保边平滑滤波器,通常在计算机视觉中用作流水线中的简单降噪阶段。它通过计算输入图像中附近像素的强度值的加权平均值来计算每个输出像素的强度。至关重要的是,权重不仅取决于当前像素和相邻像素之间的欧几里得距离,还取决于它们之间的辐射差异(例如,颜色强度差异)。结果是边缘得到保留,而强度相似的区域被平滑。

输入参数输出

\begin{align*} \mathit{kernelSize} &= 7x7 \\ \sigma_s &= 1.7 \\ \sigma_r &= 50 \end{align*}

实现

双边滤波器定义为

\[ I'(p) = \frac{1}{W_p} \sum_{q\in\Omega}I(p)k_r(\|I(q) - I(p)\|)k_s(\|p-q\|) \]

归一化项 W 定义为

\[ W_p = \sum_{q\in\Omega}k_r(\|I(p)-I(q)\|)k_s(\|p-q\|) \]

其中

  • \(I\) 和 \(I'\) 分别是输入和输出图像。
  • \(k_r\) 和 \(k_s\) 分别是范围和空间核,定义为以下非归一化高斯函数

    \begin{align*} k_r(p) &= e^{-\frac{\|p\|^2}{2\sigma_r^2}} \\ k_s(p) &= e^{-\frac{\|p\|^2}{2\sigma_s^2}} \end{align*}

  • \(\sigma_r\) 控制被平滑的强度范围。值越高,被平滑的区域越大。\(\sigma_r\) 值的选择应考虑到图像像素值的动态范围。
  • \(\sigma_s\) 控制平滑因子。值越高,平滑度越高。

C API 函数

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

函数描述
vpiSubmitBilateralFilter 在图像上运行 2D 双边滤波器。

用法

语言
  1. 导入 VPI 模块
    import vpi
  2. 使用 CUDA 后端在输入图像上运行双边滤波器。它使用 7x7 内核,\(\sigma_r=50\) 和 \(\sigma_s=1.7\),以及 ZERO 边界条件。输入和输出是 VPI 图像。
    with vpi.Backend.CUDA
    output = input.bilateral_filter(5, 7, 50, border=vpi.Border.ZERO)
  1. 初始化阶段
    1. 包含定义双边滤波器函数的头文件。
      声明实现双边滤波器算法的函数。
    2. 定义输入图像。
      VPIImage input = /*...*/;
      struct VPIImageImpl * VPIImage
      图像的句柄。
      Definition: 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
      预定义的图像格式。
      Definition: ImageFormat.h:94
      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
      流的句柄。
      Definition: Types.h:250
      VPIStatus vpiStreamCreate(uint64_t flags, VPIStream *stream)
      创建流实例。
  2. 处理阶段
    1. 使用 CUDA 后端以及所有参数将算法提交到流。这里我们使用 7x7 内核,\(\sigma_r=50\) 和 \(\sigma_s=1.7\)。
      vpiSubmitBilateralFilter(stream, VPI_BACKEND_CUDA, input, output, 7, 50, 1.7, VPI_BORDER_ZERO);
      VPIStatus vpiSubmitBilateralFilter(VPIStream stream, uint64_t backend, VPIImage input, VPIImage output, int32_t kernelSize, float sigmaRange, float sigmaSpace, VPIBorderExtension border)
      在图像上运行 2D 双边滤波器。
      @ VPI_BACKEND_CUDA
      CUDA 后端。
      Definition: Types.h:93
      @ VPI_BORDER_ZERO
      图像外部的所有像素均视为零。
      Definition: Types.h:278
    2. (可选)等待直到处理完成。
      vpiStreamSync(stream);
      VPIStatus vpiStreamSync(VPIStream stream)
      阻塞调用线程,直到此流队列中的所有已提交命令都完成(队列为空)。。
  3. 清理阶段
    1. 释放流以及输入和输出图像所持有的资源。
      vpiImageDestroy(output);
      void vpiImageDestroy(VPIImage img)
      销毁图像实例。
      void vpiStreamDestroy(VPIStream stream)
      销毁流实例并释放所有硬件资源。

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

性能

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

 -