基于暗通道优先的单幅图像去雾算法(Matlab/C++)

算法原理:

            参见论文:Single Image Haze Removal Using Dark Channel Prior  [1]

       ① 暗通道定义

     何恺明 通过对大量在户外拍摄的自然景物图片进行统计分析得出一个结论:在绝大多数非天空的局部区域里,某一些像素总会(至少一个颜色通道)具有很低的值。换言之,该区域光强度的最小值是个很小的数(趋于0)。

基于上述结论,我们定义暗通道,用公式描述,对于一幅图像J有如下式子:

 也就是说以像素点x为中心,分别取三个通道内窗口Ω内的最小值,然后再取三个通道的最小值作为像素点x的暗通道的值,如下图所示:

   

 Jc代表J的某一个颜色通道,而Ω(x)是以x为中心的一块方形区域。我们观察得出,除了天空方位,Jdark的强度总是很低并且趋近于0。如果J是户外的无雾图像,我们把Jdark称为J的暗原色,并且把以上观察得出的经验性规律称为暗原色先验。

②大气物理模型

要想从物理模型角度对有雾图像进行清晰化处理,就要了解有雾图像的物理成因,那么就要了解雾天的大气散射模型。

大气散射物理模型包含两部分,第一部分称为直接衰减项(Direct Attenuation)也称直接传播,第二部分称为大气光照(Airlight)

用公式表示如下:

   I是观测到的有雾图像,J是景物反射光强度(也就是清晰的无雾图像),A是全局大气光照强度,t用来描述光线通过介质透射到成像设备过程中没有被散射的部分,去雾的目标就是从I中复原J。那么也就是要通过I求A和t。


    方程右边的第一项J(x)t(x) 叫做直接衰减项,第二项A(1-t(x))则是大气光照。直接衰减项描述的是景物光线在透射媒介中经衰减后的部分,而大气光则是由前方散射引起的,会导致景物颜色的偏移。因为大气层可看成各向同性的,透射率t可表示为:

β为大气的散射系数,该式表明景物光线是随着景物深度d按指数衰减的。

③求解透射率t

在论文[1]中,作者给出了推导过程,这里就不再重复,其最后得到透射率t的公式如下:

Ic为输入的有雾图像,对其除以全局大气光照Ac后在利用暗通道定义公式进行求解暗通道。w(0<w<1)是雾的保留系数通常取0.95。

这里需要值得注意的是,求得的t是粗透射率图,并不能直接带入大气模型公式求解,所以需要进行细化后再处理。细化过程见⑤,Ac为全局大气光照,其求法见④。

④求解全局大气光照Ac

论文[1]中作者给出求解全局大气光照的过程如下:

1.首先对输入的有雾图像I求解其暗通道图像Jdark

2.选择暗通道Jdark内图像总像素点个数(N_imagesize)千分之一(N=N_imagesize/1000)个最亮的像素点,并记录这些像素点(x,y)坐标。

3.再根据这些点的坐标分别在原图像I的三个通道(r,g,b)内找到这些像素点并加和得到(sum_r,sum_g,sum_b).

4.Ac=[Ar,Ag,Ab]. 其中Ar=sum_r/N;   Ag=sum_g/N;   Ab=sum_b/N.

⑤细化透射率t

    作者在论文[1]中使用了软抠图(soft matting)的方法,详见论文如下:

A Closed-Form Solution to Natural Image Matting[2], 作者:Anat Levin

使用软抠图法对得到的粗透射率t~进行细化。由于这个方法时间和内存花费比较大,后来作者又使用指导性滤波器进行细化粗透射图。效果上指导性滤波要稍差于软抠图法,但在时间和内存花费上具有明显优势,因此这里我们使用指导性滤波器进行细化粗透射率t~。(注:Matlab代码中也附带软抠图法细化透射率的代码。内容见文件包)

关与指导性滤波的详细内容见论文:Guided Image Filtering [3] 作者:何恺明 

⑥求解最后清晰图像

现在,我们得到了A和t,那么带入大气模型公式:

这里,t0参数用来限定透射率t的下限值,其作用也就是在输入图像的浓雾区域保留一定的雾。

