图像平滑是一种区域增强算法,在图像产生、传输和复制的过程中,会因为多方面原因而产生噪声(某一像素与周围像素点相比有明显不同)或丢失数据,因而图像的质量会降低。此时就需要对图像进行一定的增强处理,以降低图像质量带来的影响
图像噪声使得图像模糊,甚至淹没图像特征,造成分析困难。
常见的噪声分类:
模板操作是图像处理中常用的一种邻域运算方式,主要有卷积和相关操作。
模板:
常用矩阵表示,可以是一幅图像、一个滤波器或一个窗口,定义了参与运算的中心元素和邻域元素的相对位置及相关系数。
模板的中心元素(原点)表示将要处理的元素,一般取模板中心点,也可以根据需要选取非中心点。
模板卷积(或相关):
指模板与图像进行卷积(或相关)运算,是一种线性滤波,其输出像素是输入邻域像素的线性加权和。
卷积核:
模板卷积中的模板又称为卷积核,其元素称为卷积系数、模板系数或加权系数,其大小及排列顺序决定了对图像进行邻域处理的类型。
卷积运算前需要将模板绕模板中心旋转 180°,其余运算过程与模板运算过程一致,因而统称模板卷积。
模板操作需要注意的两个问题:
图像边界问题
当模板原点移至图像边界时,部分模板系数可能在原图像中找不到与之对应的像素。
解决方法:
1.不做处理
2.扩充图像
可以复制原图像边界像素或利用常数来填充扩充的像素边界
计算结果可能超出灰度范围
原理: 用一个像素邻域平均值作为滤波结果,此时滤波器模板的所有系数取值均为 1,仅获取内核区域下所有像素的平均值,并替换中心元素,为保证输出像素值不越界,邻域平均的卷积核系数之和为 1
计算思路:
例如下图中,我们要计算红色点经过均值滤波后的像素值,蓝色区域 3×3 的矩阵为核,采用核处理后,红色点的像素值=(100+210+123+123+220+231+45+21+32)/9
均值滤波常用的一个 3×3 的 Box 模板(还有 5×5 等等),Box 模板中加权系数均相同,邻域中各像素对平滑结果的影响相同。
代码:
import cv2 as cv
img=cv.imread('noise.jpg')
blur=cv.blur(img,(3,3)) #(3×3)为核大小
cv.imshow('original',img)
cv.imshow('blur',blur)
cv.waitKey(0)
cv.destroyAllWindows()
处理结果:
代码:
import cv2 as cv
img=cv.imread('noise.jpg')
box=cv.boxFilter(img,-1,(3,3),normalize=True) # -1 表示颜色通道一致,(3,3)表示卷积核的大小 normalize表示归一化,如果选择归一化,则和均值滤波是一样的
box2=cv.boxFilter(img,-1,(3,3),normalize=False)
# normalize为false,不进行归一化处理,此时模板内像素进行处理时可能会发生越界的情况(即超过最大的像素值255),越界的情况会直接取最大值255
cv.imshow('boxfilter1',box)
cv.imshow('box2',box2)
cv.waitKey(0)
cv.destroyAllWindows()
处理结果(进行归一化):
处理结果(不进行归一化):
原理:
高斯滤波常用的一个 3×3 模板
代码:
cv.GaussianBlur(src,ksize,sigmaX,sigmaY)
如果仅指定 sigmaX,则将 sigmaY 与 sigmaX 相同。如果两个都为零,则根据内核大小进行计算。
import cv2 as cv
img=cv.imread('noise.jpg')
gauss=cv.GaussianBlur(img,(7,7),0)# (7,7)为卷积核大小
cv.imshow('original',img)
cv.imshow('gauss',gauss)
cv.waitKey(0)
cv.destroyAllWindows()
处理结果:
中值滤波是一种非线性滤波,它能在滤除噪声的同时很好地保持图像边缘。
原理: 以某像素为中心的窗口内所有像素的灰度按从小到大排序,取排序结果的中间值作为该像素的灰度值。
计算思路:
例如我们以 220 为中心选取了一个 3×3 的窗口,此时对窗口内所有像素按灰度大小进行排序,取中间值 123 作为中值滤波后的像素值。
代码:
cv.medianBlur(src,ksize)
import cv2 as cv
img=cv.imread('noise.jpg')
media=cv.medianBlur(img,5)
cv.imshow('original',img)
cv.imshow('media',media)
cv.waitKey(0)
cv.destroyAllWindows()
处理结果:
import numpy as np
import cv2 as cv
img=cv.imread('noise.jpg')
blur=cv.blur(img,(3,3))
gauss=cv.GaussianBlur(img,(7,7),0)
media=cv.medianBlur(img,5)
res=np.hstack((img,blur,gauss,media)) # 水平拼接所有图像
cv.imshow('all',res)