高斯算法实现

高斯算法的原理

首先,高斯滤波算法的一般过程分为两步:

  1. 计算掩膜(高斯核)
  2. 卷积(即掩膜上每一个位置的值和图像对应位置的像素值的乘积、求和运算)

其次,我们知道高斯分布也叫做正态分布;

在二维空间中,这个公式生成的曲面的等高线是从中心开始呈正态分布的同心圆。分布不为零的像素组成的卷积矩阵与原始图像做变换。每个像素的值都是周围相邻像素值的加权平均。原始像素的值有最大的高斯分布值,所以有最大的权重,相邻像素随着距离原始像素越来越远,其权重也越来越小。

通过高斯分布公式计算出需要使用的高斯核(GaussKern),也就是计算出各个位置的所需的权重大小,使得不同位置的像素值影响度不同,距离中心点的越远的位置,权重越小,反之越近的权重越大。

int* Gauss::buildGaussKern(int winSize, int sigma)
{

int wincenter, x;
float sum = 0.0f;
//计算中心点大小
wincenter = winSize / 2;
//kern用来存储高斯模糊前的数据
//ikern用来存储高斯模糊后与像素值256的乘积值
float *kern = (float*)malloc(winSize*sizeof(float));
int *ikern = (int*)malloc(winSize*sizeof(int));
//计算高斯分布公式的系数
float SQRT_2PI = 2.506628274631f;
float sigmaMul2PI = 1.0f / (sigma * SQRT_2PI);
float divSigmaPow2 = 1.0f / (2.0f * sigma * sigma);

for (x = 0; x < wincenter + 1; x++)
{
    kern[wincenter - x] = kern[wincenter + x] = exp(-(x * x)* divSigmaPow2) * sigmaMul2PI;
    sum += kern[wincenter - x] + ((x != 0) ? kern[wincenter + x] : 0.0);
}
sum = 1.0f / sum;

for (x = 0; x < winSize; x++)
{
    kern[x] *= sum;
    ikern[x] = kern[x] * 256.0f;
}

free(kern);
return ikern;
}

理论上来讲,图像中每点的分布都不为零,这也就是说每个像素的计算都需要包含整幅图像。在实际应用中,在计算高斯函数的离散近似时,在大概3σ距离之外的像素都可以看作不起作用,这些像素的计算也就可以忽略。通常,图像处理程序只需要计算 (6 \sigma + 1) \times (6 \sigma + 1) 的矩阵就可以保证相关像素影响。对于边界上的点,通常采用复制周围的点到另一面再进行加权平均运算。

//忽略3sigma外的像素点
//计算(6*sigma+1)*(6*sigma+1)的矩阵
unsigned int  winsize = (1 + (((int)ceil(3 * sigma)) * 2));