附录:

     

ReadMe.txt:

感谢论文Single Image Haze Removal Using Dark Channel Prior作者何凯明。
基于暗通道优先去雾算法的Matlab /C++ 源码为免费开源。只供研究学习使用,如果引用请注明原开发者,及出处。
Matlab版中指导性滤波的源码为原作者何凯明提供。
开发者:赵常凯(不包括Matlab版中 指导性滤波的源码)
时间:2013.8.19

       Matlab 源代码  下载 5.69MB

       C++ 源代码     下载 1.68MB

       说明:C++ 是基于 OpenCV2.2 + Qt 4.8.5 编写的,如果不匹配需要搭建 Qt+OpenCV开发环境。 如果只想查看核心源码文件,请查看Dehazor.cpp文件。

 /*--------------------------------------------------------------------------------*\

    This program is free software; permission is hereby granted to use, copy, modify,
and distribute this source code, or portions thereof, for any purpose, without fee,
subject to the restriction that the copyright notice may not be removed
or altered from any source or altered source distribution.
The software is released on an as-is basis and without any warranties of any kind.
In particular, the software is not guaranteed to be fault-tolerant or free from
failure. The author disclaims all warranties with regard to this software, any use,
and any consequent failure, is purely the responsibility of the user. Copyright (C) 2013-2016 Changkai Zhao, www.cnblogs.com/changkaizhao
\*-------------------------------------------------------------------------------*/
#include "dehazor.h" cv::Mat Dehazor::process(const cv::Mat &image)
{
int dimr=image.rows;
int dimc=image.cols; cv::Mat rawtemp;
cv::Mat refinedImage_temp;
cv::Mat output_b_temp(image.rows,image.cols,CV_32F);
cv::Mat output_g_temp(image.rows,image.cols,CV_32F);
cv::Mat output_r_temp(image.rows,image.cols,CV_32F);
cv::Mat output_temp(dimr,dimc,image.type());
rawImage.create(image.rows,image.cols,CV_8U);
refinedImage_temp.create(image.rows,image.cols,CV_32F);
rawtemp.create(image.rows,image.cols,CV_8U); float sumb=;float sumg=;float sumr=;
float Air_b; float Air_g; float Air_r;
cv::Point2i pt; int dimone=floor(dimr*dimc*0.001);
cv::Mat quantile;
quantile=cv::Mat::zeros(,dimone,CV_8U); int dx=floor(windowsize/);
// cv::Mat imagetemp;
// imagetemp.create(image.rows,image.cols,CV_32FC3); for(int j=;j<dimr;j++){
for(int i=;i<dimc;i++){
int min;
image.at<cv::Vec3b>(j,i)[] >= image.at<cv::Vec3b>(j,i)[]?
min=image.at<cv::Vec3b>(j,i)[]:
min=image.at<cv::Vec3b>(j,i)[];
if(min>=image.at<cv::Vec3b>(j,i)[])
min=image.at<cv::Vec3b>(j,i)[];
rawImage.at<uchar>(j,i)=min;
}
} for(int j=;j<dimr;j++){
for(int i=;i<dimc;i++){
int min=; int jlow=j-dx;int jhigh=j+dx;
int ilow=i-dx;int ihigh=i+dx; if(ilow<=)
ilow=;
if(ihigh>=dimc)
ihigh=dimc-;
if(jlow<=)
jlow=;
if(jhigh>=dimr)
jhigh=dimr-; for(int m=jlow;m<=jhigh;m++){
for(int n=ilow;n<=ihigh;n++){
if(min>=rawImage.at<uchar>(m,n))
min=rawImage.at<uchar>(m,n);
}
}
rawtemp.at<uchar>(j,i)=min;
}
} for(int i=;i<dimone;i++){
cv::minMaxLoc(rawtemp,,,,&pt);
sumb+= image.at<cv::Vec3b>(pt.y,pt.x)[];
sumg+= image.at<cv::Vec3b>(pt.y,pt.x)[];
sumr+= image.at<cv::Vec3b>(pt.y,pt.x)[];
rawtemp.at<uchar>(pt.y,pt.x)=;
}
Air_b=sumb/dimone;
Air_g=sumg/dimone;
Air_r=sumr/dimone; cv::Mat layb; cv::Mat Im_b;
cv::Mat layg; cv::Mat Im_g;
cv::Mat layr; cv::Mat Im_r; // create vector of 3 images
std::vector<cv::Mat> planes;
// split 1 3-channel image into 3 1-channel images
cv::split(image,planes); layb=planes[];
layg=planes[];
layr=planes[];
Im_b=planes[];
Im_g=planes[];
Im_r=planes[]; layb.convertTo(layb, CV_32F);
layg.convertTo(layg, CV_32F);
layr.convertTo(layr, CV_32F); Im_b.convertTo(Im_b, CV_32F);
Im_g.convertTo(Im_g, CV_32F);
Im_r.convertTo(Im_r, CV_32F); for (int j=; j<dimr; j++) {
for (int i=; i<dimc; i++) {
// process each pixel ---------------------
layb.at<float>(j,i)=layb.at<float>(j,i)/Air_b; layg.at<float>(j,i)=layg.at<float>(j,i)/Air_g; layr.at<float>(j,i)=layr.at<float>(j,i)/Air_r;
// end of pixel processing ----------------
} // end of line
} rawtemp.convertTo(rawtemp,CV_32F); for(int j=;j<dimr;j++){
for(int i=;i<dimc;i++){
float min;
layb.at<float>(j,i) >= layg.at<float>(j,i)?
min=layg.at<float>(j,i):
min=layb.at<float>(j,i);
if(min>=layr.at<float>(j,i))
min=layr.at<float>(j,i);
rawtemp.at<float>(j,i)=min;
}
}
for(int j=;j<dimr;j++){
for(int i=;i<dimc;i++){
float min=; int jlow=j-dx;int jhigh=j+dx;
int ilow=i-dx;int ihigh=i+dx; if(ilow<=)
ilow=;
if(ihigh>=dimc)
ihigh=dimc-;
if(jlow<=)
jlow=;
if(jhigh>=dimr)
jhigh=dimr-; for(int m=jlow;m<=jhigh;m++){
for(int n=ilow;n<=ihigh;n++){
if(min>=rawtemp.at<float>(m,n))
min=rawtemp.at<float>(m,n);
}
}
rawImage.at<uchar>(j,i)=(-(float)fog_reservation_factor*min)*;
}
} refinedImage_temp=guildedfilter_color(image,rawImage,localwindowsize,eps); for(int j=;j<dimr;j++){
for(int i=;i<dimc;i++){
if(refinedImage_temp.at<float>(j,i)<0.1)
refinedImage_temp.at<float>(j,i)=0.1;
}
} cv::Mat onemat(dimr,dimc,CV_32F,cv::Scalar()); cv::Mat air_bmat(dimr,dimc,CV_32F);
cv::Mat air_gmat(dimr,dimc,CV_32F);
cv::Mat air_rmat(dimr,dimc,CV_32F); cv::addWeighted(onemat,Air_b,onemat,,,air_bmat);
cv::addWeighted(onemat,Air_g,onemat,,,air_gmat);
cv::addWeighted(onemat,Air_r,onemat,,,air_rmat); output_b_temp=Im_b-air_bmat;
output_g_temp=Im_g-air_gmat;
output_r_temp=Im_r-air_rmat; output_b_temp=output_b_temp.mul(/refinedImage_temp,)+air_bmat;
output_g_temp=output_g_temp.mul(/refinedImage_temp,)+air_gmat;
output_r_temp=output_r_temp.mul(/refinedImage_temp,)+air_rmat; output_b_temp.convertTo(output_b_temp,CV_8U);
output_g_temp.convertTo(output_g_temp,CV_8U);
output_r_temp.convertTo(output_r_temp,CV_8U); for(int j=;j<dimr;j++){
for(int i=;i<dimc;i++){
output_temp.at<cv::Vec3b>(j,i)[]=output_b_temp.at<uchar>(j,i);
output_temp.at<cv::Vec3b>(j,i)[]=output_g_temp.at<uchar>(j,i);
output_temp.at<cv::Vec3b>(j,i)[]=output_r_temp.at<uchar>(j,i);
}
} cv::Mat nom_255(dimr,dimc,CV_32F,cv::Scalar()); cv::Mat ref_temp(dimr,dimc,CV_32F);
ref_temp=refinedImage_temp;
ref_temp=ref_temp.mul(nom_255,);
ref_temp.convertTo(refinedImage,CV_8U); return output_temp;
}
cv::Mat Dehazor::boxfilter(cv::Mat &im, int r)
{
//im is a CV_32F type mat [0,1] (normalized)
//output is the same size to im; int hei=im.rows;
int wid=im.cols;
cv::Mat imDst;
cv::Mat imCum; imDst=cv::Mat::zeros(hei,wid,CV_32F);
imCum.create(hei,wid,CV_32F); //cumulative sum over Y axis
for(int i=;i<wid;i++){
for(int j=;j<hei;j++){
if(j==)
imCum.at<float>(j,i)=im.at<float>(j,i);
else
imCum.at<float>(j,i)=im.at<float>(j,i)+imCum.at<float>(j-,i);
}
} //difference over Y axis
for(int j=;j<=r;j++){
for(int i=;i<wid;i++){
imDst.at<float>(j,i)=imCum.at<float>(j+r,i);
}
}
for(int j=r+;j<=hei-r-;j++){
for(int i=;i<wid;i++){
imDst.at<float>(j,i)=imCum.at<float>(j+r,i)-imCum.at<float>(j-r-,i);
}
}
for(int j=hei-r;j<hei;j++){
for(int i=;i<wid;i++){
imDst.at<float>(j,i)=imCum.at<float>(hei-,i)-imCum.at<float>(j-r-,i);
}
} //cumulative sum over X axis
for(int j=;j<hei;j++){
for(int i=;i<wid;i++){
if(i==)
imCum.at<float>(j,i)=imDst.at<float>(j,i);
else
imCum.at<float>(j,i)=imDst.at<float>(j,i)+imCum.at<float>(j,i-);
}
}
//difference over X axis
for(int j=;j<hei;j++){
for(int i=;i<=r;i++){
imDst.at<float>(j,i)=imCum.at<float>(j,i+r);
}
}
for(int j=;j<hei;j++){
for(int i=r+;i<=wid-r-;i++){
imDst.at<float>(j,i)=imCum.at<float>(j,i+r)-imCum.at<float>(j,i-r-);
}
}
for(int j=;j<hei;j++){
for(int i=wid-r;i<wid;i++){
imDst.at<float>(j,i)=imCum.at<float>(j,wid-)-imCum.at<float>(j,i-r-);
}
} return imDst;
}
cv::Mat Dehazor::guildedfilter_color(const cv::Mat &Img, cv::Mat &p, int r, float &epsi)
{ int hei=p.rows;
int wid=p.cols; cv::Mat matOne(hei,wid,CV_32F,cv::Scalar());
cv::Mat N; N=boxfilter(matOne,r); cv::Mat mean_I_b(hei,wid,CV_32F);
cv::Mat mean_I_g(hei,wid,CV_32F);
cv::Mat mean_I_r(hei,wid,CV_32F);
cv::Mat mean_p(hei,wid,CV_32F); cv::Mat Ip_b(hei,wid,CV_32F);
cv::Mat Ip_g(hei,wid,CV_32F);
cv::Mat Ip_r(hei,wid,CV_32F);
cv::Mat mean_Ip_b(hei,wid,CV_32F);
cv::Mat mean_Ip_g(hei,wid,CV_32F);
cv::Mat mean_Ip_r(hei,wid,CV_32F);
cv::Mat cov_Ip_b(hei,wid,CV_32F);
cv::Mat cov_Ip_g(hei,wid,CV_32F);
cv::Mat cov_Ip_r(hei,wid,CV_32F); cv::Mat II_bb(hei,wid,CV_32F);
cv::Mat II_gg(hei,wid,CV_32F);
cv::Mat II_rr(hei,wid,CV_32F);
cv::Mat II_bg(hei,wid,CV_32F);
cv::Mat II_br(hei,wid,CV_32F);
cv::Mat II_gr(hei,wid,CV_32F); cv::Mat var_I_bb(hei,wid,CV_32F);
cv::Mat var_I_gg(hei,wid,CV_32F);
cv::Mat var_I_rr(hei,wid,CV_32F);
cv::Mat var_I_bg(hei,wid,CV_32F);
cv::Mat var_I_br(hei,wid,CV_32F);
cv::Mat var_I_gr(hei,wid,CV_32F); cv::Mat layb;
cv::Mat layg;
cv::Mat layr;
cv::Mat P_32; // create vector of 3 images
std::vector<cv::Mat> planes;
// split 1 3-channel image into 3 1-channel images
cv::split(Img,planes); layb=planes[];
layg=planes[];
layr=planes[]; layb.convertTo(layb, CV_32F);
layg.convertTo(layg, CV_32F);
layr.convertTo(layr, CV_32F); p.convertTo(P_32,CV_32F);
cv::Mat nom_255(hei,wid,CV_32F,cv::Scalar()); layb=layb.mul(/nom_255,);
layg=layg.mul(/nom_255,);
layr=layr.mul(/nom_255,);
P_32=P_32.mul(/nom_255,); cv::Mat mean_I_b_temp=boxfilter(layb,r);
cv::Mat mean_I_g_temp=boxfilter(layg,r);
cv::Mat mean_I_r_temp=boxfilter(layr,r);
cv::Mat mean_p_temp=boxfilter(P_32,r); mean_I_b=mean_I_b_temp.mul(/N,);
mean_I_g=mean_I_g_temp.mul(/N,);
mean_I_r=mean_I_r_temp.mul(/N,);
mean_p=mean_p_temp.mul(/N,); Ip_b=layb.mul(P_32,);
Ip_g=layg.mul(P_32,);
Ip_r=layr.mul(P_32,); cv::Mat mean_Ip_b_temp=boxfilter(Ip_b,r);
cv::Mat mean_Ip_g_temp=boxfilter(Ip_g,r);
cv::Mat mean_Ip_r_temp=boxfilter(Ip_r,r); mean_Ip_b=mean_Ip_b_temp.mul(/N,);
mean_Ip_g=mean_Ip_g_temp.mul(/N,);
mean_Ip_r=mean_Ip_r_temp.mul(/N,); cov_Ip_b=mean_Ip_b-mean_I_b.mul(mean_p,);
cov_Ip_g=mean_Ip_g-mean_I_g.mul(mean_p,);
cov_Ip_r=mean_Ip_r-mean_I_r.mul(mean_p,); // variance of I in each local patch: the matrix Sigma in Eqn (14).
// Note the variance in each local patch is a 3x3 symmetric matrix:
// bb, bg, br
// Sigma = bg, gg, gr
// br, gr, rr
II_bb=layb.mul(layb,);
II_gg=layg.mul(layg,);
II_rr=layr.mul(layr,);
II_bg=layb.mul(layg,);
II_br=layb.mul(layr,);
II_gr=layg.mul(layr,); cv::Mat bb_box=boxfilter(II_bb,r);
cv::Mat gg_box=boxfilter(II_gg,r);
cv::Mat rr_box=boxfilter(II_rr,r);
cv::Mat bg_box=boxfilter(II_bg,r);
cv::Mat br_box=boxfilter(II_br,r);
cv::Mat gr_box=boxfilter(II_gr,r); var_I_bb=bb_box.mul(/N,)-mean_I_b.mul(mean_I_b);
var_I_gg=gg_box.mul(/N,)-mean_I_g.mul(mean_I_g);
var_I_rr=rr_box.mul(/N,)-mean_I_r.mul(mean_I_r);
var_I_bg=bg_box.mul(/N,)-mean_I_b.mul(mean_I_g);
var_I_br=br_box.mul(/N,)-mean_I_b.mul(mean_I_r);
var_I_gr=gr_box.mul(/N,)-mean_I_g.mul(mean_I_r); cv::Mat a_b(hei,wid,CV_32F);
cv::Mat a_g(hei,wid,CV_32F);
cv::Mat a_r(hei,wid,CV_32F); cv::Mat b(hei,wid,CV_32F);
cv::Mat sigma(,,CV_32F,cv::Scalar());
cv::Mat inv_sigma(,,CV_32F); for(int j=;j<hei;j++){
for(int i=;i<wid;i++){
sigma.at<float>(,)=var_I_rr.at<float>(j,i)+epsi;
sigma.at<float>(,)=var_I_gr.at<float>(j,i);
sigma.at<float>(,)=var_I_br.at<float>(j,i);
sigma.at<float>(,)=var_I_gr.at<float>(j,i);
sigma.at<float>(,)=var_I_br.at<float>(j,i);
sigma.at<float>(,)=var_I_gg.at<float>(j,i)+epsi;
sigma.at<float>(,)=var_I_bb.at<float>(j,i)+epsi;
sigma.at<float>(,)=var_I_bg.at<float>(j,i);
sigma.at<float>(,)=var_I_bg.at<float>(j,i);
inv_sigma=sigma.inv(cv::DECOMP_LU); a_r.at<float>(j,i)=cov_Ip_r.at<float>(j,i)*inv_sigma.at<float>(,)+
cov_Ip_g.at<float>(j,i)*inv_sigma.at<float>(,)+
cov_Ip_b.at<float>(j,i)*inv_sigma.at<float>(,);
a_g.at<float>(j,i)=cov_Ip_r.at<float>(j,i)*inv_sigma.at<float>(,)+
cov_Ip_g.at<float>(j,i)*inv_sigma.at<float>(,)+
cov_Ip_b.at<float>(j,i)*inv_sigma.at<float>(,);
a_b.at<float>(j,i)=cov_Ip_r.at<float>(j,i)*inv_sigma.at<float>(,)+
cov_Ip_g.at<float>(j,i)*inv_sigma.at<float>(,)+
cov_Ip_b.at<float>(j,i)*inv_sigma.at<float>(,); }
}
b=mean_p-a_b.mul(mean_I_b,)-a_g.mul(mean_I_g,)-a_r.mul(mean_I_r,); cv::Mat box_ab=boxfilter(a_b,r);
cv::Mat box_ag=boxfilter(a_g,r);
cv::Mat box_ar=boxfilter(a_r,r);
cv::Mat box_b=boxfilter(b,r);
cv::Mat q(hei,wid,CV_32F); q=box_ab.mul(layb,)+box_ag.mul(layg,)+box_ar.mul(layr,)+box_b;
q=q.mul(/N,); return q; }

