• 数字图像处理(二):图像去雾


    1.主程序

    clear all;clc
    close all
    
    kenlRatio = .01;%窗口大小比例
    minAtomsLight = 240;
    %原始论文中的A最终是取原始像素中的某一个点的像素,我实际上是取的符合条件的所有点的平均值作为A的值。
    %如果是取一个点,则各通道的A值很有可能全部很接近255,这样的话会造成处理后的图像偏色和出现大量色斑。
    %原文作者说这个算法对天空部分不需特别处理,我实际发现该算法对有天空的图像的效果一般都不好。天空会出现明显的过渡区域。
    %作为解决方案,我增加了一个参数,最大全球大气光值minAtomsLight,当计算的值大于该值时,则就取该值。
    image_name = 'defog.jpg';%图像名
    img=imread(image_name);%读取图像
    figure,imshow(uint(img)), title('原始图像');%显示原始图像
    
    sz=size(img);%读取图像大小
    
    w=sz(2);%图像宽度
    
    h=sz(1);%图像高度
    
    dc = zeros(h,w);%生成一个与原图像大小相同的零矩阵
    
    for y=1:h
    
        for x=1:w
    
            dc(y,x) = min(img(y,x,:));%计算每个像素点RGB中最小的值
    
        end
    
    end
    
    
    figure,imshow(uint8(dc)), title('Min(R,G,B)');%显示RGB取最小值后的图像
    
    krnlsz = floor(max([3, w*kenlRatio, h*kenlRatio]));%计算窗口大小
    
    dc2 = minfilt2(dc, [krnlsz,krnlsz]);%最小值滤波
    
    dc2(h,w)=0;
    
    figure,imshow(uint8(dc2)), title('After Minfilter ');%显示最小值滤波后的图像
    
    t = 255 - dc2;%计算透射率
    
    figure,imshow(uint8(t)),title('t');
    
    t_d=double(t)/255;%归一化
    
    sum(sum(t_d))/(h*w)
    
    
    A = min([minAtomsLight, max(max(dc2))])%计算全球大气光的值
    
    J = zeros(h,w,3);%生成一个与原图像大小相同的三维矩阵
    
    img_d = double(img);%将整型转化为浮点型
    
    J(:,:,1) = (img_d(:,:,1) - (1-t_d)*A)./t_d;%计算去雾后的R通道
    
    J(:,:,2) = (img_d(:,:,2) - (1-t_d)*A)./t_d;%计算去雾后的G通道
    
    J(:,:,3) = (img_d(:,:,3) - (1-t_d)*A)./t_d;%计算去雾后的B通道
    
    figure,imshow(uint8(J)), title('J');%去雾后的图像
    % figure,imshow(rgb2gray(uint8(abs(J-img_d)))), title('J-img_d');
    % a = sum(sum(rgb2gray(uint8(abs(J-img_d))))) / (h*w)
    % return;
    %----------------------------------
    r = krnlsz*4;%滤波半径
    eps = 10^-6;%调整参数
    
    % filtered = guidedfilter_color(double(img)/255, t_d, r, eps);
    filtered = guidedfilter(double(rgb2gray(img))/255, t_d, r, eps);%计算导向滤波图(灰度)求得精确的透射率
    
    t_d = filtered;%将原来的透射率修改为新的透射率
    
    figure,imshow(t_d,[]),title('filtered t');
    
    J(:,:,1) = (img_d(:,:,1) - (1-t_d)*A)./t_d;%计算去雾后的R通道
    
    J(:,:,2) = (img_d(:,:,2) - (1-t_d)*A)./t_d;%计算去雾后的G通道
    
    J(:,:,3) = (img_d(:,:,3) - (1-t_d)*A)./t_d;%计算去雾后的B通道
    % 
    
    img_d(1,3,1)
    figure,imshow(uint8(J)), title('J_guild_filter');%显示图像
    
    %----------------------------------
    %imwrite(uint8(J), ['_', image_name])

    2.vanherk

    function Y = vanherk(X,N,TYPE,varargin)
    %  VANHERK    Fast max/min 1D filter
    %
    %    Y = VANHERK(X,N,TYPE) performs the 1D max/min filtering of the row
    %    vector X using a N-length filter.
    %    The filtering type is defined by TYPE = 'max' or 'min'. This function
    %    uses the van Herk algorithm for min/max filters that demands only 3
    %    min/max calculations per element, independently of the filter size.
    %
    %    If X is a 2D matrix, each row will be filtered separately.
    %    
    %    Y = VANHERK(...,'col') performs the filtering on the columns of X.
    %    
    %    Y = VANHERK(...,'shape') returns the subset of the filtering specified
    %    by 'shape' :
    %        'full'  - Returns the full filtering result,
    %        'same'  - (default) Returns the central filter area that is the
    %                   same size as X,
    %        'valid' - Returns only the area where no filter elements are outside
    %                  the image.
    %
    %    X can be uint8 or double. If X is uint8 the processing is quite faster, so
    %    dont't use X as double, unless it is really necessary.
    %
    
    % Initialization
    [direc, shape] = parse_inputs(varargin{:});
    if strcmp(direc,'col')
       X = X';
    end
    if strcmp(TYPE,'max')
       maxfilt = 1;
    elseif strcmp(TYPE,'min')
       maxfilt = 0;
    else
       error([ 'TYPE must be ' char(39) 'max' char(39) ' or ' char(39) 'min' char(39) '.'])
    end
    
    % Correcting X size
    fixsize = 0;
    addel = 0;
    if mod(size(X,2),N) ~= 0
       fixsize = 1;
       addel = N-mod(size(X,2),N);
       if maxfilt
          f = [ X zeros(size(X,1), addel) ];
       else
          f = [X repmat(X(:,end),1,addel)];
       end
    else
       f = X;
    end
    lf = size(f,2);
    lx = size(X,2);
    clear X
    
    % Declaring aux. mat.
    g = f;
    h = g;
    
    % Filling g & h (aux. mat.)
    ig = 1:N:size(f,2);
    ih = ig + N - 1;
    
    g(:,ig) = f(:,ig);
    h(:,ih) = f(:,ih);
    
    if maxfilt
       for i = 2 : N
          igold = ig;
          ihold = ih;
          
          ig = ig + 1;
          ih = ih - 1;
          
          g(:,ig) = max(f(:,ig),g(:,igold));
          h(:,ih) = max(f(:,ih),h(:,ihold));
       end
    else
       for i = 2 : N
          igold = ig;
          ihold = ih;
          
          ig = ig + 1;
          ih = ih - 1;
          
          g(:,ig) = min(f(:,ig),g(:,igold));
          h(:,ih) = min(f(:,ih),h(:,ihold));
       end
    end
    clear f
    
    % Comparing g & h
    if strcmp(shape,'full')
       ig = [ N : 1 : lf ];
       ih = [ 1 : 1 : lf-N+1 ];
       if fixsize
          if maxfilt
             Y = [ g(:,1:N-1)  max(g(:,ig), h(:,ih))  h(:,end-N+2:end-addel) ];
          else
             Y = [ g(:,1:N-1)  min(g(:,ig), h(:,ih))  h(:,end-N+2:end-addel) ];
          end
       else
          if maxfilt
             Y = [ g(:,1:N-1)  max(g(:,ig), h(:,ih))  h(:,end-N+2:end) ];
          else
             Y = [ g(:,1:N-1)  min(g(:,ig), h(:,ih))  h(:,end-N+2:end) ];
          end
       end
       
    elseif strcmp(shape,'same')
       if fixsize
          if addel > (N-1)/2
             disp('hoi')
             ig = [ N : 1 : lf - addel + floor((N-1)/2) ];
             ih = [ 1 : 1 : lf-N+1 - addel + floor((N-1)/2)];
             if maxfilt
                Y = [ g(:,1+ceil((N-1)/2):N-1)  max(g(:,ig), h(:,ih)) ];
             else
                Y = [ g(:,1+ceil((N-1)/2):N-1)  min(g(:,ig), h(:,ih)) ];
             end
          else   
             ig = [ N : 1 : lf ];
             ih = [ 1 : 1 : lf-N+1 ];
             if maxfilt
                Y = [ g(:,1+ceil((N-1)/2):N-1)  max(g(:,ig), h(:,ih))  h(:,lf-N+2:lf-N+1+floor((N-1)/2)-addel) ];
             else
                Y = [ g(:,1+ceil((N-1)/2):N-1)  min(g(:,ig), h(:,ih))  h(:,lf-N+2:lf-N+1+floor((N-1)/2)-addel) ];
             end
          end            
       else % not fixsize (addel=0, lf=lx) 
          ig = [ N : 1 : lx ];
          ih = [ 1 : 1 : lx-N+1 ];
          if maxfilt
             Y = [  g(:,N-ceil((N-1)/2):N-1) max( g(:,ig), h(:,ih) )  h(:,lx-N+2:lx-N+1+floor((N-1)/2)) ];
          else
             Y = [  g(:,N-ceil((N-1)/2):N-1) min( g(:,ig), h(:,ih) )  h(:,lx-N+2:lx-N+1+floor((N-1)/2)) ];
          end
       end      
       
    elseif strcmp(shape,'valid')
       ig = [ N : 1 : lx];
       ih = [ 1 : 1: lx-N+1];
       if maxfilt
          Y = [ max( g(:,ig), h(:,ih) ) ];
       else
          Y = [ min( g(:,ig), h(:,ih) ) ];
       end
    end
    
    if strcmp(direc,'col')
       Y = Y';
    end
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function [direc, shape] = parse_inputs(varargin)
    direc = 'lin';
    shape = 'same';
    flag = [0 0]; % [dir shape]
    
    for i = 1 : nargin
       t = varargin{i};
       if strcmp(t,'col') & flag(1) == 0
          direc = 'col';
          flag(1) = 1;
       elseif strcmp(t,'full') & flag(2) == 0
          shape = 'full';
          flag(2) = 1;
       elseif strcmp(t,'same') & flag(2) == 0
          shape = 'same';
          flag(2) = 1;
       elseif strcmp(t,'valid') & flag(2) == 0
          shape = 'valid';
          flag(2) = 1;
       else
          error(['Too many / Unkown parameter : ' t ])
       end
    end

    3.导向滤波

    function q = guidedfilter(I, p, r, eps)
    %   GUIDEDFILTER   O(1) time implementation of guided filter.
    %
    %   - guidance image: I (should be a gray-scale/single channel image)
    %   - filtering input image: p (should be a gray-scale/single channel image)
    %   - local window radius: r
    %   - regularization parameter: eps
    
    [hei, wid] = size(I);
    N = boxfilter(ones(hei, wid), r); % the size of each local patch; N=(2r+1)^2 except for boundary pixels.
    
    % imwrite(uint8(N), 'N.jpg');
    % figure,imshow(N,[]),title('N');
    
    
    mean_I = boxfilter(I, r) ./ N;
    mean_p = boxfilter(p, r) ./ N;
    mean_Ip = boxfilter(I.*p, r) ./ N;
    cov_Ip = mean_Ip - mean_I .* mean_p; % this is the covariance of (I, p) in each local patch.
    
    mean_II = boxfilter(I.*I, r) ./ N;
    var_I = mean_II - mean_I .* mean_I;
    
    a = cov_Ip ./ (var_I + eps); % Eqn. (5) in the paper;
    b = mean_p - a .* mean_I; % Eqn. (6) in the paper;
    
    mean_a = boxfilter(a, r) ./ N;
    mean_b = boxfilter(b, r) ./ N;
    
    q = mean_a .* I + mean_b; % Eqn. (8) in the paper;
    end
    function q = guidedfilter_color(I, p, r, eps)
    %   GUIDEDFILTER_COLOR   O(1) time implementation of guided filter using a color image as the guidance.
    %
    %   - guidance image: I (should be a color (RGB) image)
    %   - filtering input image: p (should be a gray-scale/single channel image)
    %   - local window radius: r
    %   - regularization parameter: eps
    
    [hei, wid] = size(p);
    N = boxfilter(ones(hei, wid), r); % the size of each local patch; N=(2r+1)^2 except for boundary pixels.
    
    mean_I_r = boxfilter(I(:, :, 1), r) ./ N;
    mean_I_g = boxfilter(I(:, :, 2), r) ./ N;
    mean_I_b = boxfilter(I(:, :, 3), r) ./ N;
    
    mean_p = boxfilter(p, r) ./ N;
    
    mean_Ip_r = boxfilter(I(:, :, 1).*p, r) ./ N;
    mean_Ip_g = boxfilter(I(:, :, 2).*p, r) ./ N;
    mean_Ip_b = boxfilter(I(:, :, 3).*p, r) ./ N;
    
    % covariance of (I, p) in each local patch.
    cov_Ip_r = mean_Ip_r - mean_I_r .* mean_p;
    cov_Ip_g = mean_Ip_g - mean_I_g .* mean_p;
    cov_Ip_b = mean_Ip_b - mean_I_b .* mean_p;
    
    % variance of I in each local patch: the matrix Sigma in Eqn (14).
    % Note the variance in each local patch is a 3x3 symmetric matrix:
    %           rr, rg, rb
    %   Sigma = rg, gg, gb
    %           rb, gb, bb
    var_I_rr = boxfilter(I(:, :, 1).*I(:, :, 1), r) ./ N - mean_I_r .*  mean_I_r; 
    var_I_rg = boxfilter(I(:, :, 1).*I(:, :, 2), r) ./ N - mean_I_r .*  mean_I_g; 
    var_I_rb = boxfilter(I(:, :, 1).*I(:, :, 3), r) ./ N - mean_I_r .*  mean_I_b; 
    var_I_gg = boxfilter(I(:, :, 2).*I(:, :, 2), r) ./ N - mean_I_g .*  mean_I_g; 
    var_I_gb = boxfilter(I(:, :, 2).*I(:, :, 3), r) ./ N - mean_I_g .*  mean_I_b; 
    var_I_bb = boxfilter(I(:, :, 3).*I(:, :, 3), r) ./ N - mean_I_b .*  mean_I_b; 
    
    a = zeros(hei, wid, 3);
    for y=1:hei
        for x=1:wid        
            Sigma = [var_I_rr(y, x), var_I_rg(y, x), var_I_rb(y, x);
                var_I_rg(y, x), var_I_gg(y, x), var_I_gb(y, x);
                var_I_rb(y, x), var_I_gb(y, x), var_I_bb(y, x)];
            Sigma = Sigma + eps * eye(3);
            
            cov_Ip = [cov_Ip_r(y, x), cov_Ip_g(y, x), cov_Ip_b(y, x)];        
            
            a(y, x, :) = cov_Ip * inv(Sigma + eps * eye(3)); % Eqn. (14) in the paper;
        end
    end
    
    b = mean_p - a(:, :, 1) .* mean_I_r - a(:, :, 2) .* mean_I_g - a(:, :, 3) .* mean_I_b; % Eqn. (15) in the paper;
    
    q = (boxfilter(a(:, :, 1), r).* I(:, :, 1)...
    + boxfilter(a(:, :, 2), r).* I(:, :, 2)...
    + boxfilter(a(:, :, 3), r).* I(:, :, 3)...
    + boxfilter(b, r)) ./ N;  % Eqn. (16) in the paper;
    end

    4.boxfilter

    function imDst = boxfilter(imSrc, r)
    
    %   BOXFILTER   O(1) time box filtering using cumulative sum
    %
    %   - Definition imDst(x, y)=sum(sum(imSrc(x-r:x+r,y-r:y+r)));
    %   - Running time independent of r; 
    %   - Equivalent to the function: colfilt(imSrc, [2*r+1, 2*r+1], 'sliding', @sum);
    %   - But much faster.
    
    [hei, wid] = size(imSrc);%记录长宽
    imDst = zeros(size(imSrc));%生成新矩阵
    
    %cumulative sum over Y axis
    imCum = cumsum(imSrc, 1);%计算各列的累加和
    %difference over Y axis
    imDst(1:r+1, :) = imCum(1+r:2*r+1, :);
    imDst(r+2:hei-r, :) = imCum(2*r+2:hei, :) - imCum(1:hei-2*r-1, :);
    imDst(hei-r+1:hei, :) = repmat(imCum(hei, :), [r, 1]) - imCum(hei-2*r:hei-r-1, :);
    
    %cumulative sum over X axis
    imCum = cumsum(imDst, 2);%计算各行的累加和
    %difference over Y axis
    imDst(:, 1:r+1) = imCum(:, 1+r:2*r+1);
    imDst(:, r+2:wid-r) = imCum(:, 2*r+2:wid) - imCum(:, 1:wid-2*r-1);
    imDst(:, wid-r+1:wid) = repmat(imCum(:, wid), [1, r]) - imCum(:, wid-2*r:wid-r-1);
    end

    5.最小值滤波

    function Y = minfilt2(X,varargin)
    %  MINFILT2    Two-dimensional min filter
    %
    %     Y = MINFILT2(X,[M N]) performs two-dimensional minimum
    %     filtering on the image X using an M-by-N window. The result
    %     Y contains the minimun value in the M-by-N neighborhood around
    %     each pixel in the original image. 
    %     This function uses the van Herk algorithm for min filters.
    %
    %     Y = MINFILT2(X,M) is the same as Y = MINFILT2(X,[M M])
    %
    %     Y = MINFILT2(X) uses a 3-by-3 neighborhood.
    %
    %     Y = MINFILT2(..., 'shape') returns a subsection of the 2D
    %     filtering specified by 'shape' :
    %        'full'  - Returns the full filtering result,
    %        'same'  - (default) Returns the central filter area that is the
    %                   same size as X,
    %        'valid' - Returns only the area where no filter elements are outside
    %                  the image.
    %
    %     See also : MAXFILT2, VANHERK
    %
    
    % Initialization
    [S, shape] = parse_inputs(varargin{:});
    
    % filtering
    Y = vanherk(X,S(1),'min',shape);%用van Herk算法对每一行进行滤波
    Y = vanherk(Y,S(2),'min','col',shape);%用van Herk算法对每一列进行滤波
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function [S, shape] = parse_inputs(varargin)
    shape = 'same';
    flag = [0 0]; % size shape
    
    for i = 1 : nargin
       t = varargin{i};
       if strcmp(t,'full') & flag(2) == 0
          shape = 'full';
          flag(2) = 1;
       elseif strcmp(t,'same') & flag(2) == 0
          shape = 'same';
          flag(2) = 1;
       elseif strcmp(t,'valid') & flag(2) == 0
          shape = 'valid';
          flag(2) = 1;
       elseif flag(1) == 0
          S = t;
          flag(1) = 1;
       else
          error(['Too many / Unkown parameter : ' t ])
       end
    end
    
    if flag(1) == 0
       S = [3 3];
    end
    if length(S) == 1;
       S(2) = S(1);
    end
    if length(S) ~= 2
       error('Wrong window size parameter.')
    end

    6.最大值滤波

    function Y = maxfilt2(X,varargin)
    %  MAXFILT2    Two-dimensional max filter
    %
    %     Y = MAXFILT2(X,[M N]) performs two-dimensional maximum
    %     filtering on the image X using an M-by-N window. The result
    %     Y contains the maximun value in the M-by-N neighborhood around
    %     each pixel in the original image. 
    %     This function uses the van Herk algorithm for max filters.
    %
    %     Y = MAXFILT2(X,M) is the same as Y = MAXFILT2(X,[M M])
    %
    %     Y = MAXFILT2(X) uses a 3-by-3 neighborhood.
    %
    %     Y = MAXFILT2(..., 'shape') returns a subsection of the 2D
    %     filtering specified by 'shape' :
    %        'full'  - Returns the full filtering result,
    %        'same'  - (default) Returns the central filter area that is the
    %                   same size as X,
    %        'valid' - Returns only the area where no filter elements are outside
    %                  the image.
    %
    %     See also : MINFILT2, VANHERK
    %
    
    % Initialization
    [S, shape] = parse_inputs(varargin{:});
    
    % filtering
    Y = vanherk(X,S(1),'max',shape);
    Y = vanherk(Y,S(2),'max','col',shape);
    
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function [S, shape] = parse_inputs(varargin)
    shape = 'same';
    flag = [0 0]; % size shape
    
    for i = 1 : nargin
       t = varargin{i};
       if strcmp(t,'full') & flag(2) == 0
          shape = 'full';
          flag(2) = 1;
       elseif strcmp(t,'same') & flag(2) == 0
          shape = 'same';
          flag(2) = 1;
       elseif strcmp(t,'valid') & flag(2) == 0
          shape = 'valid';
          flag(2) = 1;
       elseif flag(1) == 0
          S = t;
          flag(1) = 1;
       else
          error(['Too many / Unkown parameter : ' t ])
       end
    end
    
    if flag(1) == 0
       S = [3 3];
    end
    if length(S) == 1;
       S(2) = S(1);
    end
    if length(S) ~= 2
       error('Wrong window size parameter.')
    end
  • 相关阅读:
    P1093 奖学金
    华容道
    回文数
    P1654 OSU!
    Noip P1063 能量项链
    Noip 寻宝
    NOIP 2009 普及组 第三题 细胞分裂
    拦截器
    OGNL
    Struts2 配置详解
  • 原文地址:https://www.cnblogs.com/pursuit1996/p/4912202.html
Copyright © 2020-2023  润新知