VPI - 视觉编程接口

3.2 版本

膨胀

概述

膨胀算法使用提供的 2D 布尔核对输入图像执行二维 (2D) 滤波操作。布尔核定义了滤波操作的像素邻域。该滤波器是一种称为膨胀的形态学操作,应用于由布尔滤波器掩盖的输入图像的每个像素。膨胀滤波器等效于最大值操作。二值图像中的膨胀操作增加增长前景区域(在下图中为白色),并识别和填充对象中的孔洞。

输入输出

\[ \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix} \]

\( \circ \; max \)

C API 函数

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

函数描述
vpiSubmitDilate 对图像运行 2D 膨胀。

实现

离散 2D 形态学滤波器使用以下离散函数实现

\[ I'[x,y] = \underset{m \in [0 .. k_h-1] \\ n \in [0 .. k_w-1]}{max} \Big\{ K[m,n] \times I[x-(n-\lfloor k_w/2 \rfloor), y-(m-\lfloor k_h/2 \rfloor)] \Big\} \]

其中

  • \(I\) 是输入图像。
  • \(I'\) 是结果图像。
  • \(K\) 是邻域核,其中 \(K \in \{0 \vee 1\}\)。
  • \(k_w, k_h\) 分别是核的宽度和高度。
  • \(max\) 是形态学滤波操作。

形态学操作是一组基于数字图像形状处理数字图像的图像处理操作。膨胀滤波器等效于最大值操作。膨胀会扩展图像中的明亮结构。输入可以是二值的(用于最常见的二值形态学),也可以是灰度的(用于灰度形态学)。另一个形态学滤波器是 腐蚀,它等效于最小值操作。腐蚀滤波器可以在膨胀滤波器之后使用,以构成图像的形态学闭运算

用法

语言
  1. 导入 VPI 模块
    import vpi
  2. 定义一个 3x3 形态学核以执行完整邻域搜索。
    kernel = [[1, 1, 1],
    [1, 1, 1],
    [1, 1, 1]]
  3. 使用 CPU 后端和给定的核对输入图像运行形态学滤波器。输入和输出是 VPI 图像。
    with vpi.Backend.CUDA
    output = input.dilate(kernel, border=vpi.Border.ZERO)
  1. 初始化阶段
    1. 包含定义所需函数和结构的头文件。
      声明使用二值核执行图像形态学滤波的函数。
    2. 定义输入图像对象。
      VPIImage input = /*...*/;
      struct VPIImageImpl * VPIImage
      图像的句柄。
      定义: Types.h:256
    3. 创建输出图像。它从输入图像获取其尺寸和格式。
      int32_t w, h;
      vpiImageGetSize(input, &w, &h);
      vpiImageGetFormat(input, &format);
      VPIImage output;
      vpiImageCreate(w, h, format, 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)
      创建流实例。
  2. 处理阶段
    1. 定义要使用的核。在本例中,是一个简单的 3x3 全邻域。
      int8_t kernel[3 * 3] = { 1, 1, 1,
      1, 1, 1,
      1, 1, 1 };
    2. 将所选形态学滤波器的算法提交到流,传递核和其他参数。在本例中,是膨胀滤波器。它将由 CPU 后端执行。
      vpiSubmitDilate(stream, VPI_BACKEND_CPU, input, output, kernel, 3, 3, VPI_BORDER_ZERO);
      VPIStatus vpiSubmitDilate(VPIStream stream, uint64_t backend, VPIImage input, VPIImage output, const int8_t *kernelData, int32_t kernelWidth, int32_t kernelHeight, VPIBorderExtension border)
      对图像运行 2D 膨胀。
      @ VPI_BACKEND_CPU
      CPU 后端。
      定义: Types.h:92
      @ VPI_BORDER_ZERO
      图像外部的所有像素都被视为零。
      定义: Types.h:278
    3. 可选地,等待直到处理完成。
      vpiStreamSync(stream);
      VPIStatus vpiStreamSync(VPIStream stream)
      阻塞调用线程,直到此流队列中所有提交的命令都完成(队列为空)...
  3. 清理阶段
    1. 释放流以及输入和输出图像所持有的资源。
      vpiImageDestroy(output);
      void vpiImageDestroy(VPIImage img)
      销毁图像实例。
      void vpiStreamDestroy(VPIStream stream)
      销毁流实例并释放所有硬件资源。

有关更多信息,请参阅VPI - 视觉编程接口的“C API 参考”部分中的 膨胀

性能

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

 -