【原文:http://blog.csdn.net/abcjennifer/article/details/6662706】
真正瞭解了什麼叫最簡單的就是最美好的
真正的好文章不需要大堆公式堆積顯得充實,而是最最平實的思想!
這篇文章的:原文PDF、PPT。感興趣的可以瞭解一下。
這篇文章的目的就是以最簡單的思路將影象達到去霧效果。用Matlab編了一下,效果圖特別好啊哈:
下面是摘錄的:
CVPR的中文名是計算機視覺與模式識別會議,是計算機視覺領域最頂尖的國際 會議之一。09年的CVPR共收到約1450篇投稿,其中393篇文章被接收,接收率為26%。只有一篇文章被選為今年的最佳論文。這是CVPR創立25年 以來首次由中國人獲得這個獎項。
2010年的結果也已經出來了,一共1724篇文章,CVPR2010 Paper Acceptance Rates: 78 papers were accepted for ORAL Presentation (4.5%).384 papers were accepted for POSTER Presentation (22.3%).
下面是作者的感想摘錄,值得借鑑:
這篇論文研究的問題是影象的去霧技術,它可 以還原影象的顏色和能見度,同時也能利用霧的濃度來估計物體的距離,這些在計算機視覺上都有重要應用(例如三維重建,物體識別)。但是之前人們還沒找到簡 單有效的方法來達到這個目的。在這篇論文裡,我們找到了一個非常簡單的,甚至說令人驚訝統計規律,並提出了有效的去霧方法。
與之前的方法不同,我們把注意力放到了無霧影象的統計特徵上。我們發 現,在無霧影象中,每一個區域性區域都很有可能會有陰影,或者是純顏色的東西,又或者是黑色的東西。因此,每一個區域性區域都很有可能有至少一個顏色通道會有 很低的值。我們把這個統計規律叫做Dark Channel Prior。直觀來說,Dark Channel Prior認為每一個區域性區域都總有一些很暗的東西。這個規律很簡單,但在我們研究的去霧問題上卻是本質的基本規律。
由於霧總是灰白色的,因此一旦影象受到霧的影響,那麼這些本來應該很暗 的東西就會變得灰白。不僅如此,根據物理上霧的形成公式,我們還能根據這些東西的灰白程度來判斷霧的濃度。因此,我們提出的Dark Channel Prior能很有效地去除霧的影響,同時利用物的濃度來估算物體的距離。
大道之行在於簡
我們這篇文章的三個審稿人都給出了最高的評分。他們認為我們的方法簡單 而有效。其中一位評委說,Dark Channel Prior的想法聽起來很不可思議,但我們卻證明了其真實性。另一位評委認為很少有文章能夠用如此簡單的方法使實驗結果獲得如此大的提升。還有一位評委甚 至親自實現了我們的方法並確認其可行。孫劍說閱讀這樣的評審結果是一件讓人快樂的事情。而湯老師認為,這篇文章的成功在於三個方面。第一,方法非常簡單; 第二,對於一個很困難的問題,給出了很好的結果;第三,發現了一個基本的自然規律並且應用在實際的問題中。在邁阿密的演講結束後,觀眾也給予了很高的評
價。他們跟我說,這是這次CVPR上最有趣的一個演講。
一位與會的研究員說,最好的idea,往往就是那些看起來很簡單,但說 出來大家都會覺得怎麼沒有人想到過的idea。而我們的idea正好就符合了這一點。我們論文摘要的第一句話是這麼說的,“我們提出了一個簡單而有效的方 法”。或許,這就是對我們這次工作最好的概括——簡單的,就是美的。
程式碼如下:
1.MATLAB
-
%=========================================================%
-
%呼叫規則:(有霧時呼叫,否則不呼叫)
-
%實際操作時,according to experiments:
-
%percent=under_50/total
-
%percent<0.1%,取w=0.6
-
%percent>0.1%&&percent<1%,取w=0.45
-
%percenet>1%&&percent<2%,取w=0.3
-
%else not use haze-free-adjust
-
%有霧:繪製出的直方圖<50的部分<1%
-
%最後控制檯還會輸出原圖中under_50畫素點所佔比例
-
%=========================================================%
-
close all
-
clear all
-
clc
-
blockSize=15; %每個block為15個畫素
-
w0=0.6;
-
t0=0.1;
-
% A=200;
-
I=imread('D:\畢業設計\Images\pic_loc\1870575550604291415.jpg');
-
%I=imread('C:\Users\Zrq\Desktop\同濟.jpg');
-
h = figure;
-
%set(gcf,'outerposition',get(0,'screensize'));%獲得SystemScreenSize 傳遞給當前影象控制程式碼gcf的outerposition屬性
-
subplot(321)%表示3(行數)*2(列數)的影象,1代表所畫圖形的序號
-
imshow(I);
-
title('Original Image');
-
-
-
subplot(323);
-
grayI=rgb2gray(I);
-
imshow(grayI,[]);
-
title('原影象灰度圖')
-
-
subplot(324);
-
imhist(grayI,64);
-
-
%統計<50的畫素所佔的比例
-
%%%%%%%%%%%%%%%%%%%%%%
-
[COUNT x]=imhist(grayI);
-
under_50=0;
-
for i=0:50
-
under_50=under_50+COUNT(x==i);
-
end
-
under_50
-
total=size(I,1)*size(I,2)*size(I,3);
-
percent=under_50/total
-
%%%%%%%%%%%%%%%%%%%%%%
-
-
if(percent>0.02)
-
error('This image need not Haze-Free-Proprocessing.');
-
else if(percent<0.001)
-
w=0.6;
-
else if (percent>0.01)
-
w=0.3;
-
else
-
w=0.45;
-
end
-
end
-
end
-
-
[h,w,s]=size(I);
-
min_I=zeros(h,w);
-
-
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)))
-
dark_channel=double(dark_I);
-
t=1-w0*(dark_channel/Max_dark_channel);
-
-
T=uint8(t*255);
-
-
t=max(t,t0);
-
-
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
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(322)
-
imshow(J);
-
imwrite(J,'tj2.jpg');
-
title('Haze-Free Image:');
-
-
subplot(325);
-
grayJ=rgb2gray(J);
-
imshow(grayJ,[]);
-
title('去霧後灰度圖')
-
-
subplot(326);
-
imhist(grayJ,64);
2.OPENCV
-
-
-
char tbarname1[] = "調節block";
-
-
char tbarname2[] = "調節w";
-
-
int block=5;
-
int w1=80;
-
double w;
-
IplImage *dst=NULL;
-
-
IplImage *quw(IplImage *src,int block,double w)
-
{
-
-
IplImage *dst1=NULL;
-
IplImage *dst2=NULL;
-
IplImage *dst3=NULL;
-
IplImage *imgroi1;
-
-
IplImage *imgroi2;
-
-
IplImage *imgroi3;
-
-
IplImage *roidark;
-
-
IplImage *dark_channel=NULL;
-
-
IplImage *toushelv=NULL;
-
-
-
-
IplImage *j1=NULL;
-
IplImage *j2=NULL;
-
IplImage *j3=NULL;
-
-
IplImage *dst=NULL;
-
-
CvRect ROI_rect;
-
-
-
dst1=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);
-
dst2=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);
-
dst3=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);
-
-
-
imgroi1=cvCreateImage(cvSize(block,block),IPL_DEPTH_8U,1);
-
imgroi2=cvCreateImage(cvSize(block,block),IPL_DEPTH_8U,1);
-
imgroi3=cvCreateImage(cvSize(block,block),IPL_DEPTH_8U,1);
-
roidark=cvCreateImage(cvSize(block,block),IPL_DEPTH_8U,1);
-
-
-
j1=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);
-
j2=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);
-
j3=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);
-
-
-
dark_channel=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);
-
-
toushelv=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,1);
-
-
dst=cvCreateImage(cvSize(src->width,src->height),IPL_DEPTH_8U,3);
-
-
cvSplit(src,dst1,dst2,dst3,NULL);
-
-
ROI_rect.width=block;
-
ROI_rect.height=block;
-
ROI_rect.x=0;
-
ROI_rect.y=0;
-
-
-
int i;
-
int j;
-
double min1=0;
-
double max1=0;
-
double min2=0;
-
double max2=0;
-
double min3=0;
-
double max3=0;
-
double min=0;
-
CvScalar value;
-
for(i=0;i<src->width/block;i++)
-
{ for(j=0;j<src->height/block;j++)
-
{
-
-
cvSetImageROI(dst1,ROI_rect);
-
cvCopy(dst1,imgroi1,NULL);
-
cvMinMaxLoc(imgroi1,&min1,&max1,NULL,NULL);
-
cvSetImageROI(dst2,ROI_rect);
-
cvCopy(dst2,imgroi2,NULL);
-
cvMinMaxLoc(imgroi2,&min2,&max2,NULL,NULL);
-
cvSetImageROI(dst3,ROI_rect);
-
cvCopy(dst3,imgroi3,NULL);
-
cvMinMaxLoc(imgroi3,&min3,&max3,NULL,NULL);
-
-
if(min1<min2)
-
min=min1;
-
else
-
min=min2;
-
if(min>min3)
-
min=min3;
-
value=cvScalar(min,min,min,min);
-
-
cvSetImageROI(dark_channel,ROI_rect);
-
cvSet(roidark,value,NULL);
-
cvCopy(roidark,dark_channel,NULL);
-
-
cvResetImageROI(dst1);
-
cvResetImageROI(dst2);
-
cvResetImageROI(dst3);
-
cvResetImageROI(dark_channel);
-
-
ROI_rect.x=block*i;
-
ROI_rect.y=block*j;
-
}
-
}
-
-
cvSaveImage("f:/dark_channel_prior.jpg",dark_channel);
-
-
double min_dark;
-
double max_dark;
-
CvPoint min_loc;
-
CvPoint max_loc;
-
cvMinMaxLoc(dark_channel,&min_dark,&max_dark,&min_loc,&max_loc,NULL);
-
-
ROI_rect.x=max_loc.x;
-
ROI_rect.y=max_loc.y;
-
double A_dst1;
-
double dst1_min;
-
double A_dst2;
-
double dst2_min;
-
double A_dst3;
-
double dst3_min;
-
cvSetImageROI(dst1,ROI_rect);
-
-
cvCopy(dst1,imgroi1,NULL);
-
cvMinMaxLoc(imgroi1,&dst1_min,&A_dst1,NULL,NULL);
-
cvSetImageROI(dst2,ROI_rect);
-
cvCopy(dst2,imgroi2,NULL);
-
cvMinMaxLoc(imgroi2,&dst2_min,&A_dst2,NULL,NULL);
-
cvSetImageROI(dst3,ROI_rect);
-
cvCopy(dst3,imgroi3,NULL);
-
cvMinMaxLoc(imgroi3,&dst3_min,&A_dst3,NULL,NULL);
-
-
-
int k;
-
int l;
-
CvScalar m;
-
CvScalar n;
-
-
for(k=0;k<src->height;k++)
-
{
-
for(l=0;l<src->width;l++)
-
{
-
m=cvGet2D(dark_channel,k,l);
-
n=cvScalar(255-w*m.val[0]);
-
-
cvSet2D(toushelv,k,l,n);
-
}
-
}
-
cvSaveImage("f:/toushelv.jpg",toushelv);
-
-
-
int p,q;
-
double tx;
-
double jj1,jj2,jj3;
-
CvScalar ix,jx;
-
for(p=0;p<src->height;p++)
-
{
-
for(q=0;q<src->width;q++)
-
{
-
tx=cvGetReal2D(toushelv,p,q);
-
tx=tx/255;
-
if(tx<0.1)
-
tx=0.1;
-
ix=cvGet2D(src,p,q);
-
jj1=(ix.val[0]-A_dst1)/tx+A_dst1;
-
jj2=(ix.val[1]-A_dst2)/tx+A_dst2;
-
jj3=(ix.val[2]-A_dst3)/tx+A_dst3;
-
jx=cvScalar(jj1,jj2,jj3,0.0);
-
cvSet2D(dst,p,q,jx);
-
}
-
}
-
cvSaveImage("f:/removed_haze.jpg",dst);
-
-
-
cvReleaseImage(&dst1);
-
cvReleaseImage(&dst2);
-
cvReleaseImage(&dst3);
-
cvReleaseImage(&imgroi1);
-
cvReleaseImage(&imgroi2);
-
cvReleaseImage(&imgroi3);
-
cvReleaseImage(&roidark);
-
cvReleaseImage(&dark_channel);
-
cvReleaseImage(&toushelv);
-
cvReleaseImage(&j1);
-
cvReleaseImage(&j2);
-
cvReleaseImage(&j3);
-
return dst;
-
}
-
-
IplImage *source;
-
void on_trackbar1(int h)
-
{
-
dst=quw(source,block,w);
-
cvShowImage("目的影象",dst);
-
-
}
-
void on_trackbar2(int h)
-
{
-
w=(double)w1/100;
-
dst=quw(source,block,w);
-
cvShowImage("目的影象",dst);
-
-
}
-
-
void CCVMFCView::OnImageHazefree()
-
{
-
imageClone(workImg,&source);
-
-
cvFlip(source);
-
-
cvNamedWindow("目的影象",CV_WINDOW_AUTOSIZE);
-
cvShowImage("目的影象",source);
-
cvCreateTrackbar(tbarname1, "目的影象", &block, 15, on_trackbar1);
-
cvCreateTrackbar(tbarname2, "目的影象", &w1, 100, on_trackbar2);
-
cvWaitKey(0);
-
-
cvReleaseImage(&source);
-
-
cvDestroyWindow("目的影象");
-
cvDestroyWindow("有霧影象");
-
cvFlip(dst);
-
m_dibFlag=imageReplace(dst,&workImg);
-
Invalidate();
-
}