OpenCV——去雾
这是一个简化的实现算法,完整的算法请参考:
Single Image Haze Removal Using Dark Channel Prior ——CVPR 2009
// define head function #ifndef PS_ALGORITHM_H_INCLUDED #define PS_ALGORITHM_H_INCLUDED #include <iostream> #include <string> #include "cv.h" #include "highgui.h" #include "cxmat.hpp" #include "cxcore.hpp" using namespace std; using namespace cv; void Show_Image(Mat&, const string &); #endif // PS_ALGORITHM_H_INCLUDED #include "PS_Algorithm.h" void Dark_Channel(Mat& src, Mat& dst, int Block_size); double Atmosperic_Light(Mat& J_dark, Mat& Img); void Recove_Img(Mat& src, Mat& dst, Mat& T, float Th, float A); int main(void) { Mat Img; Img=imread("5.jpg"); Mat D_Img(Img.size(), CV_32FC3); Img.convertTo(D_Img, CV_32FC3); Mat Dark_Img(D_Img.size(), CV_32FC1); imshow("Img", Img); int Block_size=3; Dark_Channel(D_Img, Dark_Img, Block_size); float A=0; A=Atmosperic_Light(Dark_Img, D_Img); float W=0.9; Mat T(D_Img.size(), CV_32FC1); T=1-W/A*Dark_Img; //imshow("Img", T); float Th=0.35; Mat Img_out(D_Img.size(), CV_32FC3); Recove_Img(D_Img, Img_out, T, Th, A); Img_out/=255; imshow("Out",Img_out); waitKey(); cvDestroyAllWindows(); cout<<"All is well."<<endl; } void Dark_Channel(Mat& src, Mat& dst, int Block_size) { Mat R(src.size(), CV_32FC1); Mat G(src.size(), CV_32FC1); Mat B(src.size(), CV_32FC1); Mat m_array[]={R,G,B}; cv::split(src, m_array); int t=0; t=(Block_size-1)/2; Mat a1(Block_size, Block_size, CV_32FC1); Mat a2(Block_size, Block_size, CV_32FC1); Mat a3(Block_size, Block_size, CV_32FC1); double min_a1=0; double min_a2=0; double min_a3=0; double min_value=0; for(int i=t; i<dst.rows-t; i++) { for(int j=t; j<dst.cols-t; j++) { a1=R(Range(i-t,i+t+1), Range(j-t,j+t+1)); a2=G(Range(i-t,i+t+1), Range(j-t,j+t+1)); a3=B(Range(i-t,i+t+1), Range(j-t,j+t+1)); cv::minMaxLoc(a1, &min_a1,NULL,NULL,NULL); cv::minMaxLoc(a2, &min_a2,NULL,NULL,NULL); cv::minMaxLoc(a3, &min_a3,NULL,NULL,NULL); min_value=min(min_a1, min_a2); min_value=min(min_a3, min_value); dst.at<float>(i,j)=(float)min_value; } } dst(Range(0,t), Range::all())=dst(Range(t,2*t), Range::all()); dst(Range(dst.rows-t,dst.rows), Range::all())= dst(Range(dst.rows-(2*t),dst.rows-t), Range::all()); dst(Range::all(), Range(0,t))=dst(Range::all(),Range(t,2*t)); dst(Range::all(),Range(dst.cols-t,dst.cols))= dst(Range::all(), Range(dst.cols-2*t,dst.cols-t)); } double Atmosperic_Light(Mat& J_dark, Mat& Img) { Mat M1(J_dark.size(), CV_32FC1); M1=J_dark; M1.reshape(0,1); Mat M2(1,J_dark.rows*J_dark.cols, CV_32FC1); cv::sort(M1,M2,CV_SORT_ASCENDING); int Index=J_dark.rows*J_dark.cols*0.9999; float T_value=M2.at<float>(0, Index); float value=0; float Temp_value; float r_temp, g_temp, b_temp; for(int i=0; i<Img.rows; i++) { for(int j=0; j<Img.cols; j++) { Temp_value=J_dark.at<float>(i,j); if(Temp_value>T_value) { r_temp=Img.at<Vec3f>(i,j)[0]; g_temp=Img.at<Vec3f>(i,j)[1]; b_temp=Img.at<Vec3f>(i,j)[2]; Temp_value=(r_temp+g_temp+b_temp)/3.0; value=max(value, Temp_value); } } } return value; } void Recove_Img(Mat& src, Mat& dst, Mat& T, float Th, float A) { float value=0; for(int i=0; i<src.rows; i++) { for(int j=0; j<src.cols; j++) { value=max(Th, T.at<float>(i,j)); dst.at<Vec3f>(i,j)[0]=(src.at<Vec3f>(i,j)[0]-A)/value+A; dst.at<Vec3f>(i,j)[1]=(src.at<Vec3f>(i,j)[1]-A)/value+A; dst.at<Vec3f>(i,j)[2]=(src.at<Vec3f>(i,j)[2]-A)/value+A; } } }
原图
效果图