OpenCV 滤波与卷积之 —— 平滑

本文最后更新于:2022年5月21日 凌晨

本文摘录OpenCV 中的卷积、滤波相关操作内容,重点介绍 Opencv 中的平滑滤波操作。

平滑

平滑一般也称“模糊”,是一种简单而又常用的图像处理操作。平滑图像的目的有很多,但通常都是为了减少噪声和伪影。在降低图像分辨率的时候,平滑也是十分重要的。OpenCV 提供5种不同的平滑操作,每种操作都有对应的函数实现,这些操作平滑的结果有着细微的差别。

1. cv2.blur()

简单模糊,官网链接

  • 函数使用
1
cv.blur(src, ksize[, dst[, anchor[, borderType]]]) -> dst

blur 函数执行平均的核卷积图像操作,卷积核为:

$$ \mathrm{K}=\frac{1}{\mathrm{ksize} . {width*ksize.height }}\left[\begin{array}{cccccc}1 & 1 & 1 & \cdots & 1 & 1 \\ 1 & 1 & 1 & \cdots & 1 & 1 \\ \cdots & & & & & \\ 1 & 1 & 1 & \cdots & 1 & 1\end{array}\right] $$
  • 示例代码
1
2
3
img = mt.cv_rgb_imread('img1.jpg', gray=True)
res = cv2.blur(img, [17, 17])
PIS(img, res)

2. cv2.boxFilter()

OpenCV中的函数cv2.boxFilter()是一种一般化的形式,而cv2.blur()是一种特殊化的形式。两者之间根本的区别主要是前者可以以非归一化形式调用,并且输出图像深度可以控制(cv2.blur()输出图像的深度与源图像保持一致)。假如变量ddepth的值设为-1,目标图像的深度将于源图像保持一致。

  • 函数使用
1
2
3
4
5
6
cv2.boxFilter(
src, # 源图像
ddepth, # 输出图像深度
ksize, # 核尺寸
anchor, # 中心锚点位置
normalize = True) # 是否归一化,如果 True,结果会除以核面积
  • 示例代码
1
2
3
img = mt.cv_rgb_imread('img1.jpg', gray=False)
res = cv2.boxFilter(img, 3, [17, 17])
PIS(img, res)

3. cv2.medianBlur()

中值滤波,官网链接

中值滤波器是一种非线性核的实例,无法以图形形式表示。

  • 函数使用
1
cv2.medianBlur(src, ksize[, dst]) ->	dst

中值滤波器(Median Filter)将每个像素替换为围绕这个像素的矩形邻域内的中值或“中值”像素(相对于平均像素)。通过平均的简单模糊对噪声图像,尤其是有较大孤立的异常值(比如数字影像中的拍摄噪声)非常敏感。少量具有较大偏差的点也会严重影响到均值滤波。中值滤波可以采用取中间点的方式来消除异常值。

  • 示例代码
1
2
3
img = mt.cv_rgb_imread('img1.jpg', gray=False)
res = cv2.medianBlur(img, 17)
PIS(img, res)

4. cv2.GaussianBlur()

使用高斯滤波器模糊图像。该函数卷积具有指定高斯核的源图像。

官方链接

  • 函数使用
1
2
3
4
5
6
7
8
9
cv.GaussianBlur(
src, # 源图像
ksize, # 高斯核尺寸
sigmaX[, # X 方向的高斯核标准差。
dst[,
sigmaY[, # X 方向的高斯核标准差。如果 sigmaY 是0,那么它将被设置为 sigmaX。
#如果两个 sigmas 都是零,那么它们将分别从 ksize.width 和 ksize.height 计算出来
borderType]
]]) -> dst
  • 两个 sigmas 都是零,高斯参数计算公式:

$$
\begin{array}{c}

\sigma_{x}=\left(\frac{n_{x}-1}{2}\right) \cdot 0.30+0.80, n_{x}=k size. width -1\
\sigma_{y}=\left(\frac{n_{y}-1}{2}\right) \cdot 0.30+0.80, n_{y}=k size .height -1
\end{array}
$$

  • 高斯核示例

  • OpenCV实现的高斯平滑还为几个常用的内核提供性能上的优化。3×3、5×5以及7×7的标准sigma核(sigmaX=0.0) 相对其他核性能更优。
  • 示例代码
1
2
3
img = mt.cv_rgb_imread('img1.jpg', gray=False)
res = cv2.GaussianBlur(img, [17, 17], 10, 10)
PIS(img, res)

5. cv2.bilateralFilter()

双边滤波

官网链接

  • 函数使用
1
2
3
4
5
6
7
cv2.bilateralFilter(
src, # 源图像
d, # 像素邻域的直径
sigmaColor, # 颜色空间滤波器的sigma值
sigmaSpace[, # 坐标空间中滤波器的sigma值
dst[,
borderType]]) -> dst

相似于高斯平滑,双边滤波对每个像素及其领域内的像素进行了加权平均。其权重由两部分组成,第一部分同高斯平滑;第二部分也是高斯权重,不同的是它不是基于空间距离而是色彩强度差计算而来,在多通道(彩色)图像上强度差由各分量的加权累加代替。

可以把双边滤波当作是高斯平滑,只是相似程度更高的像素权值更高,边缘更明显,对比度更高。双边滤波的效果就是将源图像变成一幅水彩画,这种效果在多次迭代后更加显著,因此这种方法在图像分割领域十分有用。

1
2
3
img = mt.cv_rgb_imread('img1.jpg', gray=False)
res = cv2.bilateralFilter(img, 9, 100, 1000)
PIS(img, res)

示例源码

参考资料

  • 《学习 OpenCV3》 第十章