《Single Image Haze Removal Using Dark Channel Prior》去雾代码实现分析

本文主要为了通过对代码进行分析,帮助更进一步了解《Single Image Haze Removal Using Dark Channel Prior》的操作步骤。

在看本篇文章前,需要对《Single Image Haze Removal Using Dark Channel Prior》有大致的了解。提供一个文章解析参考的连接:https://www.cnblogs.com/Imageshop/p/3281703.html
本文的代码分析也是基于上述文章中的代码资源进行分析的,本文主要在于结合代码梳理出更加清晰的思路,并且对代码进行了较为详细的注释。

一、主程序
首先在这给出主程序及其相关注释

clear
clc
close all

kenlRatio = 0.01;
minAtomsLight = 240;            %设定的大气光的上限值
% image_name =  'test images\21.bmp';
image_name =  'D:\1.png';       %原图像
img=imread(image_name);         %读取原始图片文件中的数据
figure,imshow(uint8(img)), title('src');   %显示原始图像  并且显示标题 

sz=size(img);       %返回一个行向量sz,该行向量的第一个元素时矩阵的行数,第二个元素是矩阵的列数。
w=sz(2);            %读取所提取矩阵的列数
h=sz(1);             %读取所提取矩阵的行数
dc = zeros(h,w);      %返回一个h×w的0矩阵给dc,实际上这个矩阵的size=原输入图像size

for y=1:h               %行遍历          
    for x=1:w           %列遍历
        dc(y,x) = min(img(y,x,:));  %对原图像的每一个像素求RGB3个通道中的最小亮度值,然后赋值给dc矩阵的y行x列
    end
end

figure,imshow(uint8(dc)), title('Min(R,G,B)');  %显示原图像的灰度图

krnlsz = floor(max([3, w*kenlRatio, h*kenlRatio])) %krnlsz为最小滤波窗口的边长尺寸大小
%kenlRatio是一个预设的值,求尺寸时拿kenlRatio和灰度图矩阵长和宽(即w和h)乘上这个预设值和3进行比较,选择最大数作为窗口尺寸
dc2 = minfilt2(dc, [krnlsz,krnlsz]);        %对得到的灰度图进行最小值滤波获得暗通道图像

dc2(h,w)=0;             %dc2矩阵的h行w列赋值0
figure,imshow(uint8(dc2)), title('After filter ');  %显示滤波后的图像
t = 255 - dc2;          %下面4行对应公式11,即求出传输特性t(x)的估计值
figure,imshow(uint8(t)),title('t');     %显示传输特性t的图像(原始的方法求t)
t_d=double(t)/255;
sum(sum(t_d))/(h*w)     %t(x)表示的是x像素出的t的估计值,而此处将t_d的矩阵进行平均处理求出一个平均的t值


A = min([minAtomsLight, max(max(dc2))]) %根据论文提示的方法求A值,不过为了防止A过高,设置了一个上限值minAtomsLight
                                         %max(max(dc2))表示从暗通道图中按照亮度的大小取前0.1%的像素。在这些位置中,在原始有雾图像I中寻找对应的具有最高亮度的点的值,作为A值
J = zeros(h,w,3);       %生成一个0矩阵J 大小为h×w 此处的3表示rgb3个通道
img_d = double(img);    %原始图像类型转换成double

J(:,:,1) = (img_d(:,:,1) - (1-t_d)*A)./t_d; %根据公式22求出图像矩阵所有元素的R通道的值,下面两行为G和B的值
J(:,:,2) = (img_d(:,:,2) - (1-t_d)*A)./t_d;
J(:,:,3) = (img_d(:,:,3) - (1-t_d)*A)./t_d;

figure,imshow(uint8(J)), title('J');    %显示去雾图像J


%----------------------------------
%由于透射率图过于粗糙,而通过导向滤波的方式来获得较好的透射率图,下面是导向滤波计算t的方式
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

t_d = filtered;%导向滤波计算的值赋值给t_d矩阵
figure,imshow(t_d,[]),title('filtered t');  %显示导向滤波后求出的t值

J(:,:,1) = (img_d(:,:,1) - (1-t_d)*A)./t_d; %根据公式22求出图像矩阵所有元素的R通道的值,下面两行为G和B的值
J(:,:,2) = (img_d(:,:,2) - (1-t_d)*A)./t_d;
J(:,:,3) = (img_d(:,:,3) - (1-t_d)*A)./t_d;

imwrite(uint8(J),'D:\11.bmp');%将去雾后的图像数据写入到文件中
figure,imshow(uint8(J)), title('J_guild_filter');%显示导向滤波后求出的去雾图像J

二、主程序拆解分析
1.首先,根据文章我们可以得知:基于暗通道先验的思想,我们可以先求出t的预估值:
在暗通道先验的原理下,求t预估值的公式转化为:
在这里插入图片描述
对于一张确定的图,我们认为Ac大气光是一个定值。
我们首先计算出原输入图像的灰度图,即括号内的部分minc Ic(y)。大概思路是对原图像的所有像素x求RGB通道中亮度最小的值,从而得到灰度图。

