暗通道先验法图像去雾

参考论文:Single Image Haze Removal Using Dark Channel Prior

在计算机视觉当中,通常使用下面这个模型去描述一幅有雾的图像:

对于这个模型,我是这样理解的,I(x)是我们观察到的灰度,J(x)是场景在无雾时的实际光照,而A是全局大气光照强度,t(x)是透射率。去雾的目标是通过I(x)来恢复J(x)和A。如果我们稍微的把这个模型变换一下:

从上面这条公式可以看出,如果我们能够求出大气光照和透射率的话,那我们就可以还原图像在没有雾的时候实际光照了,这就实现了图像的去雾。当t(x)的值非常小的时候,公式1中的J(x)*t(x)也会非常小,如果这样直接把图像J(x)恢复出来的话,虽然能有更好的去雾效果,但是会存在非常多的噪点,所以为了限制噪点的数量,我们把t的最小值限制在0.1,这也意味着会有少量的雾保留在图中。

这个去雾算法叫暗通道先验法,大多数无雾室外图像中的局部图像中包含一些像素,这些像素在至少一个颜色通道中具有非常低的灰度,我们把这些像素称之为暗通道像素。经过观察,75%的暗通道像素灰度为0,90%的暗通道像素灰度都在25以下。在有雾图像中我们优先利用这个特点,我们可以估计雾的浓度然后把图像还原成高质量的去雾图像。

我们首先提取暗通道中灰度小于50的像素,根据这些像素占总像素的比例来选择合适的参数,然后这些像素中找到灰度最高的像素就被选择作为大气光照强度。再计算出图像的透射率,最后利用公式②来回复图像。

程序和流程图如下。

 

close all
clear all
clc

w0=0.6; 
t0=0.1;
%I=imread('D:\Matlab\dehaze\初始图像\有雾图像样本1.jpg'); %读取需要处理的图像样本
I=imread('D:\Matlab\dehaze\初始图像\有雾图像样本2.jpg');

subplot(3,2,1);                                         %表示3(行数)*2(列数)的图像,1代表所画图形的序号
%subplot(2,2,1);
imshow(I);                                              %显示读取到的图像
title('原始图像:');                                     %给读取到的图像添加标题

subplot(3,2,3);                                         %在读取到的图像下面添加图像
%subplot(2,2,3);
grayI=rgb2gray(I);                                      %将RGB图像转换为灰度图
imshow(grayI,[]);                                       %将原始图像转换的灰度图展示在原始图像的下方
title('原图像灰度图:')

subplot(3,2,4);                                         %在第四个位置显示原始图像的直方图
imhist(grayI,256);                                      %计算灰度图像的直方图
title('原图像灰度直方图:')

%统计<50的像素所占的比例
[COUNT,x]=imhist(grayI);                                %返回初始图像直方图每一级的像素个数
under_50=0;
for i=0:50                                              %统计有多少像素的灰度级别小于50
    under_50=under_50+COUNT(x==i);
end
under_50
total=size(I,1)*size(I,2)*size(I,3);                    %I是读取的图像样本,这个方程是计算图像大小?
percent=under_50/total                                  %计算深色像素在所有像素中占的比例

if(percent>0.02)                                        %灰度小于50的像素的比例大于2%就不需要去雾。灰度值越小,图像越黑
    error('This image need not Haze-Free-Proprocessing.');
else if(percent<0.001)                                  %w0这个参数用于保留远处物体的雾,从而使图像看起来更自然,保留更多的深度信息
        w0=0.6;                                         %w0=0不去雾,w0=1去掉全部的雾,不过最好不要超过0.7,不然过饱和
    else if (percent>0.01)                              
            w0=0.3;
        else
            w0=0.45;
        end
    end
end

[h,w,s]=size(I);                                        %返回三个维度的大小(高,宽,颜色)
for i=1:h
    for j=1:w
        dark_I(i,j)=min(I(i,j,:));                      %取每个点的像素为RGB分量中最低的那个通道的值,组成矩阵
    end
end

Max_dark_channel=double(max(max(dark_I)))               %在找到所有像素RGB分量最低的那个通道的值后,再在这些值中找到最亮那个,作为大气光线的估计值
dark_channel=double(dark_I);                            %把矩阵里面的元素转换为双精度类型
t=1-w0*(dark_channel/Max_dark_channel);                 %计算透射率 t                                    
t=max(t,t0);                                            %t0初始值为0.1

I1=double(I);
J(:,:,1) = uint8((I1(:,:,1) - (1-t)*Max_dark_channel)./t);  %使用公式②进行去雾
J(:,:,2) = uint8((I1(:,:,2) - (1-t)*Max_dark_channel)./t);  
J(:,:,3) = uint8((I1(:,:,3) - (1-t)*Max_dark_channel)./t);

subplot(3,2,2);                                             %在第二个位置绘制已经去雾的图像
%subplot(2,2,2);
imshow(J);                                                  %J是处理后的图像
%imwrite(J,'D:\Matlab\dehaze\去雾图像\去雾图像1.jpg');
imwrite(J,'D:\Matlab\dehaze\去雾图像\去雾图像2.jpg');       %使用绝对路径,不然会报错
title('去雾图像:');

subplot(3,2,5);                                             %在第5个位置显示去雾后图像的灰度图
%subplot(2,2,4);
grayJ=rgb2gray(J);
imshow(grayJ,[]);
title('去雾后灰度图:')                                      

subplot(3,2,6);
imhist(grayJ,256);                                          %返回处理图像直方图每一级的像素个数
title('去雾图像灰度直方图:')

 

  • 5
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值