Bilateral filter 双边滤波器 C#版本

人类的眼镜与大脑是自带滤波器的,能抗干扰。可是计算机和传感器不滤波不行。遇到要计算图像梯度、曲率的时候,哪怕是很微弱的白噪声都会造成可笑的结果,这是我拿实测数据试出来的。

滤波的方式有很多种,根据你用什么滤波器可以得到不同的效果。最容易理解的均值滤波,相对不太困难的高斯滤波可以用力的消除白噪声,计算速度也很快,缺点是图像特征也会丢失很多。运算速度很难提升的中值滤波,可以干掉讨厌的椒盐噪声同时保留绝大部分细节,缺点是对白噪声无能为力。如果能够准确调节参数的kalman滤波器简直是完美,缺点同样就是需要人工调参数。

那么有没有能够很好消除白噪声,同时尽可能保留图像特征的滤波器?

有,双边滤波(bilateral filter)就是一种可以保留图像特征,同时很好的去除白噪声的方法。

重新看一下均值滤波、高斯滤波,可以这样解释。矩阵位置[x,y]处的滤波输出值G(x,y) 是周围范围内的元素的加权平均:

G(x,y)=\sum w(u,v)m(u,v)/ \sum w(u,v)

w(u,v)是u,v位置处的权重。

均值滤波中 w(u,v) =1,和u,v无关

高斯滤波中 w(u,v) = e ^{ -d/2\sigma ^{2} }

可以看出w(u,v)只考虑了位置距离d,并没有考虑其他。

P过图的就知道,想保留图像特征,就不能只考虑像素位置,还要考虑像素附近颜色。颜色相邻、视作同一部分的才予以平均处理。

定义i为两个像素的颜色距离(值距离),在权重函数中添加一项:

w_{bilateral}(u,v) = e^{ -d/2\sigma_{d}^{2}} e^{ -i/2\sigma_{i}^{2}}

这个新的权重函数就是双边滤波器区别于高斯滤波器的重点。

附上C#代码实现。Matrix是自己做的矩阵类,可以用mathdotnet中的matrix类替代。d是滤波器半宽,sigmaValue与sigmaSpace取大值,滤波涂抹效果明显,取小值,滤波倾向于保留原状。

public static Matrix BilateralFiltering(Matrix src, int d, double sigmaValue, double sigmaSpace, BoardType board = BoardType.Replicate){
            Matrix dst = new Matrix(src.ColumnCount, src.RowCount);
            double sig_s = 2* sigmaSpace * sigmaSpace;
            double sig_i = 2* sigmaValue * sigmaValue;
            for (int i = 0; i < src.ColumnCount; i++)
            {
                for (int j = 0; j < src.RowCount; j++)
                {
                    double weightSum = 0;
                    double filterValue = 0;
                    for (int row_d = -d; row_d <= d; row_d++)
                    {
                        for (int col_d = -d; col_d <= d; col_d++)
                        {
                            int distance_Square = row_d * row_d + col_d * col_d;
                            int d_v = src[i, j] - src[i + row_d, j + col_d];
                            double gi = Math.Exp(-d_v * d_v /  sig_i) / (Math.PI* sig_i);
                            double gs = Math.Exp(-distance_Square /  sig_s) / (Math.PI* sig_s);
                            double w = gi * gs;
                            weightSum += w;
                            filterValue += w * src[i + row_d, j + col_d];
                        }
                    }
                    dst[i, j] = (int)(filterValue / weightSum);
                }
            }
            return dst;
        }

滤波器的运算复杂度是O(h*w*d^{2}),d值对运算速度影响很明显。

下面是用来测试的源图像

取d=10, sigmaSpace=10, sigmaValue=10,滤波结果如下

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值