图像去雾算法

#include 
#include
#include
#include
#include
#include
using namespace cv;
using namespace std;

#define CV_SORT_EVERY_ROW    0
#define CV_SORT_EVERY_COLUMN 1
#define CV_SORT_ASCENDING    0
#define CV_SORT_DESCENDING   16

//CV_SORT_EVERY_ROW + CV_SORT_ASCENDING:对矩阵的每行按照升序排序;
//CV_SORT_EVERY_ROW + CV_SORT_DESCENDING:对矩阵的每行按照降序排序;
//CV_SORT_EVERY_COLUMN + CV_SORT_ASCENDING:对矩阵的每列按照升序排序;
//CV_SORT_EVERY_COLUMN + CV_SORT_DESCENDING:对矩阵的每列按照降序排序;

void makeDepth32f(Mat& source, Mat& output)
{
	if ((source.depth() != CV_32F) > FLT_EPSILON)
		source.convertTo(output, CV_32F);
	else
		output = source;
}


void guidedFilter(Mat& source, Mat& guided_image, Mat& output, int radius, float epsilon)
{
	//CV_Assert(radius >= 2 && epsilon > 0);
	CV_Assert(source.data != NULL && source.channels() == 1);//可改变输入图像类型(通道)
	CV_Assert(guided_image.channels() == 1);                 //导向图一般为单通道
	CV_Assert(source.rows == guided_image.rows && source.cols == guided_image.cols);

	Mat guided;
	if (guided_image.data == source.data)
		guided_image.copyTo(guided);
	else
		guided = guided_image;

	Mat source_32f, guided_32f;
	makeDepth32f(source, source_32f);//将输入扩展为32位浮点型,以便以后做乘法
	makeDepth32f(guided, guided_32f);

	Mat mat_Ip, mat_I2;   //计算I*p和I*I
	multiply(guided_32f, source_32f, mat_Ip);
	multiply(guided_32f, guided_32f, mat_I2);

	Mat mean_p, mean_I, mean_Ip, mean_I2;   //计算各种均值
	Size win_size(2 * radius + 1, 2 * radius + 1);
	boxFilter(source_32f, mean_p, CV_32F, win_size);
	boxFilter(guided_32f, mean_I, CV_32F, win_size);
	boxFilter(mat_Ip, mean_Ip, CV_32F, win_size);
	boxFilter(mat_I2, mean_I2, CV_32F, win_size);

	Mat cov_Ip = mean_Ip - mean_I.mul(mean_p);//计算Ip的协方差和I的方差
	Mat var_I = mean_I2 - mean_I.mul(mean_I);
	var_I += epsilon;

	Mat a, b;   //求a和b
	divide(cov_Ip, var_I, a);
	b = mean_p - a.mul(mean_I);

	Mat mean_a, mean_b;  //对包含像素i的所有a、b做平均
	boxFilter(a, mean_a, CV_32F, win_size);
	boxFilter(b, mean_b, CV_32F, win_size);

	output = mean_a.mul(guided_32f) + mean_b;//计算输出 (depth == CV_32F)
}


