去雾算法的代码实现(不含Soft Matting)

代码有部分改动

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);


	
}








  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ListenAlone

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值