在图像产生、传输和复制过程中,常常会因为多方面原因而被噪声干扰或出现数据丢失,降低了图像的质量(某一像素,如果它与周围像素点相比有明显的不同,则该点被噪声所感染)。这就需要对图像进行一定的增强处理以减小这些缺陷带来的影响。可以采用图像平滑中的均值滤波、方框滤波、高斯滤波及中值滤波等方法。
原图:
噪声图片:
给原图添加噪声以供测试的代码:
# -*- coding:utf-8 -*-
import cv2
import numpy as np
#读取图片
img = cv2.imread('./out/partition7.jpg', cv2.IMREAD_UNCHANGED)
rows, cols, chn = img.shape
#加噪声
for i in range(5000):
x = np.random.randint(0, rows)
y = np.random.randint(0, cols)
img[x,y,:] = 255
cv2.imshow("noise", img)
#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.imwrite('./out/noise7.jpg', img)
一、均值滤波
1.原理
均值滤波是指任意一点的像素值,都是周围N*M个像素值的均值。例如下图中,红色点的像素值为蓝色背景区域像素值之和除25。
其中5*5的矩阵称为核(kernel),针对原始图像内的像素点,采用核进行处理,得到结果图像,针对原始图像的每一个像素点,都要进行核处理,处理过程如下,原始图像中的每一像素点(从左到右,从上到下)依次被核处理。
红色点的像素值=卷积核大小(上图也就是5*5)的范围内像素值之和/5*5.
函数:
实现均值滤波的核心函数如下:
result = cv2.blur(src,kernel),其中src是原图像,kernel是核大小。
代码:
#encoding:utf-8
import cv2
import numpy as np
#读取图片
img = cv2.imread('./out/noise7.jpg')
#均值滤波
result = cv2.blur(img, (5,5))
cv2.imshow("noise", img)
cv2.imshow("result", result)
#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
核设置越大,图像越模糊。设置为1时,没有变化。
二、方框滤波
方框滤波和均值滤波核基本一致,区别是需不需要均一化处理。
OpenCV调用boxFilter()函数实现方框滤波,如下:
result = cv2.boxFilter(src, 目标图像深度, kernel, normalize)
其中,目标图像深度是int类型,通常用“-1”表示与原始图像一致;
normalize属性表示是否对目标图像进行归一化处理。当normalize为true时需要执行均值化处理,当normalize为false时,不进行均值化处理,实际上为求周围各像素的和,很容易发生溢出,溢出时均为白色,对应像素值为255。
代码:
#encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
img = cv2.imread('./out/noise7.jpg')
#方框滤波
result1 = cv2.boxFilter(img, -1, (5,5), normalize=1)
result2 = cv2.boxFilter(img, -1, (5,5), normalize=0)
cv2.imshow("noise", img)
cv2.imshow("result1", result1)
cv2.imshow("result2", result2)
#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
可以看到如果省略参数normalize,则默认是进行归一化处理。如果normalize=0则不进行归一化处理,像素值为周围像素之和,图像更多为白色。
三、高斯滤波
- 图像高斯平滑也是邻域平均的思想对图像进行平滑的一种方法,在图像高斯平滑中,对图像进行平均时,不同位置的像素被赋予了不同的权重。高斯平滑与简单平滑不同,它在对邻域内像素进行平均时,给予不同位置的像素不同的权值,下图的所示的 3 * 3 和 5 * 5 领域的高斯模板。
- 高斯滤波让临近的像素具有更高的重要度,对周围像素计算加权平均值,较近的像素具有较大的权重值。
Python中OpenCV主要调用GaussianBlur函数,如下:
result = cv2.GaussianBlur(src, ksize, sigmaX)
其中sigmaX表示X方向方差,通常为0。核大小(N, N)必须是奇数。
代码:
#encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
img = cv2.imread('./out/noise7.jpg')
#高斯滤波
result = cv2.GaussianBlur(img, (3,3), 0)
#显示图形
cv2.imshow("noise", img)
cv2.imshow("result", result)
#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
四、中值滤波
中值滤波是非线性的图像处理方法,在去噪的同时可以兼顾到边界信息的保留。选一个含有奇数点的窗口W,将这个窗口在图像上扫描,把窗口中所含的像素点按灰度级的升或降序排列,取位于中间的灰度值来代替该点的灰度值。 例如选择滤波的窗口如下图,是一个一维的窗口,待处理像素的灰度取这个模板中灰度的中值,滤波过程如下:
OpenCV主要调用medianBlur()函数实现中值滤波。
result = cv2.medianBlur(src, kernel)
核必须是大于1的奇数,如3、5、7等。
代码:
#encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt
#读取图片
img = cv2.imread('./out/noise7.jpg')
#高斯滤波
result = cv2.medianBlur(img, 3)
#显示图像
cv2.imshow("source img", img)
cv2.imshow("medianBlur", result)
#等待显示
cv2.waitKey(0)
cv2.destroyAllWindows()
结果:
开始学习openCV第四课,主要学习来源:
[Python图像处理] 四.图像平滑之均值滤波、方框滤波、高斯滤波及中值滤波
谢谢大神的分享!