dehazor.cpp

       截图:

  

 

 

基于暗通道优先算法的去雾应用(Matlab/C++)的更多相关文章

  1. 《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果(速度可实时)

    最新的效果见 :http://video.sina.com.cn/v/b/124538950-1254492273.html 可处理视频的示例:视频去雾效果 在图像去雾这个领域,几乎没有人不知道< ...

  2. paper 105: 《Single Image Haze Removal Using Dark Channel Prior》一文中图像去雾算法的原理、实现、效果及其他

    在图像去雾这个领域,几乎没有人不知道<Single Image Haze Removal Using Dark Channel Prior>这篇文章,该文是2009年CVPR最佳论文.作者 ...

  3. OpenCV导向滤波(引导滤波)实现(Guided Filter)代码,以及使用颜色先验算法去雾

    论文下载地址:http://research.microsoft.com/en-us/um/people/jiansun/papers/GuidedFilter_ECCV10.pdf 本文主要介绍导向 ...

  4. 暗通道去雾算法的python实现

    何凯明博士的去雾文章和算法实现已经漫天飞了,我今天也就不啰里啰唆,直接给出自己python实现的完整版本,全部才60多行代码,简单易懂,并有简要注释,去雾效果也很不错. 在这个python版本中,计算 ...

  5. Retinex图像增强和暗通道去雾的关系及其在hdr色调恢复上的应用

    很多人都认为retinex和暗通道去雾是八杆子都打不着的增强算法.的确,二者的理论.计算方法都完全迥异,本人直接从二者的公式入手来简单说明一下,有些部分全凭臆想,不对之处大家一起讨论. 首先,为描述方 ...

  6. paper 100:何恺明经典去雾算法

    一:由简至美的最佳论文(作者:何恺明  视觉计算组) [视觉机器人:个人感觉学习他的经典算法固然很重要,但是他的解决问题的思路也是非常值得我们学习的] 那是2009年4月24日的早上,我收到了一封不同 ...

  7. 基于clahe的图像去雾

    基于clahe的图像去雾     通过阅读一些资料,我了解到clahe算法对图像去雾有所价值,正好opencv中有了实现,拿过来看一看.   但是现在实现的效果还是有所差异 #);    clahe] ...

  8. 纯C++去雾算法

    去雾算法 前言:经过不断的改进研究,该算法最终稳定,高效的问世了. 经过研究使该算法适应大雾环境,对该算法的内存优化,可以实时的高效的执行. 一.实时视频: watermark/2/text/aHR0 ...

  9. 一种可实时处理 O(1)复杂度图像去雾算法的实现。

    在我博文的一系列的文章,有不少算法都于去雾有关,比如限制对比度自适应直方图均衡化算法原理.实现及效果.局部自适应自动色阶/对比度算法在图像增强上的应用这两个增强算法都有一定的去雾能力,而最直接的就是& ...