image_name =  'D:\1.png';       %原图像
img=imread(image_name);         %读取原始图片文件中的数据
figure,imshow(uint8(img)), title('src');   %显示原始图像  并且显示标题 
sz=size(img);       %返回一个行向量sz,该行向量的第一个元素时矩阵的行数,第二个元素是矩阵的列数。
w=sz(2);            %读取所提取矩阵的列数
h=sz(1);             %读取所提取矩阵的行数
dc = zeros(h,w);      %返回一个h×w的0矩阵给dc,实际上这个矩阵的size=原输入图像size
for y=1:h               %行遍历          
    for x=1:w           %列遍历
        dc(y,x) = min(img(y,x,:));  %对原图像的每一个像素求RGB3个通道中的最小亮度值,然后赋值给dc矩阵的y行x列
    end
end
figure,imshow(uint8(dc)), title('Min(R,G,B)');  %显示原图像的灰度图

对于公式11减号后面内容的实现:对上面得到的灰度图像进行最小值滤波,minfilt2是一个最小值滤波的函数。

kenlRatio = 0.01;
krnlsz = floor(max([3, w*kenlRatio, h*kenlRatio])) %krnlsz为最小滤波窗口的边长尺寸大小
%kenlRatio是一个预设的值,求尺寸时拿kenlRatio和灰度图矩阵长和宽(即w和h)乘上这个预设值和3进行比较,选择最大数作为窗口尺寸
dc2 = minfilt2(dc, [krnlsz,krnlsz]);        %对得到的灰度图进行最小值滤波获得暗通道图像

最后进行归一化、均值处理实现公式11的效果:

dc2(h,w)=0;             %dc2矩阵的h行w列赋值0
figure,imshow(uint8(dc2)), title('After filter ');  %滤波后的图像结果
t = 255 - dc2;          %下面4行对应公式11,即求出传输特性t(x)的估计值
figure,imshow(uint8(t)),title('t');     %显示传输特性t的图像(原始的方法求t)
t_d=double(t)/255;
sum(sum(t_d))/(h*w)     %t(x)表示的是x像素出的t的估计值,而此处将t_d的矩阵进行平均处理求出一个平均的t值

2.预估了传输特性t值后,现在根据文章求出大气光A的估值。

minAtomsLight = 240;            %设定的大气光的上限值
A = min([minAtomsLight, max(max(dc2))]) %根据论文提示的方法求A值,不过为了防止A过高,设置了一个上限值minAtomsLight

3.根据最终的求去雾图像J的公式来还原去雾图像,根据的公式如下:
在这里插入图片描述
代码中的平均估值t_d替换的是公式中的max(t(x),t0)部分。

J = zeros(h,w,3);       %生成一个0矩阵J 大小为h×w 此处的3表示rgb3个通道
img_d = double(img);    %原始图像类型转换成double
J(:,:,1) = (img_d(:,:,1) - (1-t_d)*A)./t_d; %根据公式22求出图像矩阵所有元素的R通道的值,下面两行为G和B的值
J(:,:,2) = (img_d(:,:,2) - (1-t_d)*A)./t_d;
J(:,:,3) = (img_d(:,:,3) - (1-t_d)*A)./t_d;
figure,imshow(uint8(J)), title('J');    %显示去雾图像J

4.由于透射率图过于粗糙,而通过导向滤波的方式来获得较好的透射率图,下面是导向滤波计算t的方式。

r = krnlsz*4
eps = 10^-6;
filtered = guidedfilter(double(rgb2gray(img))/255, t_d, r, eps);%导向滤波计算t
t_d = filtered;%导向滤波计算的值赋值给t_d矩阵
figure,imshow(t_d,[]),title('filtered t');  %显示导向滤波后求出的t值

5.利用导向滤波计算的t_d求出最后的去雾图像

J(:,:,1) = (img_d(:,:,1) - (1-t_d)*A)./t_d; %根据公式22求出图像矩阵所有元素的R通道的值,下面两行为G和B的值
J(:,:,2) = (img_d(:,:,2) - (1-t_d)*A)./t_d;
J(:,:,3) = (img_d(:,:,3) - (1-t_d)*A)./t_d;

imwrite(uint8(J),'D:\11.bmp');%将去雾后的图像数据写入到文件中
figure,imshow(uint8(J)), title('J_guild_filter');%显示导向滤波后求出的去雾图像J

