图像增强--暗原色先验去雾(三)

具体的理论可以参考这篇文章,写得非常详细。

https://blog.csdn.net/songhhll/article/details/12612681

下面直接进行基于opencv4.10的算法实现

一、求取暗原色图像

//求取min(R,G,B)
	Mat minRgb = Mat::zeros(src.rows, src.cols, CV_8UC1);
	for (int i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			uchar g_minvalue = 255;
			for (int c = 0; c < 3; c++)
			{
				if (g_minvalue > src.at<Vec3b>(i, j)[c])
					g_minvalue = src.at<Vec3b>(i, j)[c];
			}
			minRgb.at<uchar>(i, j) = g_minvalue;
		}
	}

	imshow("min[r,g,b]",minRgb);

	//求取暗源色图像
	Mat darkChannelImage;
	int ksize = std::max(3, std::max((int)(src.cols*kernRatio), (int)(src.rows*kernRatio))); //求取自适应核大小
	minFilter(minRgb, darkChannelImage, ksize);
	/*显示暗原色图像*/
	imshow("Dark_Channel_Image",darkChannelImage);

其中滤波函数为

void minFilter(const cv::Mat src, cv::Mat &dst, int ksize)
{
	//检测原始图像
	if (src.channels() != 1)
		return;
	if (src.depth() > 8)
		return;

	int r = (ksize - 1) / 2; //核半径
	//初始化目标图像
	dst = Mat::zeros(src.rows, src.cols, CV_8UC1);
	//最小值滤波
	for (int i = 0; i < src.rows; i++)
		for (int j = 0; j < src.cols; j++)
		{
			//初始化滤波核的上下左右边界
			int top = i - r;
			int bottom = i + r;
			int left = j - r;
			int right = j + r;

			//检查滤波核是否超出边界
			if (i - r < 0)
				top = 0;
			if (i + r > src.rows)
				bottom = src.rows;
			if (j - r < 0)
				left = 0;
			if (j + r > src.cols)
				right = src.cols;

			//求取模板下的最小值
			Mat ImROI = src(Range(top, bottom), Range(left, right));
			double min, max;
			minMaxLoc(ImROI, &min, &max, 0, 0);
			dst.at<uchar>(i, j) = min;
		}
}

二、求取透过率图

//求取透过率图(根据暗原色先验原理)
	Mat t = Mat::zeros(src.rows, src.cols, CV_64FC1);
	for (int i = 0; i < src.rows; i++)
		for (int j = 0; j < src.cols; j++)
		{
			t.at<double>(i, j) = (255.0 -
				(double)darkChannelImage.at<uchar>(i, j)*wFactor) / 255;
		}
	imshow("T_Image",t);//透过率图, 如果要显示 只有范围在0到1之间才有意义

三、求取全局大气光强A

//求取全球大气光强A(全局量)
	double A; Point maxLoc;
	minMaxLoc(darkChannelImage, 0, &A, 0, &maxLoc);
	A = std::max(src.at<Vec3b>(maxLoc.y, maxLoc.x)[0],std::max(src.at<Vec3b>(maxLoc.y, maxLoc.x)[1],
		src.at<Vec3b>(maxLoc.y, maxLoc.x)[2]));

四、根据去雾公式求取去雾图像

//根据去雾公式求取去雾图像  J=(I-(1-t)*A)/max(t,min_t)
	Mat deFog = Mat::zeros(src.rows, src.cols, CV_8UC3);
	for (int i = 0; i < src.rows; i++)
		for (int j = 0; j < src.cols; j++)
			for (int c = 0; c < src.channels(); c++)
				deFog.at<Vec3b>(i, j)[c] = (src.at<Vec3b>(i, j)[c] -
				(1 - t.at<double>(i, j))*A) /
				std::max(t.at<double>(i, j), min_t);
	imshow("defog", deFog);

文章中的代码我已经上传到CSDN上了

https://download.csdn.net/download/weixin_42521239/11167242

没有积分的小伙伴可以在评论中留下你的邮箱,我发给你。

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 36
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 36
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值