随机推荐

  1. netlink优势

    netlink相对其他应用进程和内核之间通信的方式(ioctrl或者系统文件等方式),全双工,可由内核发起,应用进程可用epoll监听,而其他方式只能由应用进程发起. 顺便记下隧道,隧道可以通过在ip ...

  2. webpack 配置文件

    现如今,webpack非常的受欢迎,比较火的几款js框架都推荐使用webpack来构建项目,而webpack也确实非常强大,但是配置webpack缺常常带来很多问题,接下来就写一下我自己遇到的一些坑. ...

  3. .net MVC中异常日志

    在日常工作中,我们有些项目可能进入了维护期,但是项目可能存在一些潜伏较深的bug导致我们在测试阶段并未发现,那么错误日志记录为我们的项目维护起着重要的作用.记录系统日志的方法如下 1.在系统根目录建立 ...

  4. IE浏览器下异步请求的缓存问题

    问题: 在做即时通讯时,需要提示用户有几条未读的提醒,这个是(如果有新的提示消息立马在浏览器无刷新提示)即时获取的.但我们的做法是,当用户点击未读信息进入到信息显示页面时重新获取下未读的提醒:但是在I ...

  5. IE7 自动为文件路径添加域名

    对于图片等文件的路径,一般在同一个域名下的文件都会使用相对路径,但如果使用JS获取文件的路径浏览器获取到的路径都是相对路径,但IE7会自动为路径添加域名变成绝对路径... IE7下图片路径,在文件相对 ...

  6. Linux kernel4.4.12 添加make menuconfig 可选项

    Linux kernel 源码添加可选项 闲来无事,顺便记录一篇在Linux kernel make menuconfig 内添加一个可选项. 说不定将来就要用到这个东西呢. linux kernel ...

  7. Visual Studio 默认保存为UTF8编码

    Visual Studio (中文版)默认保存的文本文件是GB2312编码(代码页936)的,默认的行尾(End of line)是CRLF的. 如果仅仅是在windows下开发问题也不大,但是涉及到 ...

  8. java 基础导航

    ecplise 常用快捷键 java notepad++ java封装好处和原则 java1 基本概述和java环境变量配置 java2 基本概念介绍和基本关键字.基本数据类型 java3 基本流程语 ...

  9. Python之美--Decorator深入详解

    转自:http://www.cnblogs.com/SeasonLee/archive/2010/04/24/1719444.html 一些往事 在正式进入Decorator话题之前,请允许我讲一个小 ...

  10. MySQL 5.6 OOM 问题解决分享【转】

    本文来自:杨德华的原创分享 | MySQL 5.6 OOM 问题解决分享 延伸阅读:Linux的内存回收和交换 当遇到应用程序OOM的时候,大多数时候只能用头疼来形容,应用程序还可以通过引流来临时重启 ...