高斯模糊实现小结.docx

上传人:b****2 文档编号:3254557 上传时间:2023-05-05 格式:DOCX 页数:19 大小:441.49KB
下载 相关 举报
高斯模糊实现小结.docx_第1页
第1页 / 共19页
高斯模糊实现小结.docx_第2页
第2页 / 共19页
高斯模糊实现小结.docx_第3页
第3页 / 共19页
高斯模糊实现小结.docx_第4页
第4页 / 共19页
高斯模糊实现小结.docx_第5页
第5页 / 共19页
高斯模糊实现小结.docx_第6页
第6页 / 共19页
高斯模糊实现小结.docx_第7页
第7页 / 共19页
高斯模糊实现小结.docx_第8页
第8页 / 共19页
高斯模糊实现小结.docx_第9页
第9页 / 共19页
高斯模糊实现小结.docx_第10页
第10页 / 共19页
高斯模糊实现小结.docx_第11页
第11页 / 共19页
高斯模糊实现小结.docx_第12页
第12页 / 共19页
高斯模糊实现小结.docx_第13页
第13页 / 共19页
高斯模糊实现小结.docx_第14页
第14页 / 共19页
高斯模糊实现小结.docx_第15页
第15页 / 共19页
高斯模糊实现小结.docx_第16页
第16页 / 共19页
高斯模糊实现小结.docx_第17页
第17页 / 共19页
高斯模糊实现小结.docx_第18页
第18页 / 共19页
高斯模糊实现小结.docx_第19页
第19页 / 共19页
亲,该文档总共19页,全部预览完了,如果喜欢就下载吧!
下载资源
资源描述

高斯模糊实现小结.docx

《高斯模糊实现小结.docx》由会员分享,可在线阅读,更多相关《高斯模糊实现小结.docx(19页珍藏版)》请在冰点文库上搜索。

高斯模糊实现小结.docx

高斯模糊实现小结

高斯模糊实现小结

高斯模糊是一种图像滤波器,它使用正态分布(高斯函数)计算模糊模板,并使用该模板与原图像做卷积运算,达到模糊图像的目的。

N维空间正态分布方程为:

其中,σ是正态分布的标准差,σ值越大,图像越模糊(平滑)。

r为模糊半径,模糊半径是指模板元素到模板中心的距离。

如二维模板大小为m*n,则模板上的元素(x,y)对应的高斯计算公式为:

在二维空间中,这个公式生成的曲面的等高线是从中心开始呈正态分布的同心圆。

分布不为零的像素组成的卷积矩阵与原始图像做变换。

每个像素的值都是周围相邻像素值的加权平均。

原始像素的值有最大的高斯分布值,所以有最大的权重,相邻像素随着距离原始像素越来越远,其权重也越来越小。

这样进行模糊处理比其它的均衡模糊滤波器更高地保留了边缘效果。

理论上来讲,图像中每点的分布都不为零,这也就是说每个像素的计算都需要包含整幅图像。

在实际应用中,在计算高斯函数的离散近似时,在大概3σ距离之外的像素都可以看作不起作用,这些像素的计算也就可以忽略。

通常,图像处理程序只需要计算(6σ+1)*(6σ+1)的矩阵就可以保证相关像素影响。

1、使用给定高斯模板平滑图像函数

σ=0.84089642的7行7列高斯模糊矩阵为:

现使用该模板对源图像做模糊处理,其函数如下:

[cpp] view

plaincopy

1.//高斯平滑  

2.//未使用sigma,边缘无处理  

3.void GaussianTemplateSmooth(const Mat &src, Mat &dst, double sigma)  

