滤波及对图像处理的去雾的研究

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

去雾

暗原色先验快速去雾

大气散射模型

大气散射模型描述了雾化图像的退化过程:
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

posted @ 2017-08-26 17:51  于繁华求淡然  阅读(1899)  评论(0编辑  收藏  举报