#include "stdafx.h" #include "DarkChannelDehaze.h" DarkChannelDehaze::DarkChannelDehaze(void):block(7),w(0.9) { ROI_rect.x = 0; ROI_rect.y = 0; double min_channel1 = 0; double min_channel2 = 0; double min_channel3 = 0; double max_channel1 = 0; double max_channel2 = 0; double max_channel3 = 0; double min = 0; double A_final = 10; } DarkChannelDehaze::~DarkChannelDehaze(void) { } void DarkChannelDehaze::doDehaze( const Mat& src, Mat& dst ) { dcc.setTo(cv::Scalar::all(0)); cv::split(src, dsts); ROI_rect.width = block; ROI_rect.height = block; Mat Vm, Vop,Vnorm; uchar pixel; cv::Scalar e2x,ex2; cv::Rect meanRect; meanRect.width = 5; meanRect.height = 5; Vm.create(src.size(), CV_8UC1); Vm.setTo(cv::Scalar::all(0)); for(int i = 0;i(i,j),dsts[0].at(i,j)); pixel = min(pixel,dsts[2].at(i,j)); Vm.at(i,j) = pixel; } } Vnorm = Vm.clone(); Sobel(Vm,Vop,-1,1,1,3,1,0,BORDER_DEFAULT); Mat element = getStructuringElement(MORPH_RECT,Size(15, 15)); morphologyEx(Vm,Vnorm,MORPH_OPEN,element); normalize(Vop, Vop, 255,0,NORM_MINMAX); for(int row = 0;row(row,col) = (Vm.at(row,col)*Vop.at(row,col)+Vnorm.at(row,col)*(255-Vop.at(row,col)))/255; } } Adcc = dcc.clone(); cv::Point minloc, maxloc; cv::minMaxLoc(Adcc, &min_dark, &max_dark, &minloc, &maxloc); ROI_rect.x = maxloc.x; ROI_rect.y = maxloc.y; ROI_rect.width = block; ROI_rect.height = block; ROI_rect = ROI_rect&(cv::Rect(0, 0, src.cols, src.rows)); imgroi1 = dsts[0](ROI_rect).clone(); cv::minMaxLoc(imgroi1, &dst1_min, &A_dst1, NULL, NULL); imgroi2 = dsts[1](ROI_rect).clone(); cv::minMaxLoc(imgroi2, &dst2_min, &A_dst2, NULL, NULL); imgroi3 = dsts[2](ROI_rect).clone(); cv::minMaxLoc(imgroi3, &dst3_min, &A_dst3, NULL, NULL); if ((src.cols<=100)&&(src.rows<=100)) { double td = 20; } else { td = 120; } if(A_dst1 > A_dst2) Amax = A_dst1; else Amax = A_dst2; if(Amax > A_dst3) Amax = A_dst3; A1 = abs(Amax - A_final); if (A1 >= td) A_final = Amax; #pragma omp parallel for for (int row = 0; row < src.rows; row++) { for (int col = 0; col < src.cols; col++) { toushelv.at(row, col) = static_cast((1.0 - w * dcc.at(row, col)/A_final) * 255.0); } } int gfresize = 4; cv::resize(toushelv, dstpinghua,cv::Size(src.cols/gfresize, src.rows/gfresize)); cv::resize(src, Ihalf, cv::Size(src.cols/gfresize, src.rows/gfresize)); pinghua = guidedFilter(Ihalf, dstpinghua, 7, 0.01); double sumtxd = 0; for (int row = 0; row < dst.rows; row++) { for (int col = 0; col < dst.cols; col++) { sumtxd = sumtxd + pinghua.at(row/gfresize, col/gfresize); } } double avetxd = sumtxd/(dst.rows * dst.cols); double adjust = 1.5 * avetxd * A_final; //ÇóÈ¡ÎÞÎíͼÏñ #pragma omp parallel for for (int row = 0; row < dst.rows; row++) { for (int col = 0; col < dst.cols; col++) { double txd; txd = pinghua.at(row/gfresize, col/gfresize);// txd = txd/255.0; if(txd < 0.1) txd = 0.1; const cv::Vec3b& ixv = src.at(row, col); double v1 = (((double)(ixv.val[0]) - A_final)/txd + A_final); double v2 = (((double)(ixv.val[1]) - A_final)/txd + A_final); double v3 = (((double)(ixv.val[2]) - A_final)/txd + A_final); v1 = (v1 * (255 + adjust))/(v1 + adjust); v2 = (v2 * (255 + adjust))/(v2 + adjust); v3 = (v3 * (255 + adjust))/(v3 + adjust); v1 = v1<1.0?1.0:v1>254.0?254:v1; v2 = v2<1.0?1.0:v2>254.0?254:v2; v3 = v3<1.0?1.0:v3>254.0?254:v3; cv::Vec3d val(v1, v2, v3); dst.at(row, col) = val;//cv::Vec3b(txd*255,txd*255,txd*255); } } } cv::Mat DarkChannelDehaze::calDev(Mat src, Rect meanRect) { int sum_value,sum_value2; double e1,e2; Mat Vop; #pragma omp parallel for for(int ii = 0;ii(i,j); sum_value2 += src(meanRect).at(i,j)*src(meanRect).at(i,j); } } e1 = sum_value/(meanRect.width*meanRect.height); e2 = sum_value2/(meanRect.width*meanRect.height); Vop.create(src.size(), CV_32FC1); Vop.setTo(cv::Scalar::all(0.0)); Vop.at(ii,jj) = static_cast(e2 - e1); } } normalize(Vop,Vop,255.0,0.0,NORM_MINMAX); return Vop; } void DarkChannelDehaze::calcDarkChannel( const Mat& src, Mat& dark ) { std::vector rgbs; cv::split(src, rgbs); int totalrow = ((src.rows)/block); totalrow += ((src.rows) % block == 0 ? 0 : 1); int totalcol = ((src.cols) / block); totalcol += ((src.cols) % block == 0)?0:1; Mat block_dark = Mat(totalrow, totalcol, CV_8UC1); block_dark.setTo(cv::Scalar::all(0)); cv::Rect imgRect(0, 0, src.cols, src.rows); #pragma omp parallel for for (int row = 0; row < totalrow; row++) { for (int col = 0;col < totalcol;col++) { cv::Rect block_rect(col*block, row*block, block, block); block_rect = block_rect&imgRect; cv::Vec3d mins, maxs; for (size_t i = 0;i < rgbs.size();i++) { cv::minMaxLoc(rgbs[i](block_rect), mins.val + i, maxs.val + i, NULL, NULL); } uchar min = 0; if(mins.val[0] < mins.val[1]) { min = static_cast(mins.val[0]); } else { min = static_cast(mins.val[1]); } if(min > mins.val[2]) { min = static_cast(mins.val[2]); } block_dark.at(row,col) = min; } } dark.create(src.size(), CV_8UC1); dark.setTo(cv::Scalar::all(0)); #pragma omp parallel for for (int row = 0; row < dark.rows; row++) { for (int col = 0; col < dark.cols; col++) { int rrow = row/block; int rcol = col/block; dark.at(row, col) = block_dark.at(rrow, rcol); } } } void DarkChannelDehaze::Init(int width, int height) { dcc.create(height, width, CV_8UC1); toushelv.create(height, width, CV_8UC1); } cv::Mat DarkChannelDehaze::guidedFilter( cv::Mat I, cv::Mat ip, int rid, double eps ) { cv::Mat _I; cv::Mat _ip; cvtColor(I, _I, CV_BGR2GRAY); _I.convertTo(I, CV_64FC1); ip.convertTo(_ip, CV_64FC1); ip = _ip; int hei = I.rows; int wid = I.cols; cv::Mat N; cv::boxFilter(cv::Mat::ones(hei, wid, I.type()), N, CV_64FC1, cv::Size(rid, rid)); cv::Mat mean_I; cv::boxFilter(I, mean_I, CV_64FC1, cv::Size(rid, rid)); cv::Mat mean_p; cv::boxFilter(ip, mean_p, CV_64FC1, cv::Size(rid, rid)); cv::Mat mean_Ip; cv::boxFilter(I.mul(ip), mean_Ip, CV_64FC1, cv::Size(rid, rid)); cv::Mat cov_Ip = mean_Ip - mean_I.mul(mean_p); cv::Mat mean_II; cv::boxFilter(I.mul(I), mean_II, CV_64FC1, cv::Size(rid, rid)); cv::Mat var_I = mean_II - mean_I.mul(mean_I); cv::Mat amask = cov_Ip/(var_I + eps); cv::Mat bmask = mean_p - amask.mul(mean_I); cv::Mat mean_a; cv::boxFilter(amask, mean_a, CV_64FC1, cv::Size(rid, rid)); mean_a = mean_a/N; cv::Mat mean_b; cv::boxFilter(bmask, mean_b, CV_64FC1, cv::Size(rid, rid)); mean_a = mean_a/N; cv::Mat pinghua = mean_a.mul(I) + mean_b; return pinghua; }