Introduction to gaussian filter 高斯滤波器


Introduction to gaussian filter 


                        我尝试尽可能低门槛的介绍这些好玩的东东~这里只须要正态分布函数作为基础就可以開始玩图像的高斯滤波了. Don't panic !



                  



          在通常的图像中,像素点都非常多,非常多情况都是非常多一大块像素点记录某一个场景区域。那么这就数字离散环境下模拟出了实际生活中颜色变化连续性的事实(注意。计算机的离散环境都是对真实的模拟.)


          高斯滤波是怎么回事捏?一句话的事情。就是利用高斯函数取权值,在一个区域内进行加权平均!


简单的事情永远别搞复杂了。project师的定义是什么。就是把复杂问题简单化的人. 越简单越好. 世界上本没有非常困难的问题,仅仅是阐述的人说的不够直白而已.


公式就在这里。怎么做?以下通过程序实现来“体会”并领悟高斯滤波. 不信我扯不清楚

         

         x y 代表距离中心点的距离

         这里先给出最简单的单通道黑白图像处理的函数(足够短小。可以说明算法就可以,后面会给出彩色图像的实现函数,为了把程序算法便于理解。我尽量不调用matlab的API,使用C语言的风格编写demo程序).


以下的程序没有经过不论什么优化

(操心优化之后程序便于和原来算法对比理解...所以当用户把kernel窗体调的比較大的时候(Kernel_size > 11的时候),程序会比較慢)

%***********************************************************
% code writer   : EOF
% code file     :  gaussian_filter_for_dark_Image.m
% code date     : 2014.10.25
% e-mail        : jasonleaster@gmail.com
%
% Code Description:
%
%        Here is my implementation of gaussian filter which
% is only work for single channel image.
%
%       If you find something wrong with my code ,please touch
% me by e-mail.
%**************************************************************

function Output = gaussian_filter_for_dark_Image(Image,Kernel_size,epsilon)

    if size(Image,3) ~= 1
        fprintf('Hey guys, please input a single channel image.\n');
    end

    
    Location_X = zeros(Kernel_size,Kernel_size);
    Location_Y = zeros(Kernel_size,Kernel_size);
    
    %% Initialization for original Location.
    for row = 1 : Kernel_size
        for col = 1 : Kernel_size
            Location_X(row ,col) = (col -1) - floor(Kernel_size/2);
            Location_Y(row ,col) = (row -1) - floor(Kernel_size/2);
        end
    end
    
    Kernel = zeros(Kernel_size,Kernel_size);
    
    for row = 1 : Kernel_size
        for col = 1 : Kernel_size
            
            % Oh , Attention. Here we are gonna to compute the Kernel of
            % our filter.
            Kernel(row,col) = (1/(2*pi*(epsilon.^2))) * ...
            exp( - (Location_X(row,col).^2 + Location_Y(row,col).^2)./(2* (epsilon.^2) ));
            
        end
    end

    sum_of_Kernel = sum(Kernel(:));
    
    Image_Height = size(Image,1);
    Image_Width  = size(Image,2);
    
    Output = zeros(Image_Height,Image_Width);
    
    for row = 1: Image_Height
        for col = 1: Image_Width
            
            sum_value = 0;
            
            % Set the patch start location and end location.
            Kernel_row_start = row - floor(Kernel_size/2);
            Kernel_col_start = col - floor(Kernel_size/2);
            Kernel_row_end   = row + floor(Kernel_size/2);
            Kernel_col_end   = col + floor(Kernel_size/2);
            
            for Kernel_row = Kernel_row_start : Kernel_row_end
                for Kernel_col = Kernel_col_start : Kernel_col_end
                    
                    %% Sum all weighted neighboring pixel by gaussian distribution.
                   
                    if Kernel_row > 0 && Kernel_col > 0 && ...
                       Kernel_row <= Image_Height && Kernel_col <= Image_Width
                       
                       sum_value = sum_value + ...
                       Kernel(Kernel_row - Kernel_row_start  + 1,...
                              Kernel_col - Kernel_col_start  + 1) *...
                       Image(Kernel_row,Kernel_col);
                    end
                end
            end
            
            Output(row,col) = sum_value/sum_of_Kernel;
            
        end
    end
    
end



測试: 

參数:Kernel_size = 11, epsilon = 2.5

左图为输入图像。右边是得到的滤波结果.