除了圆形对称之外,高斯模糊也可以在二维图像上对两个独立的一维空间分别进行计算,这叫作线性可分。这也就是说,使用二维矩阵变换得到的效果也可以通过在水平方向进行一维高斯矩阵变换加上竖直方向的一维高斯矩阵变换得到。从计算的角度来看,这是一项有用的特性,因为这样只需要O(n * M * N) + O(m * M * N)次计算,而不可分的矩阵则需要O(m * n * M * N)次计算,其中M,N是需要进行滤波的图像的维数,m、n是滤波器的维数。

     for (unsigned int w = 0; w < width; w += channels)
    {
        //存储r g b分量的数据
        unsigned int rowR = 0;
        unsigned int rowG = 0;
        unsigned int rowB = 0;
        unsigned int alpha = 0;
        //将高斯系数赋值给gaussKernPtr
        int * gaussKernPtr = gaussKern;
        int whalfsize = w + width - halfsize;
        //当前位置
        unsigned int  curPos = rowWidth + w;
        for (unsigned int k = 1; k < winsize; k += channels)
        {
            unsigned int  pos = rowWidth + ((k + whalfsize) % width);
            int fkern = *gaussKernPtr++;
            //当前像素值乘以高斯系数,rowR G B这了泛指单通道的当前像素点高斯处理后的数
            rowR += (pixels[pos + MT_RED] * fkern);
            rowG += (pixels[pos + MT_GREEN] * fkern);
            rowB += (pixels[pos + MT_BLUE] * fkern);
            alpha += (pixels[pos + MT_ALPHA] * fkern);
        }
算法实现部分
void Gauss::GaussBlur(unsigned char *pixels, unsigned int width, unsigned int height, unsigned int channels, int sigma)
{
//四个通道。 存储每行数据的宽度
width = 4 * width;

if ((width % 4) != 0)
   width += (4 - (width % 4));
//窗的大小
//忽略3sigma外的像素点
//计算(6*sigma+1)*(6*sigma+1)的矩阵
unsigned int  winsize = (1 + (((int)ceil(3 * sigma)) * 2));
//构建高斯核,计算高斯系数
int *gaussKern = buildGaussKern(winsize, sigma);

winsize *= 3;
//窗的边到中心的距离
unsigned int  halfsize = winsize / 2;
//开辟新的内存存储处理高斯模糊后的数据
unsigned char *tmpBuffer = (unsigned char*)malloc(width * height* sizeof(unsigned char));
//外层循环,图像的高度
for (unsigned int h = 0; h < height; h++)
{
    //当前行的宽度为图像的高度乘以每行图像的数据所占的宽度。
    //因为是按行存储的数组
    unsigned int  rowWidth = h * width;

    for (unsigned int w = 0; w < width; w += channels)
    {
        //存储r g b alpha分量的数据
        unsigned int rowR = 0;
        unsigned int rowG = 0;
        unsigned int rowB = 0;
        unsigned int alpha = 0;
        //将高斯系数赋值给gaussKernPtr
        int * gaussKernPtr = gaussKern;
        int whalfsize = w + width - halfsize;
        //当前位置
        unsigned int  curPos = rowWidth + w;
        for (unsigned int k = 1; k < winsize; k += channels)
        {
            unsigned int  pos = rowWidth + ((k + whalfsize) % width);
            int fkern = *gaussKernPtr++;
            //当前像素值乘以高斯系数,rowR G B这了泛指单通道的当前像素点高斯处理后的数
            rowR += (pixels[pos + MT_RED] * fkern);
            rowG += (pixels[pos + MT_GREEN] * fkern);
            rowB += (pixels[pos + MT_BLUE] * fkern);
            alpha += (pixels[pos + MT_ALPHA] * fkern);
        }
        //除以256
        tmpBuffer[curPos + MT_RED] = ((unsigned char)(rowR >> 8));
        tmpBuffer[curPos + MT_GREEN] = ((unsigned char)(rowG >> 8));
        tmpBuffer[curPos + MT_BLUE] = ((unsigned char)(rowB >> 8));
        tmpBuffer[curPos + MT_ALPHA] = ((unsigned char)(alpha >> 8));
    }
}
winsize /= 3;
//窗的边到中心的距离
halfsize = winsize / 2;

for (unsigned int w = 0; w < width; w++)
{
    for (unsigned int h = 0; h < height; h++)
    {
        unsigned int col_all = 0;
        int hhalfsize = h + height - halfsize;
        for (unsigned int k = 0; k < winsize; k++)
        {
            col_all += tmpBuffer[((k + hhalfsize) % height)* width + w] * gaussKern[k];
        }
        pixels[h * width + w] = (unsigned char)(col_all >> 8);
    }
}
free(tmpBuffer);
free(gaussKern);
}

原文地址:https://www.cnblogs.com/ranjiewen/p/9332654.html

时间: 2024-10-17 16:28:09

高斯算法实现的相关文章

opencv 2.4.7 的混合高斯算法 BackgroundSubtractorMOG问题

视频处理是对于前景的提取,混合高斯算法的调用是在cv空间域名中但是在opencv2.4.7中提示直接调用发生错误: 提示cv中没有BackgroundSubtractorMOG这个成员: 我在网上查了一下分析说:2.4.7 使用时无法检测到主页中的例子.在只有我又将头文件加上,发现只要加上: #include <cvaux.h>就可以调用BackgroundSubtractorMOG这个成员: 附上代码: 1 #include<cv.h> 2 #include<highgui

Android 高斯算法在&quot;在路上&quot;APP 的实现

转载请标明出处:http://blog.csdn.net/yianemail/article/details/47019383 一:我们可以看到APP"在路上"上面的 高斯的模糊的处理的效果,在下拉的时候,图像就会变的清晰并且变大 松开的时候自动恢复模糊效果 . 效果分析. 我开始在想直接用高斯模糊处理图片,在图片不断的下拉的过程中也对图片的进行高斯处理达到实时对图片进行高斯模糊处                 理,达到 下拉到最下面的 图片变的clear,在拉动的过程中,图片的模糊

快速高斯滤波

高斯滤波器是图像处理中经常用到的滤波器,其滤波核函数为: 为简单起见,这里省略了归一化因子. 由的可分离特性: 得: 其中为输入图像,为输出图像,为滤波模板半径.根据准则,通常使. 由上式可见,我们可以将二维高斯滤波分解为两次一维高斯滤波. 对于二维高斯滤波,设图像大小,高斯模板大小,处理每个像素点需要次操作,则算法复杂度.若使用一维高斯核先对图像逐行滤波,再对中间结果逐列滤波,则处理每个像素需要次操作,算法复杂度,随着滤波模板尺寸的增大,算法优势越明显. 程序: #include "stdaf

数据结构和算法绪论笔记整理

程序设计 = 数据结构 + 算法 数据结构:就是数据元素相互之间存在的一种或多种特定关系的集合(关系就是讲逻辑结构,集合就是将物理结构); a.逻辑结构            集合:数据元素之间只有"同属于一个集合"的关系            线性结构:数据元素之间存在一个对一个的关系            树形结构:数据元素之间存在一个对多个关系            图形结构或网状结构:数据元素之间存在多个对多个的关系 b.物理结构(存储结构)            顺序存储:数

VC++高斯滤波\中值滤波实现图像模糊处理

一.算法 高斯模糊算法 详见:高斯模糊,基本思想就是利用高斯函数,将一个坐标点的所有邻域的加权平均值设置为这些点的颜色值. 中值滤波算法就更简单了:将一个坐标点的所有邻域的平均值设置为这些点的像素值. 二.算法的代码实现 高斯函数: 使用宏定义来替换: #define PI<span style="white-space:pre"> </span>3.1415926 //高斯模糊函数 #define GAUSS_FUN(x, y) (exp(-(x*x)/(do

图片高斯模糊效果

为实现一些玻璃蒙版的效果,需要用到高斯算法对图片进行模糊处理,基础算法代码如下 1 public static Bitmap fastblur(Context context, Bitmap sentBitmap, int radius) { 2 3 if (VERSION.SDK_INT > 20) { 4 Bitmap bitmap = sentBitmap.copy(sentBitmap.getConfig(), true); 5 6 final RenderScript rs = Ren

.net版高斯模糊算法

最近挺多人找高斯算法,本人贴上一个高斯模糊算法类,希望可以帮助到大家.算法的效率还是可以接受的. 1 #region 高斯模糊算法 2 /// <summary> 3 /// 高斯模糊算法 4 /// </summary> 5 using System ; 6 using System .Drawing ; 7 public class Gaussian 8 { 9 public static double[,] Calculate1DSampleKernel(double dev

数据结构和算法-学习笔记1

什么是数据结构? 数据结构是一门研究非数值计算的程序设计问题中的操作对象,以及它们之间的关系和操作等相关问题的学科. 程序设计=数据结构+算法(简单说就是关系,数据元素相互之间存在的一种或多种特定关系的集合) 数据结构分为逻辑结构和物理结构 逻辑结构(集合结构.线性结构.树形结构.图形结构) 数据对象中的数据元素之间的相互关系 集合机构 集合结构中的元素除了同属于一个集合外,他们之间没有其它关系 线性结构 线性结构中的数据元素之间是一对一的关系 树形结构 树形结构中的数据元素之间存在一种一对多的

Bilateral Filtering(双边滤波)算法研究

1. 简介 图像平滑是一个重要的操作,而且有多种成熟的算法.这里主要简单介绍一下Bilateral方法(双边滤波),这主要是由于前段时间做了SSAO,需要用bilateral blur 算法进行降噪.Bilateral blur相对于传统的高斯blur来说很重要的一个特性即可可以保持边缘(Edge Perseving),这个特点对于一些图像模糊来说很有用.一般的高斯模糊在进行采样时主要考虑了像素间的空间距离关系,但是却并没有考虑像素值之间的相似程度,因此这样我们得到的模糊结果通常是整张图片一团模