高斯滤波和双边滤波的概念和实现

高斯滤波和双边滤波的概念和实现

高斯滤波

  高斯滤波比较简单,首先来看一下在写程序时用到的的二维高斯分布:
在这里插入图片描述
这里注意前面的常数我们省略了,因为在在计算高斯核的mask的时候,每一个对应位置的像素点都要乘这个常数,最后在归一化后,起到作用的只是权重之间的比值,这样说可能不是很清楚,用一张图来表示:
在这里插入图片描述
参考上面的公式,(0,0)点的位置取x=y=0,很明显,(0,0)点位置的权重最大这是因为二维高斯分布中,越靠近中心的位置,概率密度函数越大,有中心往四周递减,就比如(1,0)到(0,0)的距离是1,而(1,1)到(0,0)的距离是 2 \sqrt{2} 2 ,所以(1,0)点的权重就要比(0,0)点更大,值得注意的是滤波后的图像的某一点处对应的像素值是在原图像上面的高斯核覆盖的图像的加权相加,所以这里要对权值做归一化,就是让上图中9个点出的权值加加在一起等于1
  得到根据公式计算出高斯核后,无脑在原图像上扫就可以了,注意如果不对原图像进行填充,得到的图像的长和宽都是要比原图像少一个(高斯核长度-1)的,具体实现过程放在下面的代码中了

双边滤波

  由于高斯核在滤波的过程中只关心一个像素周围的像素到该像素的距离,并不关心该像素和周围的像素的大小关系,所以有点无脑模糊的意思,双边滤波就是将一个像素和周围像素之间的大小关系考虑进来了,这里我们简单的说就是当一个像素旁边的像素的像素值和这个中心像素差的很远的时候,我们就要把这个值差的很远的像素的权重减小,因为这个像素很可能和中心像素点不在一个“语义”上面,如果给它的权值设置的很大,就会将中心像素拉入错误的语义,这样的语义交融就是我们所说的“模糊”,双边滤波的实现也不难,基本思想也是用一个“核”在原图上面扫,只不过这个核k=k1*k2,k1就是高斯核,k2是:在这里插入图片描述
这里的f(i,j)就是中心点的像素值,f(k,l)就是中心点周围某个点(k,l)的像素值可以看到,(k,l)核中心点差的越大,他对应的权值就越小

实现汇总

  基于python+numpy的简单实现,运行速度一般,kernel_size搞大了跑的会比较慢,为了方便看用了进度条,没这个包的朋友可以自己在python环境里面pip install tqdm安装一下,还需要PIL的支持,没有的pip install scikit-image安装一下,numpy就不多赘述了

高斯滤波

#mask和图像上的像素无关,直接生成mask
def GenerateGaussianMask(kernel_size=3, sigma=0.8):
    mask = [[[0.,0.,0.] for i in range(kernel_size)] for j in range(kernel_size)]
    sum, center_x, center_y = 0, (kernel_size - 1) / 2, (kernel_size - 1) / 2
    for i in range(kernel_size):
        for j in range(kernel_size):
            tem = (1 / 2 * PI * sigma ** 2) * \
                  (math.exp(-(((i - center_x) ** 2 + (j - center_y) ** 2) / 2 * sigma ** 2)))
            mask[i][j]=[tem,tem,tem]
            sum += tem
    mask=np.array(mask)
    mask/=[sum]
    return mask

#高斯滤波
def GaussianFilt(img, kernel_size=9, sigma=0.2):
    mask = GenerateGaussianMask(kernel_size, sigma)
    img_np = np.asarray(img)
    print(img_np.shape)
    img_gf_np = np.zeros((img_np.shape[0] - kernel_size + 1, img_np.shape[1] - kernel_size + 1,3))

    for i in tqdm(range(img_gf_np.shape[0])):
        for j in range(img_gf_np.shape[1]):
            tem=img_np[i:i+kernel_size,j:j+kernel_size,:]*mask
            tem=np.sum(np.sum(tem,axis=0,keepdims=False),axis=0,keepdims=False)
            img_gf_np[i][j] = tem

    img_gf = Image.fromarray(np.uint8(img_gf_np))
    img_gf.show()
    return

双边滤波

这里注意需要用到上面GenerateGaussianMask函数,都复制到一个文件里面就好

#生成双边滤波的mask
def GenerateBilateralMask(region,mask_s,sigma_r=10):
    kernel_size=region.shape[0]
    mask_r = [[[0., 0., 0.] for i in range(kernel_size)] for j in range(kernel_size)]
    sum, center_x, center_y = 0, int((kernel_size - 1) / 2), int((kernel_size - 1) / 2)
    for i in range(kernel_size):
        for j in range(kernel_size):
            tem=math.exp(-((np.sum(region[i][j])-np.sum(region[center_x][center_y]))**2/(2*sigma_r**2)))
            mask_r[i][j]=[tem,tem,tem]
            sum+=(tem*mask_s[i][j][0])
    mask=mask_r*mask_s/[sum]
    return np.sum(np.sum(mask*region,axis=0,keepdims=False),axis=0,keepdims=False)


#双边滤波
def BilateralFilt(img,kernel_size=9,sigma_s=0.2,sigma_r=30):
    mask_s=GenerateGaussianMask(kernel_size,sigma_s)
    img_np = np.asarray(img,dtype=float)
    print(img_np.shape)
    img_bf_np = np.zeros((img_np.shape[0] - kernel_size + 1, img_np.shape[1] - kernel_size + 1, 3))
    for i in tqdm(range(img_bf_np.shape[0])):
        for j in range(img_bf_np.shape[1]):
            region=img_np[i:i+kernel_size,j:j+kernel_size,:]
            img_bf_np[i][j]=GenerateBilateralMask(region,mask_s,sigma_r)

    img_gf = Image.fromarray(np.uint8(img_bf_np))
    img_gf.show()
    return

看一下最终效果:
原图:
在这里插入图片描述
高斯滤波:
在这里插入图片描述

双边滤波:
在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贪睡熊猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值