代码有部分改动
int main()
{
Mat image = imread(line);
if (image.empty()){
cout <<line<< " 文件不存在" << endl;
return -1;
}
Mat darkmat(image.size(), CV_8UC1);
//区域大小
const int RECT = 17;
Mat txMat(darkmat.size(), CV_32FC1);
Mat dst(image.size(), CV_8UC3);
HazeRemoval(image, darkmat, txMat, dst, RECT, 0.95);
imshow("原图", image);
imshow("还原图",dst);
waitKey(0);
return 0;
}
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
void getDarkChannel(Mat& src, Mat& darkmat,const int RECT)
{
for (int i = 0; i < src.rows; ++i)
{
for (int j = 0; j < src.cols; ++j)
{
int startPosX = i - (RECT - 1) / 2;
int startPosY = j - (RECT - 1) / 2;
if (startPosX < 0)
startPosX = 0;
if (startPosY < 0)
startPosY = 0;
int endPosX = i + (RECT - 1) / 2;
int endPosY = j + (RECT - 1) / 2;
if (endPosX >= src.rows)
endPosX = src.rows - 1;
if (endPosY >= src.cols)
endPosY = src.cols - 1;
uchar minValue = 255;
for (int m = startPosX; m <= endPosX; ++m)
{
uchar b, g, r, min_perPiex = 255;
Vec3b* ptr = src.ptr<Vec3b>(m);
for (int n = startPosY; n <= endPosY; ++n)
{
b = ptr[n][0];
g = ptr[n][1];
r = ptr[n][2];
if (b > g){
min_perPiex = ((g < r) ? g : r);
}
else{
min_perPiex = ((b < r) ? g : r);
}
if ((int)minValue>(int)min_perPiex)
minValue = min_perPiex;
}
}
darkmat.at<uchar>(i, j) = minValue;
}
}
}
float getA(Mat& image, Mat& darkmat)
{
int total_num = darkmat.rows*darkmat.cols;
int reference_value = total_num / 1000;
int *light_num = new int[256]{0};
if (light_num == NULL)
cout << "申请内存不成功!" << endl;
for (int i = 0; i < darkmat.rows; ++i)
{
for (int j = 0; j < darkmat.cols; ++j)
{
int index = (int)darkmat.at<uchar>(i, j);
++(light_num[index]);
}
}
int count = 0;
vector<int> piexValue;
for (int i = 255; i >= 0; --i)
{
if (light_num[i] != 0){
count += light_num[i];
piexValue.push_back(i);
if (count >= reference_value)
break;
}
}
vector<int> point(reference_value*2);
int cal_point = 0;
for (int k = 0; k < piexValue.size(); ++k)
{
for (int i = 0; i < darkmat.rows; ++i)
{
for (int j = 0; j < darkmat.cols; ++j)
{
int index = (int)darkmat.at<uchar>(i, j);
if (index == piexValue[k])
{
if (cal_point < (reference_value * 2))
{
point[cal_point] = i;
point[cal_point+1] = j;
cal_point += 2;
}
}
}
}
}
//计算A值
float a;
float sum = 0;
for (auto i = point.cbegin(); i != point.cend(); i = i + 2)
{
int b, g, r;
b = image.at<Vec3b>(*i, *(i + 1))[0];
g = image.at<Vec3b>(*i, *(i + 1))[1];
r = image.at<Vec3b>(*i, *(i + 1))[2];
//这个是取最大值的方式
//a = (b > g ? (b > r ? b : r) : (g > r ? g : r));
//取均值方式
sum += (b + g + r);
}
//均值
a = sum * 2 / (3 * point.size());
delete []light_num;
//if (a > 220.0)
// a = 220.0;
return a;
}
void getT_x(Mat& darkmat, Mat &txMat, float a, float w, float threshold = 0.1)
{
for (int i = 0; i < darkmat.rows; ++i)
for (int j = 0; j < darkmat.cols; ++j)
{
txMat.at<float>(i, j) = 1 - w*((int)darkmat.at<uchar>(i, j)) / a;
if (txMat.at<float>(i, j) < threshold)
txMat.at<float>(i, j) = threshold;
}
}
void get_dst(Mat& image, Mat& dst, Mat& txMat, float a)
{
for (int i = 0; i < image.rows; ++i)
for (int j = 0; j < image.cols; ++j)
{
for (int k = 0; k < 3; ++k)
{
int ss = ((image.at<Vec3b>(i, j)[k] - a) / txMat.at<float>(i, j)) + a;
if (ss > 255)
dst.at<Vec3b>(i, j)[k] = 255;
else if (ss < 0)
dst.at<Vec3b>(i, j)[k] = 0;
else
dst.at<Vec3b>(i, j)[k] = ss;
}
}
}
void HazeRemoval(Mat &image, Mat &darkmat, Mat &txMat,Mat &dst, const int RECT,float w)
{
//得到暗通道图
getDarkChannel(image, darkmat, RECT);
//得到A值
float a = getA(image, darkmat);
//计算t(x)
getT_x(darkmat, txMat, a, w);
//得到目标图
get_dst(image, dst, txMat, a);
}
版权声明:本文为ListenAlone原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。