研究去雾算法有一段时间了,看了很多论文,最终还是觉得何凯明的去雾相关论文最靠谱:
何凯明主页:http://kaiminghe.com/
暗通道透雾:Single Image Haze Removal
有些图像处理后感觉自己实现的透雾效果不如作者的效果好。
造成此差异的原因大概是:
①自己的实现有不到位的地方。
②透雾处理后的曝光方式不一样,由于暗通道方法透雾后会出现图像偏暗的情况,所以需要曝光处理,但作者的论文中没有提到他自己用了什么方法。
另外,我在实现过程中其中传播图的细化用的是Guided Image Filtering,也试过均值等其他滤波方式,但是很明显引导滤波的效果更好,原因就是滤波后边缘效应,据说双边滤波的保边效果不错,但是自己没有实现过,大致了解了一下双边滤波的快速算法,大概估计其流程比引导滤波会更耗时,加上自己较忙,所以也没有继续研究了,希望有实现双边滤波的朋友曝一下处理效果及处理时间。
此文没有介绍关于暗通道的一些流程,但是博客园就不止一篇文章介绍其去雾算法,所以偷个懒直接加个链接,感兴趣的朋友推荐看看以下文章以及下面的评论。
http://www.cnblogs.com/Imageshop/p/3281703.html;
http://www.cnblogs.com/celerychen/archive/2013/03/23/2976792.html;
另外我现在还存在以下问题:
①目前我实现过的透雾算法都有其自身的缺陷,何凯明的算法也有处理效果不理想的情况。
就目前自己实现的透雾算法中,还没有一种能够适应各种雨雾霾图像的处理,有研究图像透雾
的朋友欢迎发表你的看法及心得。
②虽然引导滤波的效果用于传输图的细化效果较好,但是实时性远远不够,
单单引导滤波而言,自己期望能达到的效率是,在配置一般的电脑上能够实时处理(20ms以内)720P灰度图像。
希望做过并行处理:GPU加速、异构编程、或FPGA等朋友报一下你们有没有处理过一些图像滤波(均值、中值、双边、甚至引导滤波等等)的加速。能加速到什么程度,这一点很重要。如果我要做相关加速工作需要了解哪些知识,可否推荐一些资料。
下面是我这里的处理效果【如果显示器偏小,请按 “Ctrl+鼠标滚轮” 缩小页面进行查看】
这些图像是经过“暗通道透雾”+“后期曝光处理”两步完成的。曝光处理用的方法简单所以效率很高。
关于曝光补偿,感兴趣的朋友可以看下下面贴出的代码。如果你有更好的曝光处理方法,能告之当然更好。
如果发现你的实现出来效果更好,请曝图,我这里好做参考继续改进,当然,能告之方法自然更好。
不好意思:全部代码及应用不方便上传,下面贴出Gama校正调整图像亮度的代码,请参考
//图像的伽马矫正 void CreateGamaTab(unsigned char* gamaTab, float gama) { float fT = 0; for(int i=0; i<256; i++) { fT = (i+0.5f)/255; fT = (float)pow(fT, gama); int iT = fT*255; if(iT>255) { iT = 255; } else if(iT<0) { iT = 0; } gamaTab[i] = iT; } } //图像亮度调整 void IMG_GamaCorrection( unsigned char* pSrc, //源图像数据 unsigned char* pDst, //目标图像数据,如果为NULL,会直接改变pSrc int width, int height, int stride, //每一行数据字节数 int iChannels, //例如 1=灰度图 3=RGB24 4=RGB32 double fGama //大致区间 0.1 - 5.0 1.0时没有变化 低于1.0变暗,高于1.0变亮 ) { //创建查找表 unsigned char GamaTab[256] = {0}; CreateGamaTab(GamaTab, 1/fGama); //*****注意这里有除1操作******* int x,y; unsigned char* pS; unsigned char* pD; if(pDst != NULL) //结果保存在pDst { if(iChannels == 1)//单通道图像 { for(y=0; y<height; y++) { pS = pSrc + y*stride; pD = pDst + y*stride; for(x=0; x<width; x++) { pD[0] = GamaTab[pS[0]]; pS+=iChannels; pD+=iChannels; } } } else//多通道彩色 { for(y=0; y<height; y++) { pS = pSrc + y*stride; pD = pDst + y*stride; for(x=0; x<width; x++) { pD[0] = GamaTab[pS[0]]; pD[1] = GamaTab[pS[1]]; pD[2] = GamaTab[pS[2]]; pS+=iChannels; pD+=iChannels; } } } } else //直接改变原图 { if(iChannels == 1)//单通道图像 { for(y=0; y<height; y++) { pS = pSrc + y*stride; for(x=0; x<width; x++) { pS[0] = GamaTab[pS[0]]; pS+=iChannels; } } } else//多通道彩色 { for(y=0; y<height; y++) { pS = pSrc + y*stride; for(x=0; x<width; x++) { pS[0] = GamaTab[pS[0]]; //gama校正 pS[1] = GamaTab[pS[1]]; //gama校正 pS[2] = GamaTab[pS[2]]; //gama校正 pS+=iChannels; } } } } }