4.{  

5.    //高斯模板(7*7),sigma = 0.84089642,归一化后得到  

6.    static const double gaussianTemplate[7][7] =   

7.    {  

8.        {0.00000067, 0.00002292, 0.00019117, 0.00038771, 0.00019117, 0.00002292, 0.00000067},  

9.        {0.00002292, 0.00078633, 0.00655965, 0.01330373, 0.00655965, 0.00078633, 0.00002292},  

10.        {0.00019117, 0.00655965, 0.05472157, 0.11098164, 0.05472157, 0.00655965, 0.00019117},  

11.        {0.00038771, 0.01330373, 0.11098164, 0.22508352, 0.11098164, 0.01330373, 0.00038771},  

12.        {0.00019117, 0.00655965, 0.05472157, 0.11098164, 0.05472157, 0.00655965, 0.00019117},  

13.        {0.00002292, 0.00078633, 0.00655965, 0.01330373, 0.00655965, 0.00078633, 0.00002292},  

14.        {0.00000067, 0.00002292, 0.00019117, 0.00038771, 0.00019117, 0.00002292, 0.00000067}  

15.    };  

16.  

17.    dst.create(src.size(), src.type());  

18.    uchar* srcData = src.data;  

19.    uchar* dstData = dst.data;  

20.  

21.    for(int j = 0; j < src.cols-7; j++)  

22.    {  

23.        for(int i = 0; i < src.rows-7; i++)  

24.        {  

25.            double acc = 0;  

26.            double accb = 0, accg = 0, accr = 0;   

27.            for(int m = 0; m < 7; m++)  

28.            {  

29.                for(int n = 0; n < 7; n++)  

30.                {  

31.                    if(src.channels() == 1)  

32.                        acc += *(srcData + src.step * (i+n) + src.channels() * (j+m)) * gaussianTemplate[m][n];  

33.                    else  

34.                    {  

35.                        accb += *(srcData + src.step * (i+n) + src.channels() * (j+m) + 0) * gaussianTemplate[m][n];  

36.                        accg += *(srcData + src.step * (i+n) + src.channels() * (j+m) + 1) * gaussianTemplate[m][n];  

37.                        accr += *(srcData + src.step * (i+n) + src.channels() * (j+m) + 2) * gaussianTemplate[m][n];  

38.                    }  

39.                }  

40.            }  

41.            if(src.channels() == 1)  

42.                *(dstData + dst.step * (i+3) + dst.channels() * (j+3))=(int)acc;  

43.            else  

44.            {  

45.                *(dstData + dst.step * (i+3) + dst.channels() * (j+3) + 0)=(int)accb;  

46.                *(dstData + dst.step * (i+3) + dst.channels() * (j+3) + 1)=(int)accg;  

47.                *(dstData + dst.step * (i+3) + dst.channels() * (j+3) + 2)=(int)accr;  

48.            }  

49.        }  

50.    }  

51.      

52.}  

其效果如图1所示,7*7的高斯模板与源图像做卷积运算时,会产生半径为3的边缘,在不精确的图像处理中,可用源图像像素填充,或者去掉边缘。

2、二维高斯模糊函数

上述的例子中,如何求得高斯模糊矩阵是高斯模糊的关键。

根据高斯函数的性质,图像处理程序只需要计算(6σ+1)*(6σ+1)的矩阵就可以保证相关像素影响。

因此,可根据σ的值确定高斯模糊矩阵的大小。

高斯矩阵可利用公式(1-2)计算,并归一化得到。

归一化是保证高斯矩阵的值在[0,1]之间,

其处理函数如下:

 

[cpp] view

plaincopy

1.void GaussianSmooth2D(const Mat &src, Mat &dst, double sigma)  

