算法优化学习:(二)二维高斯滤波的引入

1.高斯分布

1.1一维高斯分布

高斯分布又称为正态分布,是一种广泛应用的概率分布,一维高斯分布比较常见,相关数学定义如下所示。

对于不同的均值和标准差,一维高斯分布曲线如下,可以看出标准差越大曲线越平坦,分布越平均;标准差越小,曲线越陡峭,分布越不均匀。

1.2二维高斯分布

图像一般作为二维数据处理,相应的会用到二维高斯分布。二维高斯分布的数学定义和分布曲线如下图所示。

                   

二维高斯分布有一个很重要的性质,即G(x,y) =G(x)*G(y) ,这一点在后面对二维高斯滤波的优化十分重要。

2.图像中的高斯滤波

由于种种原因,图像中总是存在噪声,假若以灰度图的形式描述图像,噪声的灰度值与其邻域灰度值往往差别较大(不过边缘像素点也有这个特征),这就为去噪提供一种简单的思路:既然噪声灰度值相对“突出”,就利用邻域的灰度信息做平衡。因此常见的去噪算法包括中值滤波(取某像素邻域的中间值作为该像素的灰度值),均值滤波(对应像素邻域的平均值),还有高斯滤波。高斯滤波简单来说利用了高斯分布,直观上看邻域中距离像素点距离越近的点其加权权值越高,反之越低。

对于二维高斯滤波,一个重要参数就是标准差,标准差对于高斯分布的影响上面已经提到。以3X3大小的二维高斯滤波为例,对于某个像素点,以其为中心的3X3邻域如下图所示,在x、y方向取值如下,将其带入G(x,y)可得到高斯分布对应的权值。不过这些权值的和不等于1(小于1),一般会把它们再做归一化处理。

设高斯滤波半径为r,则邻域大小一般为2*r+1,生成高斯滤波加权系数示例代码如下。

void generateGaussianTemplate(double window[][11], int r, double sigma)
{
    static const double pi = 3.1415926;
    int center = r; // 模板的中心位置,也就是坐标的原点
    int ksize = 2*r + 1;// 邻域边长
    double x2, y2;
    double sum = 0;
    for (int i = 0; i < ksize; i++)
    {
        x2 = pow(i - center, 2);
        for (int j = 0; j < ksize; j++)
        {
            y2 = pow(j - center, 2);
            double g = exp(-(x2 + y2) / (2 * sigma * sigma));
            g /= 2 * pi * sigma;
            sum += g;
            window[i][j] = g;
        }
    }
    
    for (int i = 0; i < ksize; i++)
    {
        for (int j = 0; j < ksize; j++)
        {
            window[i][j] /= sum;
        }
    }
}

之后就是使用该权值模板对像素点邻域做加权求和。对于M*N大小的灰度图,若二维高斯滤波模板半径为r,则完成滤波需要(2*r+1)*(2*r+1)*M*N次乘法和((2*r+1)*(2*r+1)-1)*M*N次加法。

3.二维高斯滤波的简化

利用二维高斯滤波的数学性质可以减少算法运算量,相关推导过程如下。

这样做,从算法层面降低了运算复杂度。

对于模板大小固定的高斯滤波,可1)提前计算好模板值保存起来,免去每次需要重新计算模板值2)模板值与邻域像素的浮点乘法,转换为定点乘法与除法,且尽量使用移位代替除法(会带来一定的精度损失)

这样就从算法层面完成了一些优化,后面开始尝试使用多线程和NEON指令集对代码进行优化

猜你喜欢

转载自blog.csdn.net/lwx309025167/article/details/82761474