opencv-视频处理--dark channel -实现暗通道去雾详解

暗通道算法是由何恺明在CVPR论文《Single ImageHaze Removalusing Dark Channel Prior》中提出的。


图像去雾的模型:

  
我们分析以上模型:

【已知条件】
:observerd intensity,即输入图像(待去雾的图像)
【未知条件】
 scene radiance,即还原图像(去雾以后的图像)
 medium transmission
 global atmospheric light
【目标】
求出这三个未知条件,而根据去雾模型,我们只需要计算出其中两个未知条件,就可以求出第三个。文中先通过求出,然后通过去雾模型的转换计算

【问题】
怎么只通过,来计算出呢?
【问题的解决办法】
opencv-视频处理--dark channel -实现暗通道去雾详解_第1张图片
也就是我们先求出darkChannel.

darkChannel的定义:

代码如下:
#include
#include
#include
using namespace std;
#include
#include
#include
using namespace cv;
int main(int argc,char*argv[])
{
	Mat image=imread(argv[1],1);
	CV_Assert(!image.empty() && image.channels() == 3);
	//图片的归一化
	Mat fImage;
	image.convertTo(fImage,CV_32FC3,1.0/255,0);
	//规定patch的大小,且均为奇数
	int hPatch = 15;
	int vPatch = 15;
	//给归一化的图片添加边界
	Mat fImageBorder;
	copyMakeBorder(fImage,fImageBorder,vPatch/2,vPatch/2,hPatch/2,hPatch/2,BORDER_REPLICATE);
	//分离通道
	vector fImageBorderVector(3);
	split(fImageBorder,fImageBorderVector);
	//创建darkChannel
	Mat darkChannel(image.rows,image.cols,CV_32FC1);
	double minTemp ,minPixel;
	//根据darkChannel的定义
	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);
		}
	}
	namedWindow("darkChannel",1);
	imshow("darkChannel",darkChannel);
	Mat darkChannel8U;
	darkChannel.convertTo(darkChannel8U,CV_8UC1,255,0);
	imwrite("darkChannel.jpg",darkChannel8U);
return 0;
}

先给出一些运行结果:
opencv-视频处理--dark channel -实现暗通道去雾详解_第2张图片     opencv-视频处理--dark channel -实现暗通道去雾详解_第3张图片 opencv-视频处理--dark channel -实现暗通道去雾详解_第4张图片           opencv-视频处理--dark channel -实现暗通道去雾详解_第5张图片
opencv-视频处理--dark channel -实现暗通道去雾详解_第6张图片    opencv-视频处理--dark channel -实现暗通道去雾详解_第7张图片

第二步:通过暗通道来实现A的过程,

	/*第2步:求出 A(global atmospheric light)*/
	//2.1 计算出darkChannel中,前top个亮的值,论文中取值为0.1%
	float top = 0.001;
	float numberTop = top*darkChannel.rows*darkChannel.cols;
	Mat darkChannelVector;
	darkChannelVector = darkChannel.reshape(1,1);
	Mat_ darkChannelVectorIndex;
	sortIdx(darkChannelVector,darkChannelVectorIndex,CV_SORT_EVERY_ROW + CV_SORT_DESCENDING);
	//制作掩码
	Mat mask(darkChannelVectorIndex.rows,darkChannelVectorIndex.cols,CV_8UC1);//注意mask的类型必须是CV_8UC1
	for(unsigned int r = 0;r < darkChannelVectorIndex.rows;r++)
	{
		for(unsigned int c = 0;c < darkChannelVectorIndex.cols;c++)
		{
			if(darkChannelVectorIndex.at(r,c) <= numberTop)
				mask.at(r,c) = 1;
			else 
				mask.at(r,c) = 0;
		}
	}
	Mat darkChannelIndex = mask.reshape(1,darkChannel.rows);
	vector A(3);//分别存取A_b,A_g,A_r
	vector::iterator itA = A.begin();
	vector::iterator it = fImageBorderVector.begin();
	//2.2在求第三步的t(x)时,会用到以下的矩阵,这里可以提前求出
	vector fImageBorderVectorA(3);
	vector::iterator itAA = fImageBorderVectorA.begin();
	for( ;it != fImageBorderVector.end() && itA != A.end() && itAA != fImageBorderVectorA.end();it++,itA++,itAA++)
	{
		Mat roi(*it,Rect(hPatch/2,vPatch/2,darkChannel.cols,darkChannel.rows));
		minMaxLoc(roi,0,&(*itA),0,0,darkChannelIndex);//
		(*itAA) = (*it)/(*itA); //[注意:这个地方有除号,但是没有判断是否等于0]
	}

第三步:通过暗通道来实现t(x)的过程:

	/*第三步:求t(x)*/
	Mat darkChannelA(darkChannel.rows,darkChannel.cols,CV_32FC1);
	float omega = 0.95;//0(r,c) = float(minPixel);
		}
	}
	Mat tx = 1.0 - omega*darkChannelA;

文中,给出了一个tx的优化,我们后面使用guiderFilter进行优化。

第四步:既然A和t(x)已经求出,就可以求j(x);

	/*第四步:我们可以求J(x)*/
	float t0  = 0.1;//论文中取t0 = 0.1
	Mat jx(image.rows,image.cols,CV_32FC3);
	for(size_t r = 0;r < jx.rows;r++)
	{
		for(size_t c =0;c(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]);
		}
	}
	namedWindow("jx",1);
	imshow("jx",jx);
	Mat jx8U;
	jx.convertTo(jx8U,CV_8UC3,255,0);
	imwrite("jx.jpg",jx8U);

结果:
opencv-视频处理--dark channel -实现暗通道去雾详解_第8张图片  opencv-视频处理--dark channel -实现暗通道去雾详解_第9张图片
opencv-视频处理--dark channel -实现暗通道去雾详解_第10张图片      opencv-视频处理--dark channel -实现暗通道去雾详解_第11张图片
opencv-视频处理--dark channel -实现暗通道去雾详解_第12张图片    opencv-视频处理--dark channel -实现暗通道去雾详解_第13张图片


文中的代码还没有优化,代码重复率比较高

你可能感兴趣的:(图像处理,OpenCV,Python,计算机视觉,opencv之视频处理)