三、程序运行结果
1.显示原始输入图像
在这里插入图片描述
2.显示原始图像的灰度图
在这里插入图片描述
3.显示对原始图像灰度图进行最小滤波后的结果
在这里插入图片描述
4.求出利用暗通道先验计算的t
在这里插入图片描述
5.根据求出的t和A计算出去雾图像J
在这里插入图片描述
6.为了细化t,此处求导向滤波后的t
在这里插入图片描述
7.利用导向滤波后求出的去雾图像
在这里插入图片描述
四、说明
这里值分析了主程序的思路,对于最小滤波和导向滤波的程序未分析,具体的代码见文章开头给出的链接。

  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
### 回答1: 单图像去是一种常见的计算机视觉问题,它旨在从含有霾的图像中恢复出清晰的图像。"Dark Channel Prior"是一种常用的算法,在单图像去中有着广泛的应用。 Dark Channel Prior(暗通道先验)是通过观察自然景物在局部区域中深度最小像素的强度来估计霾浓度和传播距离的先验知识。Dark Channel可以简单地通过在输入图像的每个像素位置上采用最小值操作来计算得到。这样,我们可以仿佛窥视很多景物的背后,包括霾中那些没有的真实景物。 Dark Channel Prior算法分为三个步骤: 1. 估计暗通道:对输入图像的每个像素计算出最小通道值,得到每个像素位置的暗通道。由于霾导致图像亮度改变,这一步估计了景物中的最小透射率。 2. 估计大气光:通过在暗通道图像中找到最亮的像素值,得到估计的大气光。这是因为大气光对于霾图像中的亮度改变有关键作用。 3. 去恢复:基于估计的暗通道和大气光,我们可以在图像中进行退化模型的恢复,以消除霾效应。这可以通过以下公式实现:R = (I - A) / t + A,其中R是去后的图像,I是输入图像,A是估计的大气光,t是透射率。 代码实现上,我们可以通过使用基于块的方法来减小计算量,同时在去后对结果进行细化和增强,以获得更好的效果。在此基础上,还可以采用其他技术和方法来进一步改进去结果,例如引入图像边缘信息和增加颜色校正。 总之,单图像去是一项具有挑战性和广泛应用的任务。"Dark Channel Prior" 算法被证明是一种有效的方法,能够在一定程度上还原出清晰的图像,提升霾图像的质量。 ### 回答2: Single image haze removal using dark channel prior是一种用于去除图片中霾的算法。该算法通过分析图像的暗通道先验信息来估计图像中的霾程度,并进行相应的去操作。 暗通道先验是指图像中的某些区域在某个颜色通道上的像素值较低。这是因为霾会使得图像中的物体颜色变浅,而远处的物体通常更加受到霾的影响。基于此,算法通过寻找图像中的暗通道来估计霾强度。 具体实现方案如下: 1. 对于给定的输入图像,算法首先计算图像的暗通道。这可以通过对图像的每个像素点在RGB颜色空间中选择最小值来实现。 2. 通过暗通道估计得到的霾强度,算法可以计算出每个像素点在霾下的透射率。透射率越高,表示该像素受到的霾影响越小。 3. 基于透射率,算法可以计算出未被霾遮挡的场景亮度。这可以通过选择图像中的最大值来实现。 4. 最后,算法通过去除透射率和场景亮度对图像进行去操作。这可以通过对每个像素点应用去公式来实现。去公式将图像中的像素值重新映射,以减少霾的影响。 通过单一图像和暗通道先验的使用,该算法能够较好地去除图像中的霾,提高图像的可视性和质量。它在计算机视觉和图像处理领域有着广泛的应用,例如景观摄影和无人驾驶等。 ### 回答3: Single image haze removal using dark channel prior是一种用于去除图像霾的算法。这个算法的代码实现逻辑是基于一个称为“暗通道先验”的概念。 在这个算法中,我们首先计算图像的暗通道图像。暗通道图像是指在图像的每个局部区域内,选择像素值最小的通道作为该区域的暗通道像素值。通过计算暗通道图像,我们可以得到整个图像的暗通道图像。 接下来,通过观察我们发现,大部分的非天空区域的暗通道像素值都是接近于0的,而天空区域的暗通道像素值通常会高于0。而这些高于0的像素值正是由于霾所导致的。 因此,我们可以通过选取每个局部区域内暗通道像素值最小的像素点作为参考点,来估算出霾的浓度。进一步地,我们可以根据这个浓度值来消除图像的霾。 具体地,我们可以使用以下公式来计算去除霾后的像素值: t(x) = 1 - w * min(R/G, R/B) 其中,t(x)表示去除霾后的像素值,w表示霾浓度(衡量霾的程度),R/G和R/B分别表示图像红色通道和绿色通道以及蓝色通道的比值。这个公式可以将原始像素值转换为去除霾后的像素值。 最后,我们可以根据去除霾后的像素值和原始图像的亮度值来还原最终的去图像。 Single image haze removal using dark channel prior代码实现了上述算法的具体步骤和细节。通过使用这个代码,我们可以方便地对图像进行去处理,使得图像更加清晰和真实。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值