双边滤波
双边滤波能够根据像素值来权衡其权重,若某像素值与当前处理像素的值差别较大,则该像素权重较低,因此可以很好地保留高频区域的信息(高频区域周围像素值差别较大,不应简单的平均化处理)
代码
# kernel_size:滤波核的大小(0 表示根据sigma自动计算),sigma_color:值域滤波sigma,sigma_space:空间域滤波sigma
def BilateralFilter(img,kernel_size,sigma_color,sigma_space):
Bila = cv2.bilateralFilter(img,kernel_size,sigma_color,sigma_space)
return Bila
引导滤波
引导滤波除了可以用于图像平滑,还可以用于HDR压缩、细节增强、图像去雾、联合上采样等图像处理任务。
下图中q为输出图像,p为输入图像,n为噪声,I为引导图
引导滤波基于一个理论:输出图像的每个像素值都可以由引导图对应像素点经过线性变化得到(不同像素点对应不同的ai,bi)
ak,bk手动推导过程
推导过程O为输出图像,I为输入图像,n为噪声,i为像素点,wk为局部区域(滤波核区域)
注意上式计算出ak,bk后还不能得到输出图像O,因为ak,bk为每个滤波核(区域)对应的ab参数,而某一个像素点可能属于多个区域,因此需要将ak,bk转变为ai,bi,即每个像素点对应的ab参数。
转变的方法为:像素点i所属于多个区域的对应ak的均值作为像素点i的a值,同理bi
最终Oi=ai*Ii+bi
引导滤波的意义
引导滤波代码
def GuideFilter(img, guide, kernel_size, eps):
# 为什么要除以255,因为eps取值一般为小于1的数,为了使平滑区域ak接近0,高频区域ak接近1,eps需要有足够的分量,因此img和guide的值不能太大使eps失活,当然如果不除以255且eps值取很大(如1000)也是可以的
img = img / 255.0
guide = guide / 255.0
meanI = cv2.blur(img, (kernel_size, kernel_size))
meanG = cv2.blur(guide, (kernel_size, kernel_size))
meanIG = cv2.blur(np.multiply(img, guide), (kernel_size, kernel_size))
meanG2 = cv2.blur(np.multiply(guide, guide), (kernel_size, kernel_size))
CovIG = meanIG - np.multiply(meanI, meanG)
VarG = meanG2 - np.multiply(meanG, meanG)
ak = CovIG / (VarG + eps)
bk = meanI - np.multiply(ak, meanG)
ai = cv2.blur(ak, (kernel_size, kernel_size))
bi = cv2.blur(bk, (kernel_size, kernel_size))
q = np.multiply(ai, guide) + bi
q *= 255.0
return q.astype(np.uint8)
结果
原图:
引导滤波:(guide=img,kernelsize=9,eps=0.01)
双边滤波:(kernelsize=21,sigmacolor=40,sigmaspace=100)
参考:【图像滤波(高斯滤波、双边滤波、引导滤波原理及实现)】https://www.bilibili.com/video/BV1fo4y1K7Rw?vd_source=525a496cd261d261388409b968c262c7