图像处理基础-高斯模糊

2020-10-29 11:35:18 浏览数 (2)

一、高斯函数

一维高斯函数:

二位高斯函数:

二位高斯函数分布

二、高斯滤波代码实现

代码语言: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验证

0 人点赞