1 高斯滤波简介
了解高斯滤波之前,我们首先熟悉一下高斯噪声。高斯噪声是指它的概率密度函数服从高斯分布(即正态分布)的一类噪声。如果一个噪声,它的幅度分布服从高斯分布,而它的功率谱密度又是均匀分布的,则称它为高斯白噪声。高斯白噪声的二阶矩不相关,一阶矩为常数,是指先后信号在时间上的相关性,高斯白噪声包括热噪声和散粒噪声。
高斯滤波器是一类根据高斯函数的形状来选择权值的线性平滑滤波器。高斯平滑滤波器对于抑制服从正态分布的噪声非常有效。一维零均值高斯函数为:
g(x)=exp( -x^2/(2 sigma^2)
其中,高斯分布参数Sigma决定了高斯函数的宽度。对于图像处理来说,常用二维零均值离散高斯函数作平滑滤波器,高斯函数的图形:
2 高斯滤波函数
对于图像来说,高斯滤波器是利用高斯核的一个2维的卷积算子,用于图像模糊化(去除细节和噪声)。
1) 高斯分布
一维高斯分布:
二维高斯分布:
3 C++实现图像高斯滤波
/******************高斯滤波*************************************************************/
/*函数功能:实现图像高斯滤波
函数名字:GaussSmooth
参数 :pSrcImage 原始图像
pDstImage 结果图像
nWidth 图像宽度
nHeight 图像高度
nKernelSize 高斯核的尺寸大小
dbSigma 标准差*/
/****************************************************************************************/
void GaussSmooth(BYTE* pSrcImage, BYTE* pDstImage, int nWidth, int nHeight,
int nKernelSize, double dbSigma)
{
int i,j;
int nCenter;
double dDisX, dDisY;
double dValue;
double dSum;
dSum = 0.0;
double* pdTemp = new double[nWidth*nHeight];
nCenter = nKernelSize / 2;
double *pdKernel = new double[nKernelSize*nKernelSize];
//计算高斯核
for (i = 0; i < nKernelSize; i++)
{
for (j = 0; j < nKernelSize; j++)
{
dDisX = (double)(i - nCenter);
dDisY = (double)(j - nCenter);
dValue = exp(-(1 / 2)*(dDisX*dDisX+dDisY*dDisY) / (dbSigma*dbSigma)) / (2 * PI*dbSigma*dbSigma);
pdKernel[i*nKernelSize+j] = dValue;
dSum += dValue;
}
}
//高斯核归一化
for (i = 0; i < nKernelSize; i++)
{
for (int j = 0; j < nKernelSize; j++)
{
pdKernel[i*nKernelSize+j] /= dSum;
}
}
double dDotMul;
double dWeightSum;
//利用高斯核进行图像卷积运算
for (int y = 0; y < nHeight; y++)
{
for (int x = 0; x < nWidth; x++)
{
dDotMul = 0.0;
dWeightSum = 0.0;
for (i = -nCenter; i <= nCenter; i++)
{
for (j = -nCenter; j <= nCenter; j++)
{
if ((y + i) >= 0 && (y + i) < nHeight && (x + j) >= 0 && (x + j) < nWidth)
{
dDotMul += (double)pSrcImage[y*nWidth + x + i] * pdKernel[(nCenter + i)*nKernelSize+(nCenter+j)];
dWeightSum += pdKernel[nKernelSize + (nCenter + j)];
}
}
}
pdTemp[y*nWidth + x] = dDotMul / dWeightSum;
}
}
for (int y = 0; y < nHeight; y++)
{
int nLinePos = y*nWidth;
for (int x = 0; x < nWidth; x++)
{
pDstImage[nLinePos + x] = (int)pdTemp[nLinePos + x];
}
}
}