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指令集对代码进行优化