暗通道先验法

大气散射模型

$$ I(x)=I_{\infty}r(x)e^{-kd(x)}+I_{\infty}(1-e^{-kd(x)}) $$

其中$r(x)$为反射率, $I_{\infty}$为无穷远处天空辐射强度, $I_{\infty}r(x)$为没有任何干扰情况下的图像, 有雾的情况下大气透射率为$e^{-kd(x)}$, $k$为散射系数

简化为:

$$ I(x)=J(x)t(x)+A[1-t(x)] $$

$A$为环境光, $J(x)$为无雾图像对应的场景辐射, $t(x)$为大气透射率$0\le t(x)\le 1$

得到恢复原图像的公式:

$$ J(x)=A-\frac{A-I(x)}{t(x)} $$

暗通道先验

暗通道为RGB通道中值最小的, 对于每个像素取最小值, 取其中最亮的0.1%的均值为环境光的估计, 因为一般天空为最亮, 代入公式天空是正好吸收和反射补偿了, 但是对于没有天空或者有灯光干扰的情况估计值就会偏小或者偏大

对于上式取最小值运算

$$ \min_{y\in N(x)}\left[\min_{C\in \{R,G,B\}}\frac{I_{C}(y)}{A_{C}}\right]=\left[1-t^{N}(x)\right]+\min_{y\in N(x)}\left[\min_{C\in \{R,G,B\}}\frac{I_C(y)}{A_C}\right]t^N(x) $$

可以得到$N_r(x)$邻域大气透射率的估计值$t^N(x)$:

$$ t^N(x)=1-\min_{y\in N(x)}\left[\min_{C\in \{R,G,B\}}\frac{I_C(y)}{A_C}\right] $$

MATLAB实现代码:

 1close all;
 2clearvars;
 3
 4fog = imread('fog1.jpg');
 5
 6figure
 7imshow(fog)
 8% find darkness channel
 9
10darkness = min(fog, [], 3);
11array_size = size(darkness);
12after = fog;
13after = double(after);
14tN = zeros(array_size, 'double');
15pixel_count = array_size(1,1) * array_size(1,2);
16reshaped_array = reshape(darkness, [1, pixel_count]);
17sorted_array = sort(reshaped_array, 'descend');
18sample_count = round(pixel_count * 0.001);
19average_gray = sum(sorted_array(1, 1:sample_count))./sample_count;
20
21window_width = floor(min(array_size, [], "all")/16/2)*2+1;
22window_height = window_width;
23half_window_width = floor(window_width/2);
24half_window_height = floor(window_height/2);
25
26figure
27imshow(darkness);
28
29for r=1:array_size(1,1)
30    for c=1:array_size(1,2)
31        y_start = max(r - half_window_height, 1);
32        y_end = min(r + half_window_height, array_size(1,1));
33        x_start = max(c - half_window_width, 1);
34        x_end = min(c + half_window_height, array_size(1,2));
35        tN(r,c) = min(darkness(y_start:y_end, x_start:x_end), [], 'all');
36    end
37end
38figure
39imshow(uint8(tN));
40tN = 1 - 0.95.*tN./average_gray;
41after(:,:,1) = floor(average_gray - (average_gray - after(:,:,1))./tN);
42after(:,:,2) = floor(average_gray - (average_gray - after(:,:,2))./tN);
43after(:,:,3) = floor(average_gray - (average_gray - after(:,:,3))./tN);
44figure
45imshow(uint8(after));

算法结果: {% gi 6 3-3 %} fog1.png dark1.png after1.png fog2.png dark1.png after2.png {% endgi %}

第一组的效果比较好, 第二组在不同景深交界处会出现明显的光晕