在尽量保留图像原有信息的情况下,过滤掉图像内部的噪声,这一过程称为对图像的平滑处理,所得的图像称为平滑图像。
图像平滑处理会对图像中与周围像素点的像素值差异较大的像素点进行处理,将其值调整为周围像素点像素值的近似值。
图像平滑处理的基本原理是,将噪声所在像素点的像素值处理为其周围临近像素点的值的近似值。取近似值的方式很多
图像平滑处理对应的是英文Smoothing Images。
图像平滑处理通常伴随图像模糊操作,因此图像平滑处理有时也被称为图像模糊处理,图像模糊处理对应的英文是Blurring Images。
图像滤波对应的英文是Images Filtering。
用当前像素点周围N·N个像素值的均值来代替当前像素值。
使用该方法遍历处理图像内的每一个像素点,即可完成整幅图像的均值滤波。
在OpenCV中,实现均值滤波的函数是cv2.blur()。
其语法格式为:
dst = cv2.blur( src, ksize, anchor, borderType )
dst是返回值,表示进行均值滤波后得到的处理结果。
src是需要处理的图像,即原始图像。它可以有任意数量的通道,并能对各个通道独立处理。图像类型应该是CV_8U、CV_16U、CV_16S、CV_32F或者CV_64F中的一种。
ksize是滤波核的大小。滤波核大小是指在均值处理过程中,其邻域图像的高度和宽度。例如,其值可以为(5, 5),表示以5×5大小的邻域均值作为图像均值滤波处理的结果
anchor是锚点,其默认值是(-1, -1),表示当前计算均值的点位于核的中心点位置。该值使用默认值即可,在特殊情况下可以指定不同的点作为锚点。
borderType是边界样式,该值决定了以何种方式处理边界一般情况下不需要考虑该值的取值,直接采用默认值即可。
通常情况下,使用均值滤波函数时,对于锚点anchor和边界样式borderType,直接采用其默认值即可。
因此,函数cv2.blur()的一般形式为:
dst = cv2.blur( src, ksize )
例子:
import cv2
o=cv2.imread("image\\lenaNoise.png") #读取待处理图像
r=cv2.blur(o, (5,5)) #使用blur函数处理
cv2.imshow("original", o)
cv2.imshow("result", r)
cv2.waitKey()
cv2.destroyAllWindows()
方框滤波不会计算像素均值。
在方框滤波中,可以自由选择是否对均值滤波的结果进行归一化,即可以自由选择滤波结果是邻域像素值之和的平均值,还是邻域像素值之和。
实现方框滤波的函数是cv2.boxFilter()
dst = cv2.boxFilter( src, ddepth, ksize, anchor, normalize, borderType )
通常情况下,在使用方框滤波函数时,对于参数anchor、normalize和borderType,直接采用其默认值即可。
方框滤波函数对normalize参数使用了默认值。在默认情况下,该值为1,表示要进行归一化处理。
因此,函数cv2.boxFilter()的常用形式为:
dst = cv2.boxFilter( src, ddepth, ksize )
在进行均值滤波和方框滤波时,其邻域内每个像素的权重是相等的。在高斯滤波中,会将中心点的权重值加大,远离中心点的权重值减小,在此基础上计算邻域内各个像素值不同权重的和。
卷积核中的值不再都是1。
实现高斯滤波的函数是cv2.GaussianBlur()。
该函数的语法格式是:
st = cv2.GaussianBlur( src, ksize, sigmaX, sigmaY, borderType )
dst是返回值,表示进行高斯滤波后得到的处理结果。
src是需要处理的图像,即原始图像。它能够有任意数量的通道,并能对各个通道独立处理。图像类型应该是CV_8U、CV_16U、CV_16S、CV_32F或者CV_64F中的一种。
ksize是滤波核的大小。滤波核大小是指在滤波处理过程中其邻域图像的高度和宽度。需要注意,滤波核的值必须是奇数。
sigmaX是卷积核在水平方向上(X轴方向)的标准差,其控制的是权重比例。
sigmaY是卷积核在垂直方向上(Y轴方向)的标准差。
如果将该值设置为0,则只采用sigmaX的值;如果sigmaX和sigmaY都是0,则通过ksize.width和ksize.height计算得到。
其中:
sigmaX=0.3×[(ksize.width-1)×0.5-1] + 0.8
sigmaY=0.3×[(ksize.height-1)×0.5-1] + 0.8
borderType是边界样式,该值决定了以何种方式处理边界。
一般情况下,不需要考虑该值,直接采用默认值即可。
sigmaY和borderType是可选参数。sigmaX是必选参数,但是可以将该参数设置为0,让函数自己去计算sigmaX的具体值。
官方文档建议显式地指定ksize、sigmaX和sigmaY三个参数的值,以避免将来函数修改后可能造成的语法错误。当然,在实际处理中,可以显式指定sigmaX和sigmaY为默认值0。
函数cv2.GaussianBlur()的常用形式为:
dst = cv2.GaussianBlur( src, ksize, 0, 0 )
例子:
import cv2
o=cv2.imread("image\\lenaNoise.png")
r=cv2.GaussianBlur(o, (5,5),0,0)
cv2.imshow("original", o)
cv2.imshow("result", r)
cv2.waitKey()
cv2.destroyAllWindows()
用邻域内所有像素值的中间值来替代当前像素点的像素值。
中值滤波会取当前像素点及其周围临近像素点(一共有奇数个像素点)的像素值,将这些像素值排序,然后将位于中间位置的像素值作为当前像素点的像素值。
中值滤波的函数是cv2.medianBlur()
dst = cv2.medianBlur( src, ksize)
例子:
import cv2
o=cv2.imread("image\\lenaNoise.png")
r=cv2.medianBlur(o,3)
cv2.imshow("original", o)
cv2.imshow("result", r)
cv2.waitKey()
cv2.destroyAllWindows()
由于没有进行均值处理,中值滤波不存在均值滤波等滤波方式带来的细节模糊问题。在中值滤波处理中,噪声成分很难被选上,所以可以在几乎不影响原有图像的情况下去除全部噪声。但是由于需要进行排序等操作,中值滤波需要的运算量较大。
双边滤波是综合考虑空间信息和色彩信息的滤波方式,在滤波过程中能够有效地保护图像内的边缘信息。
双边滤波在计算某一个像素点的新值时,不仅考虑距离信息(距离越远,权重越小),还考虑色彩信息(色彩差别越大,权重越小)。
双边滤波综合考虑距离和色彩的权重结果,既能够有效地去除噪声,又能够较好地保护边缘信息。
在双边滤波中,当处在边缘时,与当前点色彩相近的像素点(颜色距离很近)会被给予较大的权重值;而与当前色彩差别较大的像素点(颜色距离很远)会被给予较小的权重值(极端情况下权重可能为0,直接忽略该点),这样就保护了边缘信息。
实现双边滤波的函数是cv2.bilateralFilter()
dst = cv2.bilateralFilter( src, d, sigmaColor, sigmaSpace, borderType )
dst是返回值,表示进行双边滤波后得到的处理结果。
src是需要处理的图像,即原始图像。它能够有任意数量的通道,并能对各个通道独立处理。图像类型应该是CV_8U、CV_16U、CV_16S、CV_32F或者CV_64F中的一种。
d是在滤波时选取的空间距离参数,这里表示以当前像素点为中心点的直径。
如果该值为非正数,则会自动从参数sigmaSpace计算得到。如果滤波空间较大(d>5),则速度较慢。因此,在实时应用中,推荐d=5。对于较大噪声的滤波,可以选择d=9。
sigmaColor是滤波处理时选取的颜色差值范围,该值决定了周围哪些像素点能够参与到滤波中来。**与当前像素点的像素值差值小于sigmaColor的像素点,能够参与到当前的滤波中。**该值越大,就说明周围有越多的像素点可以参与到运算中。该值为0时,滤波失去意义;该值为255时,指定直径内的所有点都能够参与运算。
sigmaSpace是坐标空间中的sigma值。它的值越大,说明有越多的点能够参与到滤波计算中来。当d>0时,无论sigmaSpace的值如何,d都指定邻域大小;否则,d与sigmaSpace的值成比例。
borderType是边界样式,该值决定了以何种方式处理边界。一般情况下,不需要考虑该值,直接采用默认值即可。
为了简单起见,可以将两个sigma(sigmaColor和sigmaSpace)值设置为相同的。如果它们的值比较小(例如小于10),滤波的效果将不太明显;如果它们的值较大(例如大于150),则滤波效果会比较明显,会产生卡通效果。
在函数cv2.bilateralFilter()中,参数borderType是可选参数,其余参数全部为必选参数。
例子:
使用双边滤波函数cv2.bilateralFilter()对原始图像进行滤波
import cv2
o=cv2.imread("image\\lenaNoise.png")
r=cv2.bilateralFilter(o,25,100,100)
cv2.imshow("original", o)
cv2.imshow("result", r)
cv2.waitKey()
cv2.destroyAllWindows()
双边滤波去除噪声的效果并不好。
双边滤波的优势体现在对于边缘信息的处理上
大多数滤波方式所使用的卷积核都具有一定的灵活性,能够方便地设置卷积核的大小和数值。
但是,有时希望使用特定的卷积核实现卷积操作
在OpenCV中,允许用户自定义卷积核实现卷积操作。
使用自定义卷积核实现卷积操作的函数是cv2.filter2D()。
其语法格式为:
dst = cv2.filter2D( src, ddepth, kernel, anchor, delta, borderType )
在通常情况下,使用卷积函数cv2.filter2D()时,对于参数锚点anchor、修正值delta、边界样式borderType,直接采用其默认值即可。
因此,函数cv2.filter2D()的常用形式为:
dst = cv2.filter2D( src, ddepth, kernel )