2.{  

3.    if(src.channels() !

= 1)  

4.        return;  

5.  

6.    //确保sigma为正数   

7.    sigma = sigma > 0 ?

 sigma :

 0;  

8.    //高斯核矩阵的大小为(6*sigma+1)*(6*sigma+1)  

9.    //ksize为奇数  

10.    int ksize = cvRound(sigma * 3) * 2 + 1;  

11.      

12.//  dst.create(src.size(), src.type());  

13.    if(ksize == 1)  

14.    {  

15.        src.copyTo(dst);      

16.        return;  

17.    }  

18.  

19.    dst.create(src.size(), src.type());  

20.  

21.    //计算高斯核矩阵  

22.    double *kernel = new double[ksize*ksize];  

23.  

24.    double scale = -0.5/(sigma*sigma);  

25.    const double PI = 3.141592653;  

26.    double cons = -scale/PI;  

27.  

28.    double sum = 0;  

29.  

30.    for(int i = 0; i < ksize; i++)  

31.    {  

32.        for(int j = 0; j < ksize; j++)  

33.        {  

34.            int x = i-(ksize-1)/2;  

35.            int y = j-(ksize-1)/2;  

36.            kernel[i*ksize + j] = cons * exp(scale * (x*x + y*y));  

37.  

38.            sum += kernel[i*ksize+j];  

39.//          cout << " " << kernel[i*ksize + j];  

40.        }  

41.//      cout <

42.    }  

43.    //归一化  

44.    for(int i = ksize*ksize-1; i >=0; i--)  

45.    {  

46.        *(kernel+i) /= sum;  

47.    }  

48.    //图像卷积运算,无边缘处理  

49.    for(int j = 0; j < src.cols-ksize; j++)  

50.    {  

51.        for(int i = 0; i < src.rows-ksize; i++)  

52.        {  

53.            double acc = 0;  

54.  

55.            for(int m = 0; m < ksize; m++)  

56.            {  

57.                for(int n = 0; n < ksize; n++)  

58.                {  

59.                    acc += *(srcData + src.step * (i+n) + src.channels() * (j+m)) * kernel[m*ksize+n];   

60.                }  

61.            }  

62.  

63.          

64.            *(dstData + dst.step * (i + (ksize - 1)/2) + (j + (ksize -1)/2)) = (int)acc;  

65.        }  

66.    }  

67.    delete []kernel;  

68.}  

利用该函数,取σ=0.84089642即可得到上例中7*7的模板,该模板数据存在kernel中。

利用该函数计算的归一化后的3*3,5*5阶高斯模板如表2,3所示:

由上表可以看出,高斯模板是中心对称的。

模糊效果如图2所示。

 

对图2中边缘的处理:

[cpp] view

plaincopy

1....  

[cpp] view

plaincopy

1.int center = (ksize-1) /2;  

2.//图像卷积运算,处理边缘  

3.for(int j = 0; j < src.cols; j++)  

4.{  

5.    for(int i = 0; i < src.rows; i++)  

6.    {  

7.        double acc = 0;  

8.  

9.        for(int m = -center, c = 0; m <= center; m++, c++)  

10.        {  

11.            for(int n = -center, r = 0; n <= center; n++, r++)  

12.            {  

13.                if((i+n) >=0 && (i+n) < src.rows && (j+m) >=0 && (j+m) < src.cols)  

14.                {  

15.                      

16.                    acc += *(srcData + src.step * (i+n) + src.channels() * (j+m)) * kernel[r*ksize+c];   

17.              

18.                }  

19.            }  

20.        }  

21.  

22.  

23.        *(dstData + dst.step * (i) + (j)) = (int)acc;  

24.    }  

25.}  

[cpp] view

plaincopy

1....  

结果图为:

如上图所示,边缘明显变窄,但是存在黑边。

3、改进的高斯模糊函数

上述的二维高斯模糊函数GaussianSmooth2D达到了高斯模糊图像的目的,但是如图2所示,会因模板的关系而造成边缘图像缺失,σ越大,缺失像素越多,额外的边缘处理会增加计算量。

并且当σ变大时,高斯模板(高斯核)和卷积运算量将大幅度提高。

根据高斯函数的可分离性,可对二维高斯模糊函数进行改进。

高斯函数的可分离性是指使用二维矩阵变换得到的效果也可以通过在水平方向进行一维高斯矩阵变换加上竖直方向的一维高斯矩阵变换得到。

