目录
图像平滑基础
本文目标
2D卷积
图像模糊(图像平滑)
平均模糊
高斯模糊
中值模糊
双边滤波
在尽量保留图像原有信息的情况下,过滤掉图像内部的噪声,这一过程称为对图像的平滑处理,所得的图像称为平滑图像。
一幅图像在获取传输等过程中会受到各种各样的噪声干扰。图像噪声来自多方面,有来自系统外部的干扰,如电磁波或经电源串进系统内部而引起的外部噪声;也有来自系统内部的干扰,如摄像机的热噪声、电器的机械运动而产生的抖动噪声等。这些噪声干扰使图像退化,质量下降,表现为图像模糊、特征淹没、对图像分析不利。因此,去除噪声、恢复原始图像是图像处理中的一个重要内容。消除噪声的工作称为图像平滑。图像平滑 (image smoothing) 是一种区域增强算法. 可以帮助我们去除早点改善图片质量。
学习使用不同的低通滤波器对图像进行模糊
使用自定义的滤波器对图像进行卷积(2D 卷积)
与信号一样,我们也可以对2D 图像实施低通滤波(LPF)、高通滤波(HPF)等。LPF 帮助我们去除噪生,模糊图像。HPF 帮助我们找到图像的边缘。OpenCV 提供的函数cv.filter2D() 可以帮助我们对一幅图像进行卷积操作。下面我们将对一幅图像使用平均滤波器。下面是一个5x5 的平均滤波器核:
操作如下,将核放在图像的一个像素A 上,求与核对应的图像上25(5x5)个像素的和,再取平均数,用这个平均数替代像素A 的值。重复以上操作直到将图像的每一个像素值更新一遍。代码如下:
# -*- coding: utf-8 -*-
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('opencv_logo.png')
kernel = np.ones((5,5),np.float32)/25
#cv.Filter2D(src, dst, kernel, anchor=(-1, -1))
#ddepth –desired depth of the destination image;
#if it is negative, it will be the same as src.depth();
#the following combinations of src.depth() and ddepth are supported:
#src.depth() = CV_8U, ddepth = -1/CV_16S/CV_32F/CV_64F
#src.depth() = CV_16U/CV_16S, ddepth = -1/CV_32F/CV_64F
#src.depth() = CV_32F, ddepth = -1/CV_32F/CV_64F
#src.depth() = CV_64F, ddepth = -1/CV_64F
#when ddepth=-1, the output image will have the same depth as the source.
dst = cv2.filter2D(img,-1,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(dst),plt.title('Averaging')
plt.xticks([]), plt.yticks([])
plt.show()
使用低通滤波器可以达到图像模糊的目的。这对与去除噪生很有帮助。其实就是去除图像中的高频成分,(比如噪音和边界)。所以边界也会被模糊一点。当然,也有一些模糊技术不会模糊掉边界。OpenCV 提供了四种模糊技术。
这是由一个归一化卷积框完成的。他只是用卷积框覆盖区域所有像素的平均值来代替中心元素。可以使用函数cv2.blur() 和cv2.boxFilter() 来完成这个任务。可以查看文档了解更多卷积框的细节。我们需要设定定卷积框的宽和高。下面是一个3x3 的归一化卷积框:
注意:如果你不想使用归一化卷积框,你应该使用cv2.boxFilter(),这时要传入参数normalize=False。
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('opencv_logo.png')
blur = cv2.blur(img,(5,5))
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()
现在把卷积核换成高斯核。(简单来说,方框不变,将原来每个方框的值是相等的,现在里面的值是符合高斯分布的,方框中心的值最大,其余方框根据距离离中心元素的距离递减,构构成一个高斯小山包。原来的求平均数现在变成求加权平均数,就是方框里的值。实现的函数是cv2.GaussianBlur()。我们指定高斯核的宽和和高,必须是奇数。以及高斯函数沿X,Y 方向的标准
差。如果我们只指定了X 方向的的标准差,Y 方向也会取相同值。如果两个标准差都是0,那么函数会根据核函数的大小自己算。高斯滤波可以有效的从图像中去除高斯噪声。如果你愿意的话,你也可以使用函数cv2.getGaussianKernel() 自己构建一个高斯核。
使用高斯模糊的核心代码是:
#0 是指根据窗口大小5,5来算斯函数标准差
blur = cv2.GaussianBlur(img,(5,5),0)
顾名思义就是用与卷积框对应像素的中值来替代中心像素的值。这个滤波器经常用来去除椒盐噪声。前面的滤波器都是是用计算得到的一个新值来取代中心像素的值,而中值滤波是用中心像素周围(也可以是他本身)的值来取代他。他能有效的去除噪声。卷积核的大小也应该是一个奇数。
在这个例子中,我们给原始图像加上50% 的噪声然后再使用中值模糊。
代码:
median = cv2.medianBlur(img,5)
函数cv2.bilateralFilter() 能在保持边界清晰的情况下有效的去除噪音。但是这种操作与其他滤波器相比会比较慢。我们已经知道高斯滤波器是求中心点邻近区域像素的高斯加权平均值。这种高斯滤波器只考像素之间的空间关系而不会考虑像素值之间的关系(像素的相似度)。所以这种方法不会考虑一个像素是否位于边界。因此边界也会别模糊掉,而这正不是我们想要。
双边滤波在同时使用空间高斯权重和灰度值相似性高斯权重。空间高斯函数确保只有领近区域的像素对中心点有影响,灰度值相似性高斯函数确保只有与中心像素灰度值相近的才会被用来做模糊运算。所以这种方法会确保边界不会被模糊掉,因为边界处的灰度值变化比较大。
#cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace)
#d – Diameter of each pixel neighborhood that is used during filtering.
# If it is non-positive, it is computed from sigmaSpace
#9 域直径两个75 分别是空斯函数标准差灰度值相似性斯函数标准差
blur = cv2.bilateralFilter(img,9,75,75)
更多的参考点:http://people.csail.mit.edu/sparis/bf_course/