假设你细致分析过Kernel_size得到的高斯权重的话就会发现。事实上Kernel_size过大是没有什么实际意义的.影响不大,一般7 和11得到的结果都非常接近。真正影响模糊效果的是epsilon, 这里epsilon取值为2.5,假设你取值小一点。图像的模糊程度就会弱(即。清晰)



既然完毕了单通道图像的高斯滤波。彩色图片的高斯滤波就变得顺理成章了,非常easy.

这里我整合了单通道和三通道的图片高斯滤波,写成一个函数(嘿嘿。I love robust)



为嘛三通道的就这么久捏....感觉跑好久...以后还是要优化一下

以下是用Kernel_win_size = 3, epsilon = 1.5的输出效果

左边是原图,右边是滤波后的结果.




%***********************************************************
% code writer   : EOF
% code file     :  gaussian_filter_for_Image.m
% code date     : 2014.10.25
% e-mail        : jasonleaster@gmail.com
%
% Code Description:
%
%        Here is my implementation of gaussian filter .
% 
%        Parameter @Image is the inputed image, @Kernel_size 
% describe the size of filter kernel and @epsilon is the 
% parameter in normal-distribution which you are familiar with.
%
%       If you find something wrong with my code ,please touch
% me by e-mail.
%**************************************************************

function Output = gaussian_filter_for_Image(Image,Kernel_size,epsilon)

    if size(Image,3) ~= 1 && size(Image,3) ~= 3
        fprintf('Hey guys, please input a single or three channel image.\n');
    end    
        
        Location_X = zeros(Kernel_size,Kernel_size);
        Location_Y = zeros(Kernel_size,Kernel_size);

        %% Initialization for original Location.
        for row = 1 : Kernel_size
            for col = 1 : Kernel_size
                Location_X(row ,col) = (col -1) - floor(Kernel_size/2);
                Location_Y(row ,col) = (row -1) - floor(Kernel_size/2);
            end
        end

        Kernel = zeros(Kernel_size,Kernel_size);

        for row = 1 : Kernel_size
            for col = 1 : Kernel_size

                % Oh , Attention. Here we are gonna to compute the Kernel of
                % our filter.
                Kernel(row,col) = (1/((2*pi*(epsilon.^2)))) * ...
                exp( - (Location_X(row,col).^2 + Location_Y(row,col).^2)./(2* (epsilon.^2) ));

            end
        end

        sum_of_Kernel = sum(Kernel(:));
        
        Image_Height = size(Image,1);
        Image_Width  = size(Image,2);

        if size(Image,3) == 1
            Output = zeros(Image_Height,Image_Width);
        else
            Output = zeros(Image_Height,Image_Width,3);
        end
        
        for row = 1: Image_Height
            for col = 1: Image_Width

                
                % Set the patch start location and end location.
                Kernel_row_start = row - floor(Kernel_size/2);
                Kernel_col_start = col - floor(Kernel_size/2);
                Kernel_row_end   = row + floor(Kernel_size/2);
                Kernel_col_end   = col + floor(Kernel_size/2);

                

                for channel = 1: size(Image,3)
                    
                    sum_value = 0;
                    for Kernel_row = Kernel_row_start : Kernel_row_end
                        for Kernel_col = Kernel_col_start : Kernel_col_end
                            %% Sum all weighted neighboring pixel by gaussian distribution.

                            if Kernel_row > 0 && Kernel_col > 0 && ...
                               Kernel_row <= Image_Height && Kernel_col <= Image_Width

                               sum_value = sum_value + ...
                               Kernel(Kernel_row - Kernel_row_start  + 1,...
                                      Kernel_col - Kernel_col_start  + 1) *...
                               Image(Kernel_row,Kernel_col,channel);
                            end

                        end
                    end

                    %%
                    % Never forget to divide 'sum_of_kernel', otherwise your outputed image
                    % would looks like more dark than original image.
                    Output(row,col,channel) = sum_value/sum_of_Kernel;
                end
            end
        end

    
end


解惑:

         之前你可能遇到过以下这种“高斯滤波核”


事实上,这就是别人已经算好的分布数据,然后直接用了。

而我们这里採用的是高度可定制的窗体大小Kernel_size。

本质是一样的

Don't panic :)



版权声明:本文博客原创文章。博客,未经同意,不得转载。

posted @ 2015-07-25 18:39  mengfanrong  阅读(919)  评论(0编辑  收藏  举报