在工業時代,各種汙染排放越來越大,空氣中瀰漫著濃濃的霧霾,我們也是很難看到藍天白雲,對遠處看去總是霧蒙蒙的一片,很難感受到大自然的美感。
甚至大媽大白天在霧霾中跳舞都會被人誤以為群魔亂舞的恐怖電影
可是我們心中的美好世界不應該是這樣的嘛:
事實上圖像處理技術,已經能夠幫我們從霧霾的世界裡看到美麗的希望。
下面一組圖,左邊是霧霾的原圖,右邊是採用了圖像處理算法去霧以後的效果。
上面的效果是如何做到的呢,下面就要講一個Matlab圖像去霧的算法
「暗通道先驗去霧」
暗通道先驗去霧是著名的大神何凱明在他上學的時候提出的,也是目前最廣泛應用的圖像去霧算法。
在了解這個算法之前我們需要了解一下圖像在大氣中衰減的模型:
J是原始的無霧霾圖像,隨著它在大氣的傳輸,受到不同的大氣衰減系統的衰減t,同時還要疊加上大氣中本身蘊含的大氣輻射,最終到達我們的相機中,我們採集到的圖像就是I。
何凱明大神發現,在無霧圖像中,每一個局部區域都很有可能會有陰影,或者是純顏色的東西,又或者是黑色的東西。因此,每一個局部區域都很有可能有至少一個顏色通道會有很低的值。把這個統計規律叫做Dark Channel Prior。
下面的公式就是暗通道的定義。
根據暗通道趨近於0的先驗理論,計算出來了大氣透過率
我們看到在計算t的時候,還需要知道大氣光A的數值,事實上大氣光A可以通過如下方法計算。
1.選取暗通道圖像暗通道最亮的0.1%的像素(一般來說,這些像素表示霧濃度最大的地方)
2.取輸入圖像裡面這些像素對應的像素裡面最亮的作為大氣光。
最終就可以計算出無霧的圖像,
話不多說,貼上Matlab的代碼:
close all;
clear;clc;
tic
pic=double(imread('7-1.png'));
pic=pic/256;
figure;
imshow(pic);
[m,n,c]=size(pic);
Feature=zeros(m,n);
pic_gray=rgb2gray(pic);%灰度化
adapt=1.4;
%循環更新每個像素的 梯度圖 顏色差圖 亮度比圖
blocksize=15;
pic_min=min(min(pic(:,:,1),pic(:,:,2)),pic(:,:,3));%求暗通道
se=strel('square',blocksize);
dark_pic=imerode(pic_min,se); %腐蝕一下才是標準的暗通道
% figure,imshow(dark_I);
U=reshape(dark_pic,1,m*n);
U1=sort(U,2,'descend');%對像素亮度排序
med=round(m*n*0.1);
U2=U1(1:med);
U3=unique(U2);
[s1,s2]=size(U3);
km=1;
for i=1:s2
[x y]=find(dark_pic==U3(i));
[l1,l2]=size(x);
for i=1:l1
x1=x(i,1);
y1=y(i,1);
km=km+1;
U4(km)=pic_gray(x1,y1);
end
end
A=max(U4(:)); %最大的像素的亮度是大氣光
%A求取完畢
%計算全圖的t,並將其中已經識別出的天空像素所對應的t改為1;
t=1-0.95*(dark_pic/A);%此處用的別的方法,請改為我的方法,此處有重大更新,具體請與我聯繫
figure,imshow(t);title('粗略透過率圖');
r =30;
eps = 0.001;
t_new =guidedfilter(pic_gray, t, r, eps);%引導濾波平滑透過率
figure,imshow(t_new);title('引導濾波的精細透過率圖');
%顯示導向濾波後的t圖
%寫作需要,顯示優化後的t圖
J(:,:,1) = double((pic(:,:,1) - (1-t_new).*A)./t_new);%./A_channel;
J(:,:,2) = double((pic(:,:,2) - (1-t_new).*A)./t_new);%./A_channel;
J(:,:,3) = double((pic(:,:,3) - (1-t_new).*A)./t_new);%./A_channel;
figure;
imshow(J);
title('去霧結果');
bi=1.5;
%R亮度增加
rr=double(J(:,:,1)*255);
gg=double(J(:,:,2)*255);
bb=double(J(:,:,3)*255);
[U,S,V] = svd(rr); %對圖像SVD分解
S=bi*S;%對SVD分解後的S進行比例增大
Ar=U*S*V';%svd恢復
%G亮度增加
[U,S,V] = svd(gg);
S=bi*S;
Ag=U*S*V';
%B亮度增加
[U,S,V] = svd(bb);
S=bi*S;
Ab=U*S*V';
res=cat(3,Ar,Ag,Ab);
figure
imshow(uint8(res),[]);title('SVD亮度增強');
figure
res2=cat(3,imadjust(uint8(Ar)),imadjust(uint8(Ag)),imadjust(uint8(Ab)));
imshow(uint8(res2));
title('SVD增強後拉伸');
原圖
去霧以後的圖