OpenCV 4.12.0
开源计算机视觉
加载中...
搜索中...
无匹配项
图像平滑

目标

  • 使用各种低通滤波器模糊图像
  • 将自定义滤波器应用于图像(2D 卷积)

2D 卷积(图像滤波)

就像一维信号一样,图像也可以使用各种低通滤波器(LPF)、高通滤波器(HPF)等进行滤波。低通滤波器有助于去除噪声、模糊图像等。高通滤波器有助于查找图像中的边缘。

OpenCV 提供了一个函数 cv.filter2D() 来将内核与图像进行卷积。作为一个例子,我们将尝试对图像应用平均滤波器。一个 5x5 平均滤波器内核如下所示

\[K = \frac{1}{25} \begin{bmatrix} 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \\ 1 & 1 & 1 & 1 & 1 \end{bmatrix}\]

我们使用以下函数:cv.filter2D (src, dst, ddepth, kernel, anchor = new cv.Point(-1, -1), delta = 0, borderType = cv.BORDER_DEFAULT)

参数
src输入图像。
dst输出图像的大小和通道数与 src 相同。
ddepth目标图像的所需深度。
kernel卷积核(或者更确切地说是相关核),一个单通道浮点矩阵;如果您想对不同的通道应用不同的内核,请使用 split 将图像分割成单独的颜色平面并单独处理它们。
anchor内核的锚点,指示内核中滤波点的相对位置;锚点应位于内核内;默认值 new cv.Point(-1, -1) 表示锚点位于内核中心。
delta在将滤波后的像素存储在 dst 中之前,添加到滤波后像素的可选值。
borderType像素外推方法(参见 cv.BorderTypes)。

尝试一下

图像模糊(图像平滑)

图像模糊是通过将图像与低通滤波器内核进行卷积来实现的。它对于去除噪声非常有用。它实际上是从图像中移除高频内容(例如:噪声、边缘)。因此,在此操作中,边缘会稍微模糊。(当然,也有一些模糊技术不会过度模糊边缘)。OpenCV 主要提供了四种类型的模糊技术。

1. 平均

这是通过将图像与归一化框滤波器进行卷积来完成的。它只是取内核区域下所有像素的平均值并替换中心元素。这是通过函数 cv.blur()cv.boxFilter() 完成的。有关内核的更多详细信息,请查看文档。我们应该指定内核的宽度和高度。一个 3x3 归一化框滤波器如下所示

\[K = \frac{1}{9} \begin{bmatrix} 1 & 1 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix}\]

我们使用以下函数:cv.blur (src, dst, ksize, anchor = new cv.Point(-1, -1), borderType = cv.BORDER_DEFAULT)

参数
src输入图像;它可以具有任意数量的通道,这些通道被独立处理,但深度应为 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F。
dst与 src 相同大小和类型的输出图像。
ksize模糊内核大小。
anchor锚点;anchor = new cv.Point(-1, -1) 表示锚点位于内核中心。
borderType用于外推图像外部像素的边框模式(参见 cv.BorderTypes)。

cv.boxFilter (src, dst, ddepth, ksize, anchor = new cv.Point(-1, -1), normalize = true, borderType = cv.BORDER_DEFAULT)

参数
src输入图像。
dst与 src 相同大小和类型的输出图像。
ddepth输出图像深度(-1 表示使用 src.depth())。
ksize模糊内核大小。
anchor锚点;anchor = new cv.Point(-1, -1) 表示锚点位于内核中心。
normalize标志,指定内核是否按其面积归一化。
borderType用于外推图像外部像素的边框模式(参见 cv.BorderTypes)。
注意
如果您不想使用归一化框滤波器,请使用 cv.boxFilter()。将参数 normalize = false 传递给函数。

尝试一下

2. 高斯模糊

在此方法中,使用高斯内核代替框滤波器。

我们使用以下函数:cv.GaussianBlur (src, dst, ksize, sigmaX, sigmaY = 0, borderType = cv.BORDER_DEFAULT)

