图像平滑是一种区域增强的算法,平滑算法有邻域平均法、中指滤波、边界保持类滤波等。在图像产生、传输和复制过程中,常常会因为多方面原因而被噪声干扰或出现数据丢失,降低了图像的质量(某一像素,如果它与周围像素点相比有明显的不同,则该点被噪声所感染)。这就需要对图像进行一定的增强处理以减小这些缺陷带来的影响。
为了方便做出比较,先给一幅图片中加入噪声,代码如下:
import cv2
import numpy as np
# 读取图片
image = cv2.imread('E:/pythonProject/mei.jpeg',cv2.IMREAD_UNCHANGED)
rows,cols,chn = image.shape
#添加噪声
for i in range (5000):
x = np.random.randint(0,rows)
y = np.random.randint(0,cols)
image[x,y,:] = 255
#显示图片
cv2.imshow("noise",image)
#窗口等待
cv2.waitKey(0)
cv2.destroyAllWindows()
#图片写入
cv2.imwrite("E:/pythonProject/meii.jpeg",image)
加入噪声后的图片显示如下:
1.原理
在进行均值滤波的时候要考虑需要对周围多少个像素去平均值,即确定核的大小,通常情况下都是以当前像素点为中心,读行数和列数相等的一块区域内的所有像素点求平均。将计算得到的结果作为该点的像素。
例如下图中,红色点的像素值为蓝色背景区域像素值之和除25。
其中红色区域的像素值均值滤波处理过程为: ((197+25+106+156+159)+ (149+40+107+5+71)+ (163+198+**226**+223+156)+ (222+37+68+193+157)+ (42+72+250+41+75)) / 25
其中5*5的矩阵称为核,针对原始图像内的像素点,采用核进行处理,得到结果图像。计算得到的新值即为226像素点位置的新的像素。其中均值滤波的核如下所示
2.代码
中值滤波核心代码:
cv2.blur(img, (3, 3))
参数说明:img表示输入的图片, (3, 3) 表示进行均值滤波的方框大小。
其中,核大小是以(宽度,高度)表示的元祖形式。常见的形式包括:核大小(3,3)和(5,5)。
代码如下所示:
import cv2
import matplotlib.pyplot as plt
#获取图像
image = cv2.imread('E:/pythonProject/meii.jpeg')
# #将BGR转换成RGB
source = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
#将BGR转换成RGB方法二
# b,g,r = cv2.split(image)
# source = cv2.merge([r,g,b])
#方框滤波
mean = cv2.blur(source,(3,3))
titles = ["source image","mean image"]
images = [source, mean]
# 图像显示
for i in range (2):
plt.subplot(1,2,i+1)
plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
输出结果如下所示:
这里涉及一个通道转换的问题,OpenCV里面图像是以BGR的形式存储的,所以在进行图像平滑处理时,先将图片通道数转换成RGB形式的,如果不转换的话,处理后的图片通道数将会以BGR格式显示,颜色基本全变成蓝色,如下所示:
.方框滤波核心代码:
cv2.boxfilter(img, -1, (3, 3), normalize=True)
参数说明:img表示输入图像。-1表示目标图像深度,目标图像深度是int类型,通常用“-1”表示与原始图像一致。 (3, 3) 表示核的大小,核大小主要包括(3,3)和(5,5)。当normalize=True时,与均值滤波结果相同, normalize=False,表示对加和后的结果不进行平均操作,实际上为求周围各像素的和,很容易发生溢出,溢出时均为白色,大于255的使用255表示
代码如下所示:
import cv2
import matplotlib.pyplot as plt
#读取图片
image = cv2.imread('E:/pythonProject/meii.jpeg')
# #将BGR转换成RGB
source = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
#方框滤波
box = cv2.boxFilter(source,-1,(5,5),normalize=1)
titles = ["source image","box image"]
images = [source, box]
# 图像显示
for i in range (2):
plt.subplot(1,2,i+1)
plt.imshow(images[i],'gray')
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
代码中使用5*5的核进行处理,Normalize=True进行归一化处理,相当于均值滤波。输出结果如下:
如果不设置参数Normalize,则默认为归一化处理,将Normalize=False不进行归一化处理,则像素值为周围像素值只和,图像则多为白色。
上图很多像素基本全为白色,主要是像素和几乎都是255.
高斯滤波是一种线性平滑滤波,适用于消除高斯噪声,广泛应用于图像处理的减噪过程。 通俗的讲,高斯滤波就是对整幅图像进行加权平均的过程,每一个像素点的值,都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波的具体操作是:用一个模板(或称卷积、掩模)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值去替代模板中心像素点的值。
高斯滤波核心代码:
cv2.Guassianblur(img, (3, 3), 1)
参数说明:img表示输入的图片, (3, 3) 表示进行均值滤波的方框大小。 1表示σ, x表示与当前值得距离,计算出的G(x)表示权重值。
注意,核大小(N, N)必须是奇数
代码如下所示:
import cv2
import matplotlib.pyplot as plt
#读取图像
image = cv2.imread('E:/pythonProject/meii.jpeg')
source = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
#高斯滤波
gaussian = cv2.GaussianBlur(source,(3,3),1)
titles = ["source image","gaussian image"]
images = [source,gaussian]
#图像显示
for i in range(2):
plt.subplot(1,2,i+1),plt.imshow(images[i])
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
下图分别一次取核大的大小为(3,3),(15,15),结果如下所示:
使用核大小为(3,3)去噪效果较差,核大小为(15,15)处理后图像较为模糊,但噪音也降低了很多。
中值滤波是一种非线性平滑技术,它将每一像素点的灰度值设置为该点某邻域窗口内的所有像素点灰度值的中值。
中值滤波对脉冲噪声有良好的滤除作用,特别是在滤除噪声的同时,能够保护信号的边缘,使之不被模糊。这些优良特性是线性滤波方法所不具有的。此外,中值滤波的算法比较简单,也易于用硬件实现。所以,中值滤波方法一经提出后,便在数字信号处理领得到重要的应用。
. 中值滤波核心代码:
cv2.medianBlur(img, 3)
参数说明:img表示当前的图片,3表示当前的核大小,核必须是大于1的奇数,如3、5、7等。
在图像的读取中,会存在一些躁声点,如一些白噪声,因此我们需要进行去躁操作
代码如下所示:
#读取图片
image = cv2.imread('E:/pythonProject/meii.jpeg')
source = cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
#中值滤波
median = cv2.medianBlur(source,5)
titles = ["source image","median image"]
images = [source,median]
#图像显示
for i in range(2):
plt.subplot(1,2,i+1),plt.imshow(images[i])
plt.title(titles[i])
plt.xticks([]),plt.yticks([])
plt.show()
输出结果如下图所示:
中值滤波是非线性的图像处理方法,相比与前面几种去噪方法,中值滤波在去噪的同时可以兼顾到边界信息的保留,去噪效果较好。
本文参考了该E、p等的文章,如有不足之处请多多见谅。