zoukankan      html  css  js  c++  java
  • 滤波及对图像处理的去雾的研究

    本周复习了滤波,对图像处理的去雾作了进一步研究

    去雾

    暗原色先验快速去雾

    大气散射模型

    大气散射模型描述了雾化图像的退化过程:
    I(x)=J(x)t(x)+A(1-t(x));

    I是观测图像的强度,

    J是景物光线的强度,

    A是无穷远处的大气光,

    t称为透射率。

    去雾的目标就是从I中复原J。方程中的第一项J(x)t(x)叫做直接衰减项,A(1−t(x))是大气光成分。

    暗原色先验

    暗原色先验是HEKai-ming等人发现的,是通过对大量户外无雾图像的统计观察得出的:在绝大多数图像的局部区域里,某一些像素总会有至少一个颜色通道具有很低的值。换言之,该区域光强度的最小值是很小的数。对图像J,定义:
    image

    代码

    clc;
    clear all;
    img_name='2.jpg';
    %原始图像
    I=double(imread(img_name))/255;
    %图像每个像元每个通道的灰度值均要除以255
    %获取图像大小
    [h,w,c]=size(I);%h,w代表行和列
    win_size=7;%窗口大小
    img_size=w*h;
    figure,imshow(I);
    win_dark=ones(h,w);%定义一个矩阵有h行w列
    %计算分块darkchannel
    for j=1+win_size:w-win_size
        for i=1+win_size:h-win_size
            m_pos_min=min(I(i,j,:));%每个(i,j)像元三通道的最小值
          for n=j-win_size:j+win_size                 %该像元的15领域
                for m=i-win_size:i+win_size
                    if(win_dark(m,n)>m_pos_min)
                        win_dark(m,n)=m_pos_min;
                    end
                end
            end
        end
    end
    figure(2),imshow(win_dark);%显示分块darkchannel
    %选定精确dark value坐标
    win_t=1-0.95*win_dark;%得到的win_t还是160行,243列
    win_b=zeros(img_size,1);%定义一个矩阵,img_size行,1列,里面数值全为0
    for ci=1:h
        for cj=1:w
            if(rem(ci-8,15)<1)%rem表示取余数
                if(rem(ci-8,15)<1)     
                    win_b(ci*w+cj)=win_dark(ci*w+cj);     
                end
            end
        end
    end
    neb_size = 9; 
    win_size = 1;  
    epsilon = 0.0000001; %指定矩阵形状
    indsM=reshape([1:img_size],h,w);%是不是win_dark 
    %计算矩阵L
    tlen = img_size*neb_size^2;
    row_inds=zeros(tlen ,1);
    col_inds=zeros(tlen,1);
    vals=zeros(tlen,1); 
    len=0;  
    for j=1+win_size:w-win_size     
        for i=win_size+1:h-win_size         
            if(rem(ci-8,15)<1)             
                if(rem(cj-8,15)<1)                
                    continue;            
                end
            end
            win_inds=indsM(i-win_size:i+win_size,j-win_size:j+win_size);    
            win_inds=win_inds(:);%列显示      
            winI=I(i-win_size:i+win_size,j-win_size:j+win_size,:);
                  winI=reshape(winI,neb_size,c); %三个通道被拉平成为一个二维矩阵 3*9
          win_mu=mean(winI,1)';  %求每一列的均值 如果第二个参数为2 则为求每一行的均值  //矩阵变向量
          win_var=inv(winI'*winI/neb_size-win_mu*win_mu' +epsilon/neb_size*eye(c)); %求方差
          winI=winI-repmat(win_mu',neb_size,1);%求离差
          tvals=(1+winI*win_var*winI')/neb_size;% 求论文所指的矩阵L
          row_inds(1+len:neb_size^2+len)=reshape(repmat(win_inds,1,neb_size),...
                                                 neb_size^2,1);
          col_inds(1+len:neb_size^2+len)=reshape(repmat(win_inds',neb_size,1),...
                                                 neb_size^2,1);
          vals(1+len:neb_size^2+len)=tvals(:);
          len=len+neb_size^2;
        end
    end 
     
     
    vals=vals(1:len);
    row_inds=row_inds(1:len);
    col_inds=col_inds(1:len);
    %创建稀疏矩阵
    A=sparse(row_inds,col_inds,vals,img_size,img_size);
    %求行的总和 sumA为列向量
    sumA=sum(A,2);
    %spdiags(sumA(:),0,img_size,img_size) 创建img_size大小的稀疏矩阵其元素是sumA中的列元素放在由0指定的对角线位置上。
    A=spdiags(sumA(:),0,img_size,img_size)-A;
    
      %创建稀疏矩阵
      D=spdiags(win_b(:),0,img_size,img_size);
      lambda=1;
      x=(A+lambda*D)(lambda*win_b(:).*win_b(:));
     
       %去掉0-1范围以外的数
      alpha=max(min(reshape(x,h,w),1),0);
     
    figure, imshow(alpha);
    A=220/255; %大气光没有去计算
    %去雾
           
    for i=1:c
        for j=1:h
            for l=1:w
                dehaze(j,l,i)=(I(j,l,i)-A)/alpha(j,l)+A;
            end
        end
    end
    figure, imshow(dehaze);
    

    image右边圆柱的细节没有得到保留

    接着用retinex实现,相比较
    image
    retinex实现颜色有些失真

    Retinex实现图像去雾

    步骤

    读入图像→归一化→设置高斯函数参数及矩阵→高斯函数和输入图像矩阵卷积→取对数→和输入图像矩阵的对数相差→取指数→输出图像

    image
    image
    基于SSR算法便可以实现一个基本的图像去雾程序。下面的MATLAB代码是完全按照上面的思路来实现的。只是在最后,对R(x,y)作对比度增强,以得到最终的去雾图像。此外,因为这里处理的是彩色图像,所以我们对R、G、B三个通道分别进行了处理。

    实现代码

    I = imread('canon.jpg');
    
    R = I(:, :, 1);
    [N1, M1] = size(R);
    R0 = double(R);
    Rlog = log(R0+1);
    %图像I做对数变换前,需要转化为double型并做归一化。log(I+1)是为了满足真数大于0,以防计算无意义。特别提醒,一般不建议采用log(eps+I)方式
    Rfft2 = fft2(R0); %对图像进行傅立叶变换,转换到频域中 
    
    sigma = 250;
    F = fspecial('gaussian', [N1,M1], sigma);
    Efft = fft2(double(F));% 对高斯滤波函数进行二维傅里叶变换
    
    DR0 = Rfft2.* Efft;% 对R分量与高斯滤波函数进行卷积运算
    DR = ifft2(DR0);%做卷积后变换回空域中 
    
    DRlog = log(DR +1);
    % 在对数域中,用原图像减去低通滤波后的图像,得到高频增强的图像
    Rr = Rlog - DRlog;
    % 取反对数,得到增强后的图像分量
    EXPRr = exp(Rr);
    % 对增强后的图像进行对比度拉伸增强
    MIN = min(min(EXPRr));
    MAX = max(max(EXPRr));
    EXPRr = (EXPRr - MIN)/(MAX - MIN);
    EXPRr = adapthisteq(EXPRr);
    
    G = I(:, :, 2);
    
    G0 = double(G);
    Glog = log(G0+1);
    Gfft2 = fft2(G0); 
    
    DG0 = Gfft2.* Efft;
    DG = ifft2(DG0);
    
    DGlog = log(DG +1);
    Gg = Glog - DGlog;
    EXPGg = exp(Gg);
    MIN = min(min(EXPGg));
    MAX = max(max(EXPGg));
    EXPGg = (EXPGg - MIN)/(MAX - MIN);
    EXPGg = adapthisteq(EXPGg);
    
    B = I(:, :, 3);
    
    B0 = double(B);
    Blog = log(B0+1);
    Bfft2 = fft2(B0);
    
    DB0 = Bfft2.* Efft;
    DB = ifft2(DB0);
    
    DBlog = log(DB+1);
    Bb = Blog - DBlog;
    EXPBb = exp(Bb);
    MIN = min(min(EXPBb));
    MAX = max(max(EXPBb));
    EXPBb = (EXPBb - MIN)/(MAX - MIN);
    EXPBb = adapthisteq(EXPBb);
    % 对增强后的图像R、G、B分量进行融合
    result = cat(3, EXPRr, EXPGg, EXPBb);
    subplot(121), imshow(I);
    subplot(122), imshow(result);
    

    image

    直方图去雾

    f = imread('2.jpg');
    hsi = rgb2hsi(f);
    h = hsi (:, :, 1);
    s = hsi (:, :, 2);
    i = hsi (:, :, 3);
    g = cat(3, h, s, adapthisteq(i));
    g = hsi2rgb(g);
    subplot(1, 2, 1), imshow(f);
    subplot(1, 2, 2), imshow(g);
    

    image

    高斯滤波和双边滤波

    matlab自带高斯滤波

    clear all;clc;close all
    img=imread('1.jpg');
    gray=rgb2gray(img);                                     %把彩色图片转化成灰度图片
    figure(1),imshow(gray),title('彩色原始图像转灰色图像)'); %显示原始图像
    gray=imnoise(gray,'gaussian',0,0.002);                  %加入均值为0,方差为0.001的高斯噪声
    figure(2),imshow(gray),title('加入高斯噪声之后的图像');   %显示加入高斯噪声之后的图像
    
    % 用matlab系统函数进行高斯滤波
    sigma=0.5;                                                %滤波器的标准值,单位为像素
    hsize=[8 8];                                              %模板尺寸
    gsseq=fspecial('gaussian',hsize,sigma);                   %生成高斯序列
    Y1=filter2(gsseq,gray)/255;                               %用生成的高斯序列进行滤波
    figure(3),imshow(Y1),title('用Matlab自带函数进行高斯滤波'); %显示滤波后的图像
    

    image

    傅里叶变换实现高斯滤波

    clear all;clc;close all
    img=imread('1.jpg');
    gray=rgb2gray(img);                                     %把彩色图片转化成灰度图片
    figure,imshow(gray),title('彩色原始图像转灰色图像)'); %显示原始图像
    gray=imnoise(gray,'gaussian',0,0.002);                  %加入均值为0,方差为0.001的高斯噪声
    figure,imshow(gray),title('加入高斯噪声之后的图像');   %显示加入高斯噪声之后的图像
    gray=double(gray);
    gray=fft2(gray);%二维傅里叶变换
    gray=fftshift(gray);%频率居中
    [m,n]=size(gray);
    d0=90%标准差
    m1=fix(m/2);
    n1=fix(n/2);
    for i=1:m
        for j=1:n
            d=sqrt((i-m1)^2+(j-n1)^2);%计算像素点到图像中心的距离
            h(i,j)=exp(-d^2/2/d0^2);%高斯滤波器
        end
    end
    g=gray.*h;%将图像进行高斯滤波,频域上表现为为两个函数相乘
    g=ifftshift(g);                   %频域圆周移位
    g=ifft2(g);                       %二维傅里叶反变换
    g=mat2gray(real(g));              %归一化
    figure,imshow(g),title('用重新编写的程序进行高斯滤波');%显示滤波后的图像
    

    image

    双边滤波

    function B = bfltGray(A,w,sigma_d,sigma_r)
    % 计算距离因子权重
    [X,Y] = meshgrid(-w:w,-w:w);
    %创建核距离矩阵
    %e.g.
    %[x,y]=meshgrid(-1:1,-1:1)
    % 
    % x =
    % 
    %     -1     0     1
    %     -1     0     1
    %     -1     0     1
    % 
    % 
    % y =
    % 
    %     -1    -1    -1
    %      0     0     0
    %      1     1     1
    
    %计算定义域核
    G = exp(-(X.^2+Y.^2)/(2*sigma_d^2));
    
    %创建进度条
    h = waitbar(0,'Applying bilateral filter...');
    set(h,'Name','Bilateral Filter Progress');
    
    % 应用双边滤波
    %计算值域核H 并与定义域核G 乘积得到双边权重函数F
    dim = size(A);
    B = zeros(dim);
    for i = 1:dim(1)
       for j = 1:dim(2)
             %边界限制
             iMin = max(i-w,1);
             iMax = min(i+w,dim(1));
             jMin = max(j-w,1);
             jMax = min(j+w,dim(2));
             
             %定义当前核所作用的区域为(iMin:iMax,jMin:jMax)
             I = A(iMin:iMax,jMin:jMax);%提取该区域的源图像值赋给I
          
             % 计算亮度因子权重
             H = exp(-(I-A(i,j)).^2/(2*sigma_r^2));
          
             % 计算双边滤波结果
             F = H.*G((iMin:iMax)-i+w+1,(jMin:jMax)-j+w+1);
             B(i,j) = sum(F(:).*I(:))/sum(F(:));
                   
       end
       waitbar(i/dim(1));
    end
    % 结束进度条
    close(h);
    
    %A为给定图像,归一化到[0,1]的矩阵
    %w为双边滤波器(核)的边长/2
    %定义域方差σd记为SIGMA(1),值域方差σr记为SIGMA(2)
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    function B = bfilter2(A,w,sigma)
    % 检验给定图像是否存在并且有效
    if ~exist('A','var') || isempty(A)
       error('Input image A is undefined or invalid.');
    end
    if ~isfloat(A) || ~sum([1,3] == size(A,3)) || ...
          min(A(:)) < 0 || max(A(:)) > 1
       error(['Input image A must be a double precision ',...
              'matrix of size NxMx1 or NxMx3 on the closed ',...
              'interval [0,1].']);      
    end
    
    % 检验双边滤波器的半宽是否符合要求
    if ~exist('w','var') || isempty(w) || ...
          numel(w) ~= 1 || w < 1
       w = 5;
    end
    w = ceil(w);
    
    % 检验sigma参数是否符合要求
    if ~exist('sigma','var') || isempty(sigma) || ...
          numel(sigma) ~= 2 || sigma(1) <= 0 || sigma(2) <= 0
       sigma = [3 0.1];
    end
    
    %选择彩色模式或灰度模式
    if size(A,3) == 1
       B = bfltGray(A,w,sigma(1),sigma(2));
    else
       B = bfltColor(A,w,sigma(1),sigma(2));
    end
    
    %调用示例
    I=imread('noise.tif'); %读入图片
    I=double(I)/255;  %转为double型并归一化
    w     = 5;        % 双边滤波器半宽,w越大平滑作用越强
    sigma = [3 0.1];  % 空间距离方差σd记为SIGMA(1),像素亮度方差σr记为SIGMA(2),即空间邻近度因子和亮度相似度因子的衰减程度
    I1=bfilter2(I,w,sigma);                     %双边滤波器滤波
    figure(1),imshow(I),title('原始图像');       %作出原始图像
    figure(2),imshow(I1),title('双边滤波后的图像')%作出双边滤波后的图像
    

    image

  • 相关阅读:
    (转)Android获取手机信息
    ListView中RadioButton实现单项选择
    ListView 实现分组
    解决PopupWindow遮住输入法
    Oracle多行记录合并处理
    ubuntu install express
    图片以BLOB存储在后台数据库中,Android客户端要进行读取显示
    将图片以Blob格式存入数据库,再通过Servlet显示到界面
    httpcomponents-client-4.3.6 HttpPost的简单使用
    设置Ubuntu Mysql可以远程链接
  • 原文地址:https://www.cnblogs.com/is-Tina/p/7435979.html
Copyright © 2011-2022 走看看