参数
src输入图像;图像可以具有任意数量的通道,这些通道被独立处理,但深度应为 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F。
dst与 src 相同大小和类型的输出图像。
ksize模糊内核大小。
sigmaXX 方向上的高斯内核标准差。
sigmaYY 方向上的高斯内核标准差;如果 sigmaY 为零,则将其设置为等于 sigmaX,如果两个 sigma 均为零,则根据 ksize.width 和 ksize.height 计算它们,为了完全控制结果,而无需考虑未来可能对此语义的所有修改,建议指定所有 ksize、sigmaX 和 sigmaY。
borderType像素外推方法(参见 cv.BorderTypes)。

尝试一下

3. 中值模糊

在这里,函数 cv.medianBlur() 取内核区域下所有像素的中值,并且中心元素被此中值替换。这对于图像中的椒盐噪声非常有效。有趣的是,在上述滤波器中,中心元素是新计算的值,可能是图像中的像素值或新值。但是在中值模糊中,中心元素始终被图像中的某个像素值替换。它可以有效地降低噪声。它的内核大小应为正奇数整数。

我们使用以下函数:cv.medianBlur (src, dst, ksize)

参数
src输入 1、3 或 4 通道图像;当 ksize 为 3 或 5 时,图像深度应为 cv.CV_8U、cv.CV_16U 或 cv.CV_32F,对于更大的孔径尺寸,它只能是 cv.CV_8U。
dst大小和类型与 src 相同的目标数组。
ksize孔径线性大小;它必须是奇数且大于 1,例如:3、5、7 ...
注意
中值滤波器在内部使用 cv.BORDER_REPLICATE 来处理边框像素。

尝试一下

4. 双边滤波

cv.bilateralFilter() 在去除噪声的同时保持边缘清晰非常有效。但是与其他滤波器相比,该操作速度较慢。我们已经看到,高斯滤波器取像素周围的邻域并找到其高斯加权平均值。此高斯滤波器仅是空间的函数,也就是说,滤波时会考虑附近的像素。它不考虑像素是否具有几乎相同的强度。它不考虑像素是否为边缘像素。因此它也会模糊边缘,这是我们不想做的。

双边滤波器还在空间中采用高斯滤波器,但还采用另一个高斯滤波器,它是像素差的函数。空间的高斯函数确保仅考虑附近的像素进行模糊处理,而强度差的高斯函数确保仅考虑那些与中心像素具有相似强度的像素进行模糊处理。因此,它可以保留边缘,因为边缘处的像素将具有较大的强度变化。

我们使用以下函数:cv.bilateralFilter (src, dst, d, sigmaColor, sigmaSpace, borderType = cv.BORDER_DEFAULT)

参数
src源 8 位或浮点型、1 通道或 3 通道图像。
dst与 src 相同大小和类型的输出图像。
d滤波期间使用的每个像素邻域的直径。如果为非正数,则从 sigmaSpace 计算得出。
sigmaColor颜色空间中的滤波器 sigma。该参数的较大值意味着像素邻域内较远的颜色将被混合在一起,从而导致较大面积的半相等颜色。
sigmaSpace坐标空间中的滤波器 sigma。参数的较大值意味着更远的像素会相互影响,只要它们的颜色足够接近。当 d>0 时,它指定邻域大小,而与 sigmaSpace 无关。否则,d 与 sigmaSpace 成正比。
borderType用于外推图像外部像素的边框模式(参见 cv.BorderTypes)。
注意
为简单起见,您可以将 2 个 sigma 值设置为相同。如果它们很小(< 10),则滤波器不会产生太大影响,而如果它们很大(> 150),则它们会产生非常强烈的效果,使图像看起来“卡通化”。大型滤波器(d > 5)非常慢,因此建议在实时应用程序中使用 d=5,对于需要大量噪声滤波的离线应用程序,可以使用 d=9。

尝试一下