void HazeRemoval(Mat& image, Mat& imageRGB)
{
	CV_Assert(!image.empty() && image.channels() == 3);
	Mat fImage;
	image.convertTo(fImage, CV_32FC3, 1.0 / 255, 0);//图片归一化

	Mat fImageBorder;
	int hPatch = 15, vPatch = 15;//设定最小滤波patch的大小,且均为奇数
	copyMakeBorder(fImage, fImageBorder, vPatch / 2, vPatch / 2, hPatch / 2, hPatch / 2, BORDER_REPLICATE);//给归一化的图片添加边界
	vector fImageBorderVector(3);
	split(fImageBorder, fImageBorderVector);//分离通道

	Mat darkChannel(image.rows, image.cols, CV_32FC1);//创建darkChannel
	double minTemp, minPixel;
	for (unsigned int r = 0; r < darkChannel.rows; r++)
	{
		for (unsigned int c = 0; c < darkChannel.cols; c++)
		{
			minPixel = 1.0;
			for (vector::iterator it = fImageBorderVector.begin(); it != fImageBorderVector.end(); it++)
			{
				Mat roi(*it, Rect(c, r, hPatch, vPatch));
				minMaxLoc(roi, &minTemp);
				minPixel = min(minPixel, minTemp);
			}
			darkChannel.at(r, c) = float(minPixel);
		}
	}
	//darkChannel.convertTo(darkChannel8U, CV_8UC1, 255, 0);

	//求出A(global atmospheric light),计算出darkChannel中前top个亮的值,论文中取值为0.1%
	float top = 0.001;
	float numberTop = top * darkChannel.rows * darkChannel.cols;
	Mat darkChannelVector;
	darkChannelVector = darkChannel.reshape(1, 1);//reshape的一个参数表示通道数,第二个表示矩阵行数
	Mat_ darkChannelVectorIndex;
	sortIdx(darkChannelVector, darkChannelVectorIndex, CV_SORT_EVERY_ROW + CV_SORT_DESCENDING);//降序,返回像素索引

	int count = 0, temp = 0;
	unsigned int x, y; //映射回暗通道图的像素位置
	Mat mask(darkChannel.rows, darkChannel.cols, CV_8UC1);//制作掩码,注意mask的类型必须是CV_8UC1
	for (unsigned int r = 0; r < darkChannelVectorIndex.rows; r++)
	{
		for (unsigned int c = 0; c < darkChannelVectorIndex.cols; c++)
		{
			temp = darkChannelVectorIndex.at(r, c);
			x = temp / darkChannel.cols;
			y = temp % darkChannel.cols;

			if (count < numberTop) {
				mask.at(x, y) = 1;
				count++;
			}
			else
				mask.at(x, y) = 0;

		}
	}

	vector A(3);                //分别存取B,G,R通道的最大A值
	vector fImageBorderVectorA(3);//在求第三步的t(x)时,会用到以下的矩阵,这里可以提前求出
	vector::iterator itA = A.begin();
	vector::iterator it = fImageBorderVector.begin();
	vector::iterator itAA = fImageBorderVectorA.begin();
	for (; it != fImageBorderVector.end() && itA != A.end() && itAA != fImageBorderVectorA.end(); it++, itA++, itAA++)
	{
		Mat roi(*it, Rect(0, 0, darkChannel.cols, darkChannel.rows));
		minMaxLoc(roi, 0, &(*itA), 0, 0, mask);
		(*itAA) = (*it) / (*itA); //注意:这个地方有除号,但是没有判断是否等于0,*itA等于零的可能性很小
	}

	//求出t(x)
	Mat darkChannelA(darkChannel.rows, darkChannel.cols, CV_32FC1);
	float omega = 0.95;      //论文中取值为0.95
	for (unsigned int r = 0; r < darkChannel.rows; r++)
	{
		for (unsigned int c = 0; c < darkChannel.cols; c++)
		{
			minPixel = 1.0;
			for (itAA = fImageBorderVectorA.begin(); itAA != fImageBorderVectorA.end(); itAA++)
			{
				Mat roi(*itAA, Rect(c, r, hPatch, vPatch));
				minMaxLoc(roi, &minTemp);
				minPixel = min(minPixel, minTemp);
			}
			darkChannelA.at(r, c) = float(minPixel);
		}
	}
	Mat tx1 = 1.0 - omega * darkChannelA;
	Mat tx(darkChannel.rows, darkChannel.cols, CV_32FC1);

	guidedFilter(tx1, tx1, tx, 8, 500);

	namedWindow("tx", cv::WINDOW_AUTOSIZE);
	imshow("tx", tx);


	//求出J(x)
	float t0 = 0.1;//论文中取0.1
	//Mat jx(image.rows, image.cols, CV_32FC3);
	for (size_t r = 0; r < imageRGB.rows; r++)
	{
		for (size_t c = 0; c < imageRGB.cols; c++)
		{
			imageRGB.at(r, c) = Vec3f((fImage.at(r, c)[0] - A[0]) / max(tx.at(r, c), t0) + A[0], (fImage.at(r, c)[1] - A[1]) / max(tx.at(r, c), t0) + A[1], (fImage.at(r, c)[2] - A[2]) / max(tx.at(r, c), t0) + A[2]);
		}
	}

}


int main()
{
	Mat image = imread("D:\\opencv\\Project\\test\\x64\\Debug\\2.jpg");//设置0写入灰度图像
	if (image.empty())
	{
		std::cout << "打开图片失败,请检查" << std::endl;
		system("pause");
		return -1;
	}
	Mat testimage(image.size(), CV_32FC3);
	HazeRemoval(image, testimage);

	namedWindow("原图", cv::WINDOW_AUTOSIZE);
	namedWindow("变换后的图", cv::WINDOW_AUTOSIZE);
	imshow("原图", image);
	imshow("变换后的图", testimage);
	waitKey(0);
	destroyAllWindows();

	system("pause");
	return 0;
}

你可能感兴趣的:(图像增强,python)