You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

313 lines
7.2 KiB
C++

2 years ago
#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<src.rows;i++)
{
for(int j = 0;j<src.cols;j++)
{
pixel = min(dsts[1].at<uchar>(i,j),dsts[0].at<uchar>(i,j));
pixel = min(pixel,dsts[2].at<uchar>(i,j));
Vm.at<uchar>(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<src.rows;row++)
{
for(int col = 0;col<src.cols;col++)
{
dcc.at<uchar>(row,col) = (Vm.at<uchar>(row,col)*Vop.at<uchar>(row,col)+Vnorm.at<uchar>(row,col)*(255-Vop.at<uchar>(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<uchar>(row, col) = static_cast<uchar>((1.0 - w * dcc.at<uchar>(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<double>(row/gfresize, col/gfresize);
}
}
double avetxd = sumtxd/(dst.rows * dst.cols);
double adjust = 1.5 * avetxd * A_final;
//<2F><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC>
#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<double>(row/gfresize, col/gfresize);//
txd = txd/255.0;
if(txd < 0.1)
txd = 0.1;
const cv::Vec3b& ixv = src.at<cv::Vec3b>(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<cv::Vec3b>(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<src.rows-meanRect.width;ii++)
{
for(int jj = 0;jj<src.cols-meanRect.height;jj++)
{
meanRect.x = jj;
meanRect.y = ii;
sum_value = 0;
sum_value2 = 0;
e1 = 0.0;
e2 = 0.0;
for (int i = 0;i<meanRect.width;i++)
{
for (int j = 0;j<meanRect.height;j++)
{
sum_value += src(meanRect).at<uchar>(i,j);
sum_value2 += src(meanRect).at<uchar>(i,j)*src(meanRect).at<uchar>(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<float>(ii,jj) = static_cast<float>(e2 - e1);
}
}
normalize(Vop,Vop,255.0,0.0,NORM_MINMAX);
return Vop;
}
void DarkChannelDehaze::calcDarkChannel( const Mat& src, Mat& dark )
{
std::vector<Mat> 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<uchar>(mins.val[0]);
}
else
{
min = static_cast<uchar>(mins.val[1]);
}
if(min > mins.val[2])
{
min = static_cast<uchar>(mins.val[2]);
}
block_dark.at<uchar>(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<uchar>(row, col) = block_dark.at<uchar>(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;
}