一、高斯函数
一维高斯函数:
![](https://img.haomeiwen.com/i3144284/fcba6c8365c68f6f.png)
二位高斯函数:
![](https://img.haomeiwen.com/i3144284/1681854e4bfc9712.png)
![](https://img.haomeiwen.com/i3144284/11e5fe85e5492a4f.png)
二、高斯滤波代码实现
/*************************************************************
*Function: Gauss mask compute
*Params:
* r-radius of gauss filter
* sigma-sigma of gauss filter
* gaussMask-gauss weight to compute with size of (2r+1)*(2r+1)
*Return NULL
************************************************************/
void GaussMask(int r, double sigma, double gaussMask[])
{
double PI = 3.1415926;
double sum = 0;
int stride = 2 * r + 1;
for (int y = -r, h = 0; y <= r; y++, h++)
{
for (int x = -r, w = 0; x <= r; x++, w++)
{
// 注意这里2.0 * PI没有开方,其实无所谓,只是求权重,2.0 * PI不影响权重的结果
gaussMask[w + h * stride] = (1.0 / (2.0 * PI * sigma * sigma)) * (exp(-((double)x * (double)x + (double)y * (double)y) / (2.0 * sigma * sigma)));
sum += gaussMask[w + h * stride];
}
}
for (int i = 0; i < stride * stride; i++)
{
gaussMask[i] = gaussMask[i] / sum;
}
};
设置参数 r = 1, sigma= 1.0 得到 3 * 3的高斯模板,如下所示:
![](https://img.haomeiwen.com/i3144284/d4492f5f1cfe3092.png)
![](https://img.haomeiwen.com/i3144284/badedc66ef442d13.png)
得到:
![](https://img.haomeiwen.com/i3144284/22d41de715698e2f.png)
对模板进行修正:得到我们常用的3* 3 的经典模板
![](https://img.haomeiwen.com/i3144284/752411ff75002e07.png)
![](https://img.haomeiwen.com/i3144284/9f71dec70930f877.png)
用木板的好处是,对特定半径可以直接计算,提升效率.
快速高斯模糊
直接用二维高斯模糊效率不高,因此采用快速算法,将二维高斯函数分解为
![](https://img.haomeiwen.com/i3144284/e4bb2c415fcfd229.png)
即:按行进行一次一维高斯滤波,再按列进行一次一维高斯滤波
三、快速高斯模糊代码实现:
int f_FastGaussFilter(unsigned char* srcData,int width, int height,int stride,float r)
{
int ret = 0;
int radius = (int)r;
if(r == 0)
return ret;
unsigned char* dstData = (unsigned char*)malloc(sizeof(unsigned char)*height*stride);
unsigned char* tempData = (unsigned char*)malloc(sizeof(unsigned char)*height*stride);
memset(dstData, 255, sizeof(unsigned char) * height * stride);
int totalWei = 0;
int i,j,k;
float sigma = r;
unsigned char *kernel = (unsigned char *)malloc(2*radius+1);
for (i = -radius; i <= radius; i++)
{
kernel[i+radius] = (unsigned char) (exp(-(float)i*i/(2*sigma*sigma))*128);
totalWei += kernel[i+radius];
}
int tempR = 0, tempG = 0, tempB = 0;
int v = 0;
int K = 0;
int rem = 0;
int t = 0;
int offset = stride - width * 4;
for ( j = 0; j < height; j++)
{
for ( i = 0; i < width; i++)
{
tempR = 0; tempG = 0; tempB = 0;
for ( k = -radius; k <= radius; k++)
{
rem = (abs(i + k) % width);
t = rem * 4 + j * stride;
K = kernel[k + radius];
tempB += srcData[t] * K;
tempG += srcData[t + 1] * K;
tempR += srcData[t + 2] * K;
}
v = i * 4 + j * stride;
tempData[v] = tempB / totalWei;
tempData[v + 1] = tempG / totalWei;
tempData[v + 2] = tempR / totalWei;
}
}
for ( i = 0; i < width; i++)
{
for ( j = 0; j < height; j++)
{
tempR = 0; tempG = 0; tempB = 0;
for ( k = -radius; k <= radius; k++)
{
rem = (abs(j + k) % height);
t = rem * stride + i * 4;
K = kernel[k + radius];
tempB += tempData[t] * K;
tempG += tempData[t + 1] * K;
tempR += tempData[t + 2] * K;
}
v = i * 4 + j * stride;
dstData[v] = tempB/totalWei;
dstData[v + 1] = tempG/totalWei;
dstData[v + 2] = tempR/totalWei;
}
}
memcpy(srcData, dstData, sizeof(unsigned char) * height * stride);
free(dstData);
free(tempData);
return ret;
};
todo:高斯模糊没有进行代码验证,后续需要再coding验证
网友评论