一、高斯函数
一维高斯函数:
二位高斯函数:
二位高斯函数分布
二、高斯滤波代码实现
代码语言:javascript复制/*************************************************************
*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的高斯模板,如下所示:
通常对高斯分布做一定的简化:
得到:
对模板进行修正:得到我们常用的3* 3 的经典模板
同样可以得到 5 * 5 的模板
用木板的好处是,对特定半径可以直接计算,提升效率.
快速高斯模糊
直接用二维高斯模糊效率不高,因此采用快速算法,将二维高斯函数分解为
即:按行进行一次一维高斯滤波,再按列进行一次一维高斯滤波
三、快速高斯模糊代码实现:
代码语言:javascript复制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验证