http://blog.csdn.net/cfqcfqcfqcfqcfq/article/details/52870799
导向滤波算法基本已取得不错的效果,保留完整细节信息。观察去雾后的图像其亮度要比原图要低。那是因为物体光线的亮度通常不及大气光线。看一些论文里提到了自动色阶算法。查阅资料发现其就是RGB三通道进行灰度拉伸。
实现过程中使用opencv的通道分离和和合并函数并结合普通的灰度拉伸函数就可以实现 RGB三通道灰度拉伸
实现代码:
- int main()
- {
-
- cv::Mat channels[3];
- split(deFog1,channels);
- for(int c=0;c<3;c++)
- channels[c]= grayStretch(channels[c],0.001,0.5);
- merge(channels,3,deFog1);
- imshow("autoLevels",deFog1);
-
- }
-
-
-
-
-
- cv::Mat grayStretch(cv::Mat src,double lowcut,double highcut)
- {
-
-
- const int bins = 256;
- int hist_size=bins;
- float range[]={0,255};
- const float* ranges[]={range};
- MatND desHist;
- int channels=0;
-
- calcHist(&src,1,&channels,Mat(),desHist,1,&hist_size,ranges,true,false);
-
-
-
- int pixelAmount=src.rows*src.cols;
- float Sum=0;
- int minValue,maxValue;
-
- for(int i=0;i<bins;i++)
- {
- Sum=Sum+desHist.at<float>(i);
- if(Sum>=pixelAmount*lowcut*0.01)
- {
- minValue=i;
- qDebug()<<"minValue"<<minValue;
- break;
- }
- }
-
-
- Sum=0;
- for(int i=bins-1;i>=0;i--)
- {
- Sum=Sum+desHist.at<float>(i);
- if(Sum>=pixelAmount*highcut*0.01)
- {
- maxValue=i;
- qDebug()<<"maxValue"<<maxValue;
- break;
- }
- }
-
-
-
- Mat dst=src;
-
- if(minValue>maxValue)
- return src;
-
- for(int i=0;i<src.rows;i++)
- for(int j=0;j<src.cols;j++)
- {
- if(src.at<uchar>(i,j)<minValue)
- dst.at<uchar>(i,j)=0;
- if(src.at<uchar>(i,j)>maxValue)
- dst.at<uchar>(i,j)=255;
- else
- {
-
- double pixelValue=((src.at<uchar>(i,j)-minValue)/
- (double)(maxValue-minValue))*255;
- dst.at<uchar>(i,j)=(int)pixelValue;
- }
- }
-
-
- return dst;
- }
结果:
注意事项:
1、opencv的通道分离函数spilt()和merge() 其channels变量类型可以去数组或vector容器两种类型。但实际操作时 使用vector容器会提示指针访问越界的错误。参考文献一给出解释是说容器初始化使没有分配其容量。但我尝试reszie(3)仍然不行 所以就改用数组。在使用数组类型时候 merge函数标签应该为merge(Mat *mv,size_t cpunt ,OutputArray dst);必须要指明第二个参数 通道个数。
2、graystrech函数中第二个参数值要取得小一点,第三个参数可以适当大一点。因为图像是整体偏暗 所以当然是希望往高亮度范围内拉伸,而不是往低亮度方向拉伸
图像去雾方法总结:
1、不管是暗原色先验还是导向滤波,当图像中出现大面积天等白色物体区域去雾效果都不理想。因为白色物体暗原色先验的条件是基本不成立的。
2、并不是一张图像上的雾能去除,向下面这张图:
基本上图像近处的物体轮廓比较清洗 能够分出前景(一层薄雾)和目标。在往远处看 基本上是一片白 除了两个车灯其他的根本分不出前景和目标。
远景那一块肉眼都看不到有没有物体 所以很难通过现有算法让计算机帮你准确分离出目标。
所以我理解的图像去雾基本上是指那种蒙着的一层薄雾,那种没有能见度的大雾个人感觉现有算法肯定去除不了。
参考文献:
1、自动色阶
2、spilt 报错