专栏首页音视频技术学习笔记图像处理基础-高斯模糊

图像处理基础-高斯模糊

一、高斯函数

一维高斯函数:

二位高斯函数:

二位高斯函数分布

二、高斯滤波代码实现

/*************************************************************
*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 的模板

用木板的好处是,对特定半径可以直接计算,提升效率.

快速高斯模糊

直接用二维高斯模糊效率不高,因此采用快速算法,将二维高斯函数分解为

即:按行进行一次一维高斯滤波,再按列进行一次一维高斯滤波

三、快速高斯模糊代码实现:

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 条评论
登录 后参与评论

相关文章

  • 照片处理-几何滤镜实现哈哈镜

    几何滤镜比较简单,不涉及色彩模型,按照某种算法,对原图进行采样,得到一张新的图片。看起来就像是把原图进行了几何变形。 这篇文章通过两个简单的案例,更直观的感受...

    sumsmile
  • Qt学习采坑记录

    6.calling '**' with incomplete return type 解决方法是,在项目头文件中,添加相应的头文件包含,在本题中是

    sumsmile
  • 22.opengl高级-实例化

    绘制有共同特征,或者按照一定规则变化的图形阵列,如果挨个按照普通流程来绘制:绑定VAO、绑定纹理、设置uniform-->调用glDrawArrays(GL_T...

    sumsmile
  • python代码实现图片噪声去除

    今天来给大家分享下怎么做图片的噪声去除。平时其实大家上网都能遇到这样的场景,就是输入讨厌验证码,怎么都输不对。验证码现在可以说是千奇百怪、分外妖娆,为啥要做成这...

    IT派
  • netty源码分析一之NioServerSocketChannel

    这里调用的也是SelectorProvider.provider()的openServerSocketChannel方法。

    开发架构二三事
  • [PYTHON]python 基础笔记(

    尽管这是一个简单的问题,但是问题本身并没有给我们足够的信息来解决它。进一步的分析是必需的。例如,我们如何确定该备份哪些文件?备份保存在哪里?我们怎么样存储备份?

    py3study
  • 理解网络命名空间与 VETH Pair 对

    如果你使用过 Docker 和 Kubernetes,那么可能应该听说过 network namespace(网络命名空间),最近在我们的 《Kubernete...

    我是阳明
  • 项目案例——双ISP接入中NAT配置

    随着企业业务需求的增加,大量的内网访问外网的数据请求通过单一的ISP已无法满足现状,因此越来越多的企业都会使用双ISP线路接入(电信与网通/移动),从而保证内网...

    民工哥
  • sc-ATAC-seq细胞类型注释策略

    解释任何单细胞测序数据的起点都是对给定数据集中的细胞簇进行注释。由于缺乏专门设计的工具以及在单细胞ATAC-seq数据中使用不直观的顺式和跨式调控元素(unin...

    生信技能树jimmy
  • 图形解读系列 | 散点图也不简单

    来源:https://www.r-graph-gallery.com/272-basic-scatterplot-with-ggplot2.html

    生信宝典

扫码关注云+社区

领取腾讯云代金券