毕设—高动态范围图像渲染算法之基于Retinex的色调映射技术(七)

这次和前几次一样,也是只介绍算法思路和实现步骤,再给出本人项目中Retinex的代码,Retinex的原理就不做解释。参考的论文是《Adaptive Local Tone Mapping Based on Retinex for High Dynamic Range Images》

本篇参考论文把算法分为两个部分,第一个部分是全局色调映射;第二部分是局部色调映射。全局自适应这部分原理既简单又容易实现,局部自适应这部分原理不简单但是容易实现。因为我们只需要按着步骤来即可。

1、全局色调映射步骤:
毕设—高动态范围图像渲染算法之基于Retinex的色调映射技术(七)_第1张图片
本篇论文把过程写的很详细,全局映射按公式(4)即可完成,那里面的参数如何求解呢?按公式(5)即可计算出。这个算法是我实现过程中最省心的。。。。

2、局部色调映射
这部分的原理有点难理解,但是实现还是很容易的,因为他把实现公式又给我们列出来了。
毕设—高动态范围图像渲染算法之基于Retinex的色调映射技术(七)_第2张图片
首先求出α,然后实现β,最后带入公式得结果。
-------------------------------------------------------------------------------------------------------------------------------------------------------
其中的Hg(x,y)是什么呢?他也给出了说明:
毕设—高动态范围图像渲染算法之基于Retinex的色调映射技术(七)_第3张图片
Hg(x,y)就是引导滤波后的结果,可见这篇算法进行了改进,使用了引导滤波代替了高斯滤波。为什么替换?这篇论文是这么解释的:为了减少光晕伪影。为什么会减少我没有看明白。




接下来是本人项目的实现步骤,共分为五步:

第一步:色彩空间转化

第二步:全局色调映射

Lave = exp(Lsum / (1.0*rows*cols));//计算对数平均值

Mat out_image(rows,cols,CV_32FC1);//定义输出图像
double Ymax=-1e9,Ysum=0,Yave=0,Ymin=1e9;

for (int i = 0; i < rows; i++)
{
	for (int j = 0; j < cols; j++)
	{
		//记录XYZ空间下x,y,z的比率
		double rateX=xyz[i][j].x/(xyz[i][j].x+xyz[i][j].y+xyz[i][j].z);
		double rateY=xyz[i][j].y/(xyz[i][j].x+xyz[i][j].y+xyz[i][j].z);

		//对亮度值进行压缩
		xyz[i][j].y = log(1 + xyz[i][j].y / Lave) / log(1 + Lmax / Lave);

		//还原x,y,z的比率
		xyz[i][j].x=xyz[i][j].y/rateY*rateX;
		xyz[i][j].z=xyz[i][j].y/rateY*(1-rateX-rateY);

第三步:局部色调映射——引导滤波

resultImage = guidedFilter3(out_image, out_image, 9, 0.01);//对分通道分别进行引导滤波,半径为1、3、5...等奇数  
Mat guidedFilter3(Mat srcMat, Mat guidedMat, int radius, double eps)//引导滤波器
{
	//转换源图像信息,将输入扩展为64位浮点型,以便以后做乘法
    srcMat.convertTo(srcMat, CV_64FC1, 1.0);  
    guidedMat.convertTo(guidedMat, CV_64FC1, 1.0);  

	/*imshow("srcMat",srcMat);
	imshow("guidedMat",guidedMat);*/

    //各种均值计算
    Mat mean_p, mean_I, mean_Ip, mean_II; 

	//生成待滤波图像均值mean_p   
    boxFilter(srcMat, mean_p, CV_64FC1, Size(radius, radius));
	//生成引导图像均值mean_I   
    boxFilter(guidedMat, mean_I, CV_64FC1, Size(radius, radius));
	//生成互相关均值mean_Ip  
    boxFilter(srcMat.mul(guidedMat), mean_Ip, CV_64FC1, Size(radius, radius));
	//生成引导图像自相关均值mean_II  	
    boxFilter(guidedMat.mul(guidedMat), mean_II, CV_64FC1, Size(radius, radius));

    //计算相关系数,计算Ip的协方差cov和I的方差var
    Mat cov_Ip = mean_Ip - mean_I.mul(mean_p);  
    Mat var_I = mean_II - mean_I.mul(mean_I);  

    //计算参数系数a、c
    Mat c = cov_Ip / (var_I + eps);  
    Mat b = mean_p - c.mul(mean_I);  

    //计算系数a、b的均值
    Mat mean_a, mean_b;  
    boxFilter(c, mean_a, CV_64FC1, Size(radius, radius));  
    boxFilter(b, mean_b, CV_64FC1, Size(radius, radius)); 

    //生成输出矩阵
    Mat dstImage = mean_a.mul(srcMat) + mean_b;  
    return dstImage;  
}

第四步:局部色调映射——计算比例因子带入公式

//获得两个因子,进行色调映射
double aerfa = 1 + 36.0 * xyz[i][j].y/Ymax;
double beta=10*Yave;
double result=resultImage.at<float>(i,j);
xyz[i][j].y=aerfa*log(xyz[i][j].y/(result+a)+beta+1);

第五步:局部色调映射——归一化

//归一化
xyz[i][j].y=(log(xyz[i][j].y+a)-log(Lmin+a))/(log(Lmax+a)-log(Lmin+a));

第六步:色彩空间还原

映射效果:
毕设—高动态范围图像渲染算法之基于Retinex的色调映射技术(七)_第4张图片总结:该算法是五种色调映射算法中,映射效果最好的。也可以用来图像增强,以车牌号为例。
在这里插入图片描述在这里插入图片描述但是增强效果一般。

你可能感兴趣的:(毕设,色调映射)