从计算的角度来看,这是一项有用的特性,因为这样只需要O(n*M*n)+O(m*M*N)次计算,而二维不可分的矩阵则需要O(m*n*M*n)次计算,其中,m,n为高斯矩阵的维数,M,N为二维图像的维数。

另外,两次一维的高斯卷积将消除二维高斯矩阵所产生的边缘。

改进的高斯模糊函数如下:

[cpp] view

plaincopy

1.void GaussianSmooth(const Mat &src, Mat &dst, double sigma)  

2.{  

3.    if(src.channels() !

= 1 && src.channels() !

= 3)  

4.        return;  

5.  

6.    //  

7.    sigma = sigma > 0 ?

 sigma :

 -sigma;  

8.    //高斯核矩阵的大小为(6*sigma+1)*(6*sigma+1)  

9.    //ksize为奇数  

10.    int ksize = ceil(sigma * 3) * 2 + 1;  

11.  

12.    //cout << "ksize=" <

13.    //  dst.create(src.size(), src.type());  

14.    if(ksize == 1)  

15.    {  

16.        src.copyTo(dst);      

17.        return;  

18.    }  

19.  

20.    //计算一维高斯核  

21.    double *kernel = new double[ksize];  

22.  

23.    double scale = -0.5/(sigma*sigma);  

24.    const double PI = 3.141592653;  

25.    double cons = 1/sqrt(-scale / PI);  

26.  

27.    double sum = 0;  

28.    int kcenter = ksize/2;  

29.    int i = 0, j = 0;  

30.    for(i = 0; i < ksize; i++)  

31.    {  

32.        int x = i - kcenter;  

33.        *(kernel+i) = cons * exp(x * x * scale);//一维高斯函数  

34.        sum += *(kernel+i);  

35.  

36.//      cout << " " << *(kernel+i);  

37.    }  

38.//  cout << endl;  

39.    //归一化,确保高斯权值在[0,1]之间  

40.    for(i = 0; i < ksize; i++)  

41.    {  

42.        *(kernel+i) /= sum;  

43.//      cout << " " << *(kernel+i);  

44.    }  

45.//  cout << endl;  

46.  

47.    dst.create(src.size(), src.type());  

48.    Mat temp;  

49.    temp.create(src.size(), src.type());  

50.  

51.    uchar* srcData = src.data;  

52.    uchar* dstData = dst.data;  

53.    uchar* tempData = temp.data;  

54.  

55.    //x方向一维高斯模糊  

56.    for(int y = 0; y < src.rows; y++)  

57.    {  

58.        for(int x = 0; x < src.cols; x++)  

59.        {  

60.            double mul = 0;  

61.            sum = 0;  

62.            double bmul = 0, gmul = 0, rmul = 0;  

63.            for(i = -kcenter; i <= kcenter; i++)  

64.            {  

65.                if((x+i) >= 0 && (x+i) < src.cols)  

66.                {  

67.                    if(src.channels() == 1)  

68.                    {  

69.                        mul += *(srcData+y*src.step+(x+i))*(*(kernel+kcenter+i));  

70.                    }  

71.                    else   

72.                    {  

73.                        bmul += *(srcData+y*src.step+(x+i)*src.channels() + 0)*(*(kernel+kcenter+i));  

74.                        gmul += *(srcData+y*src.step+(x+i)*src.channels() + 1)*(*(kernel+kcenter+i));  

75.                        rmul += *(srcData+y*src.step+(x+i)*src.channels() + 2)*(*(kernel+kcenter+i));  

76.                    }  

77.                    sum += (*(kernel+kcenter+i));  

78.                }  

79.            }  

80.            if(src.channels() == 1)  

81.            {  

82.                *(tempData+y*temp.step+x) = mul/sum;  

83.            }  

84.            else  

85.            {  

86.                *(tempData+y*te

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 解决方案 > 学习计划

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2