Skip to content

图像平滑

本教程中你将学到如何使用 OpenCV 函数为图像应用各种线性滤波器以进行平滑,例如:

  • blur()
  • GaussianBlur()
  • medianBlur()
  • bilateralFilter()

注意: 下面的说明出自 Richard Szeliski 所著的 Computer Vision: Algorithms and Applications 一书,以及 LearningOpenCV。

  • 平滑(smoothing),也称为模糊(blurring),是一种简单且常用的图像处理运算。

  • 进行平滑处理的原因有很多。在本教程中,我们将聚焦于通过平滑来降低噪声(其他用途将在后续教程中介绍)。

  • 要执行平滑运算,我们需要对图像应用一个滤波器(filter)。最常见的滤波器类型是线性滤波器,其中输出像素的值(例如 g(i,j)g(i,j))由输入像素值的加权和(例如 f(i+k,j+l)f(i+k,j+l))决定:

    g(i,j)=∑k,lf(i+k,j+l)h(k,l)g(i,j) = \sum_{k,l} f(i+k, j+l) h(k,l)

    h(k,l)h(k,l) 称为核(kernel),它不过是滤波器的系数而已。

    把滤波器想象成一个系数窗口在图像上滑动,会有助于理解。

  • 滤波器的种类很多,这里我们介绍最常用的几种:

归一化方框滤波器(Normalized Box Filter)

Section titled “归一化方框滤波器(Normalized Box Filter)”
  • 这种滤波器是所有滤波器中最简单的!每个输出像素是其核邻域像素的均值(所有邻域像素的权重相同)。

  • 其核如下:

    K=1Kwidth⋅Kheight[111...1111...1......1......1111...1]K = \dfrac{1}{K_{width} \cdot K_{height}} \begin{bmatrix} 1 & 1 & 1 & ... & 1 \\ 1 & 1 & 1 & ... & 1 \\ . & . & . & ... & 1 \\ . & . & . & ... & 1 \\ 1 & 1 & 1 & ... & 1 \end{bmatrix}

Smoothing_Tutorial_theory_gaussian_0.jpg

  • 这可能是最有用的滤波器(尽管不是最快的)。高斯滤波的做法是将输入数组中的每个点与一个高斯核做卷积,然后将它们全部求和,得到输出数组。

  • 为了让画面更清晰,回想一下一维高斯核长什么样?

    假设图像是一维的,你会注意到位于中间的像素权重最大。随着邻域像素与中心像素之间空间距离的增大,其权重随之减小。

    注意: 记住,二维高斯可以表示为: G0(x,y)=Ae−(x−μx)22σ2∗x+−(y−μ∗y)22σy2G_{0}(x, y) = A e^{ \dfrac{ -(x - \mu_{x})^{2} }{ 2\sigma^{2}*{x} } + \dfrac{ -(y - \mu*{y})^{2} }{ 2\sigma^{2}_{y} } } 其中 μ\mu 是均值(峰值),σ2\sigma^{2} 表示方差(分别对应变量 xx 与 yy)。

中值滤波器遍历信号(本例中即图像)的每个元素,并用其邻域像素(位于被评估像素周围的一个方形邻域内)的中位数替换该像素。

  • 到目前为止,我们介绍的一些滤波器主要目标是平滑输入图像。然而有时,这些滤波器不仅消除了噪声,也把边缘一并平滑掉了。为避免这种情况(至少在一定程度上),我们可以使用双边滤波器。
  • 与高斯滤波类似,双边滤波器也会考虑邻域像素,并为每个邻域像素分配权重。这些权重包含两个分量:第一个分量与高斯滤波器所用的加权方式相同;第二个分量则考虑邻域像素与被评估像素之间的强度差异。
  • 更详细的说明可参阅这个链接。
  • 这个程序做什么?

    • 载入一幅图像
    • 应用 4 种不同的滤波器(在理论部分说明)并依次显示滤波后的图像
  • 可下载代码:点击 这里

  • 代码一览: 代码见下方示例

  • 可下载代码:点击 这里

  • 代码一览: 代码见下方示例

  • 可下载代码:点击 这里

  • 代码一览: 代码见下方示例

我们来检查一下仅涉及平滑过程的 OpenCV 函数,因为其余部分你现在已经了解了。

  • OpenCV 提供了 blur() 函数来用这种滤波器执行平滑。 我们指定 4 个参数(更多细节请查阅参考文档):
    • src:源图像
    • dst:目标图像
    • Size( w, h ):定义要使用的核大小(宽度为 w 像素,高度为 h 像素)
    • Point(-1, -1):指示锚点(被评估的像素)相对于邻域的位置。若为负值,则将核的中心视为锚点。
  • 它由函数 GaussianBlur() 执行: 这里我们使用 4 个参数(更多细节请查阅 OpenCV 参考文档):
    • src:源图像
    • dst:目标图像
    • Size(w, h):要使用的核大小(要考虑的邻域数)。ww 与 hh 必须为正的奇数,否则大小会根据 σx\sigma_{x} 与 σy\sigma_{y} 参数来计算。
    • σx\sigma_{x}:x 方向的标准差。写 00 表示根据核大小计算 σx\sigma_{x}。
    • σy\sigma_{y}:y 方向的标准差。写 00 表示根据核大小计算 σy\sigma_{y}。
  • 该滤波器由 medianBlur() 函数提供: 我们使用三个参数:
    • src:源图像
    • dst:目标图像,类型必须与 src 相同
    • i:核的大小(由于使用方形窗口,所以只有一个值)。必须为奇数。
  • 由 OpenCV 函数 bilateralFilter() 提供 我们使用 5 个参数:
    • src:源图像
    • dst:目标图像
    • d:每个像素邻域的直径。
    • σColor\sigma_{Color}:颜色空间中的标准差。
    • σSpace\sigma_{Space}:坐标空间中的标准差(以像素为单位)。

Smoothing_Tutorial_Result_Median_Filter.jpg

  • 该程序打开一幅图像(本例中为 lena.jpg),并在上述 4 种滤波器的作用下显示它。
  • 下面是用 medianBlur 平滑后的图像快照: