opencv 均值平滑blur,中值平滑medianBlur,高斯平滑GaussianBlur(),双边平滑bilateralFilter()

1.均值平滑blur()
均值平滑的滑动窗口所有系数为1/(窗口高*窗口宽).

dst=cv2.blur(src, ksize[, dst[, anchor[, borderType]]])

src:源图像,通道数不限,数据类型必须为CV_8U, CV_16U, CV_16S, CV_32F or CV_64F;
ksize:kernel尺寸、窗口大小,二元组类型,元素值可以是偶数或奇数;
anchor:锚点,默认为(-1,-1),作用于滑动窗口的中心点;
borderType:边界处理类型;

img_ret = cv2.blur(img,(3,3))

2.中值平滑medianBlur()
中值平滑和均值平滑一样也用到了滑动窗口,但是它并不是计算滑动窗口中的某种加权和,而是使用原图像滑动窗口中所有像素值排序后的中值作为新图像的像素值。
dst=cv2.medianBlur(src, ksize[, dst])
src:源图像,通道数可以是1,3或4,当ksize为3或者5时,数据类型可以是CV_8U, CV_16U, CV_32F,当使用更大的ksize时,数据类型只能是CV_8U;
ksize:kernel尺寸、窗口大小,整数型,大于1的奇数值;

img_ret = cv2.medianBlur(img,3)

3.像素值对比
平滑处理是图像滤波的一种,可以看做是低通滤波,它会消除图像的高频“信号”,让图像看起来更模糊、平滑,通过将变化前后的图像像素值绘制曲线可以更形象地观察到这种平滑效果。

4.高斯平滑GaussionBlur()
高斯平滑则根据距离中心点的间距远近其权重会不同,这种方式看起来更符合”惯例”。

高斯分布的曲线可以看到(μ=0时):
当x=0时,f(x)的值最大,当x向两边变化时,f(x)的值越来越小;
这个曲线在x=0的2侧是对称的,f(-1)=f(1),f(-2)=f(2);
σ越大,曲线越平坦,x=0时的取值越低。

OpenCV中要用到二维高斯分布.

用matplotlib绘制二维高斯分布:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = Axes3D(fig) 
X = np.arange(-3, 3.1, 0.1,dtype=np.float64).reshape(-1,1)
Y = np.arange(-3, 3.1, 0.1,dtype=np.float64)
mux,muy=0,0
sigmax,sigmay = 0.8,0.8
expont = -0.5*(((X-mux)/sigmax)**2 + ((Y-muy)/sigmay)**2)
Z=np.exp(expont)/(2*np.pi*sigmax*sigmay)
ax.plot_surface(X, Y, Z, rstride=2, cstride=2, cmap=cm.viridis)
plt.show()

GaussianBlur()的接口形式:
dst=cv2.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])

src:通道数任意,实际处理是分通道处理;图像深度只能是CV_8U, CV_16U, CV_16S, CV_32F or CV_64F;
ksize:元组类型,窗口大小,宽度和高度可以不一样,但是必须是正的奇数;如果设置为0,则根据sigma计算得到。
sigmaX:图像X方向的标准差,对应前述二维高斯分布的σ1;
sigmaY:图像Y方向的标准差,对应前述二维高斯分布的σ2,如果传入0,会等于sigmaX,如果sigmaX和sigmaY都传入0,sigmaX和sigmaX则根据ksize计算;
borderType:边界处理方式;

注意:GaussianBlur的首字母是大写的G,和其他大多数OpenCV函数名称采用小驼峰命名风格稍有差异。

因为都是以滑动窗口中心点为原点,为了保证中心点(x,y)=(0,0)的权重为最大值,所以在OpenCV的高斯平滑中μ1和μ2都设置为0,这样在调用高斯平滑函数时只需要传入σ1(sigmaX)和σ2(sigmaY)。

img_ret = cv2.GaussianBlur(img,(11,11),0)
imshow(cv2.cvtColor(img_ret,cv2.COLOR_BGR2RGB))

对应到高斯分布曲线的特性,当sigma越大时,原点的取值越小,周围点的取值更大,对应到图像上中心点的权重越低,周围点权重越高,所以sigma越大图像越模糊。
5.双边平滑bilateralFilter()
均值、中值、高斯平滑的去躁是一种“无差别攻击”,所有的像素都受到同一个加权系数的影响,所以在平滑过程中也会影响到图像的边沿(像素值突变的地方),接下来要介绍的双边滤波则可以在去除噪声的同时又能保持图像的边沿,也就是”去噪保边”。

bilateralFilter()的接口形式:
dst=cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace[, dst[, borderType]])

src:8bit或浮点类型;1或3通道;
d:窗口大小,如果为非正数,根据sigmaSpace计算;d>5时速度会比较慢,当噪声比较严重时可以选择d>=9,但是此时不适合对时间敏感的处理;
sigmaColor:亮度差的sigma参数;
sigmaSpace:空间距离的sigma参数,同时作用于图像的X和Y(行、列)2个方向;
borderType:边界处理方式;

滑动窗口大小的参数里,高斯平滑的ksize参数是一个宽高可以不等的元组,但是双边平滑用的参数d是一个整型类型,这也决定了其滑动窗口宽高是相等的。

如果d小于0,用sigma_space*1.5后取整得到半径,如果d大于0则先除以2得到半径radius,然后用半径radius和1比较取其中更大的值,最后乘以2加1,这样的得到的d可以保证是不小于3的奇数。

sigmaColor和sigmaSpace参数比较小的时候(<10),平滑的效果不是很明显,当参数比较大或者多次平滑后的图像看起来会比较卡通化.

img_ret = cv2.bilateralFilter(img,7,25,25)
img_edge=cv2.Sobel(img_ret,cv2.CV_8U,1,0,ksize=3)

在颜色突然变化的地方(边沿),高斯平滑只保留了一半左右的边界,而双边平滑几乎将所有的边界保留下来,而且高斯平滑的边界亮度平均值也没有双边平滑高。

高斯平滑对比均值和中值平滑其取值更符合“惯例”,在空间距离上距离越近的像素用来计算新像素的值其权重越大。均值平滑、中值平滑和高斯平滑会对整幅图像实现无差别的平滑,一个固定系数的滑动窗口作用于整个图像,所以平滑后的图像虽然处理掉了噪声,但是边沿部分也会被削弱。而双边平滑在高斯平滑使用的系数基础上乘以像素差值的高斯函数,和中心点像素差值越大整个系数值越小,最后就能达到去躁保边的效果。

猜你喜欢

转载自blog.csdn.net/aqiangdeba/article/details/129767116