【图像处理】双边滤波算法(bilateral filter)和导向滤波算法(guided filter)

一、双边滤波算法(Bilateral Filter)

1、原理

高斯滤波是以距离为权重,设计滤波模板作为滤波系数,只考虑了像素间的空间位置上的关系,因此滤波的结果会丢失边缘的信息。
高斯滤波的缺陷如下图所示:平坦区域正常滤波,图像细节没有变化,而在突变的边缘上,因为只使用了距离来确定滤波权重,导致边缘被模糊。
在这里插入图片描述
在高斯基础上,进一步优化,叠加了像素值的考虑,因此也就引出了双边滤波,一种非线性滤波,滤波效果对保留边缘更有效。
在这里插入图片描述
空间距离:当前点距离滤波模板中心点的欧式距离。
灰度距离:当前点距离滤波模板中心点的灰度的差值的绝对值。
双边滤波的核函数是空间域核与像素范围域核的综合结果:
1)在图像的平坦区域,像素值变化很小,那么像素差值接近于0,对应的像素范围域权重接近于1,此时空间域权重起主要作用,相当于进行高斯模糊;
2)在图像的边缘区域,像素值变化很大,那么像素差值大,对应的像素范围域权重变大,即使距离远空间域权重小,加上像素域权重总的系数也较大,从而保护了边缘的信息。
双边滤波的效果如下图,在突变的边缘上,使用了像素差权重,所以很好的保留了边缘。
在这里插入图片描述
在这里插入图片描述

2、opence-python 实现

import cv2
import numpy as np

image = cv2.imread('./image/cat.jpeg')
image_blur = cv2.blur(image, (3, 3))
image_bilater = np.hstack([  # 结果图像的水平拼接
    image_blur,
    cv2.bilateralFilter(image_blur, 5, 21, 21),
    cv2.bilateralFilter(image_blur, 7, 31, 31),
    cv2.bilateralFilter(image_blur, 9, 41, 41)
])
cv2.imshow('image_bilater', image_bilater)
cv2.waitKey(0)

在这里插入图片描述

二、导向滤波算法(Guided Filter)

1、原理

引导滤波的思想用一张引导图像产生权重,从而对输入图像进行处理,这个过程可以表示为下面公式:
在这里插入图片描述
公式中 q、I、p分表表示输出图像、引导图像和输入图像 ,i、j分别表示图像中像素点的索引。可以看到上方公式中权重 W 仅与引导图像 I 有关,而在双边滤波中权重 W 由输入图像自身决定。
在这里插入图片描述
在这里插入图片描述

2、python实现

"""
    uv通道滤波,取出颜色噪声
"""
import cv2
import numpy as np

image_path = './image/wait_uv_filter.png'
image = cv2.imread(image_path)
cv2.namedWindow('image', 0)
cv2.resizeWindow('image', 600, 500)
cv2.imshow('image', image)
cv2.waitKey(0)

def my_guidedFilter_oneChannel(srcImg, guidedImg, rad=9, eps=0.01):
    srcImg = srcImg / 255.0
    guidedImg = guidedImg / 255.0

    P_mean = cv2.boxFilter(srcImg, -1, (rad, rad), normalize=True)
    I_mean = cv2.boxFilter(guidedImg, -1, (rad, rad), normalize=True)

    I_square_mean = cv2.boxFilter(np.multiply(guidedImg, guidedImg), -1, (rad, rad), normalize=True)
    I_mul_P_mean = cv2.boxFilter(np.multiply(srcImg, guidedImg), -1, (rad, rad), normalize=True)

    var_I = I_square_mean - np.multiply(I_mean, I_mean)
    cov_I_P = I_mul_P_mean - np.multiply(I_mean, P_mean)

    a = cov_I_P / (var_I + eps)
    b = P_mean - np.multiply(a, I_mean)

    a_mean = cv2.boxFilter(a, -1, (rad, rad), normalize=True)
    b_mean = cv2.boxFilter(b, -1, (rad, rad), normalize=True)

    dstImg = np.multiply(a_mean, guidedImg) + b_mean

    return dstImg * 255.0


def my_guidedFilter_threeChannel(srcImg, guidedImg, rad=9, eps=0.01):
    img_shape = np.shape(srcImg)
    dstImg = np.zeros(img_shape, dtype=float)
    for ind in range(0, img_shape[2]):
        dstImg[:, :, ind] = my_guidedFilter_oneChannel(srcImg[:, :, ind],guidedImg[:, :, ind], rad, eps)
    dstImg = dstImg.astype(np.uint8)
    return dstImg


def main():
    img = cv2.imread(input_fn)
    print(np.shape(img))

    img_y = cv2.split(img)[0]
    img_u = cv2.split(img)[1]
    img_v = cv2.split(img)[2]

    image_guidedFilter = my_guidedFilter_threeChannel(img, img, 15, 0.0001)
    print(np.shape(image_guidedFilter))
    cv2.namedWindow('image_guidedFilter', 0)
    cv2.resizeWindow('image_guidedFilter', 600, 500)
    cv2.imshow('image_guidedFilter', image_guidedFilter)
    cv2.waitKey(0)

    dst_u = my_guidedFilter_oneChannel(img_u, img_u, 9, 0.0001).astype(np.uint8)
    dst_v = my_guidedFilter_oneChannel(img_v, img_v, 9, 0.0001).astype(np.uint8)
    dstimg_uv = cv2.merge([img_y, dst_u, dst_v])
    cv2.namedWindow('dstimg_uv', 0)
    cv2.resizeWindow('dstimg_uv', 600, 500)
    cv2.imshow('dstimg_uv', dstimg_uv)
    cv2.waitKey(0)


if __name__ == '__main__':
    main()

  • 4
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值