這次和前幾次一樣,也是隻介紹算法思路和實現步驟,再給出本人項目中Retinex的代碼,Retinex的原理就不做解釋。參考的論文是《Adaptive Local Tone Mapping Based on Retinex for High Dynamic Range Images》
本篇參考論文把算法分爲兩個部分,第一個部分是全局色調映射;第二部分是局部色調映射。全局自適應這部分原理既簡單又容易實現,局部自適應這部分原理不簡單但是容易實現。因爲我們只需要按着步驟來即可。
1、全局色調映射步驟:
本篇論文把過程寫的很詳細,全局映射按公式(4)即可完成,那裏面的參數如何求解呢?按公式(5)即可計算出。這個算法是我實現過程中最省心的。。。。
2、局部色調映射
這部分的原理有點難理解,但是實現還是很容易的,因爲他把實現公式又給我們列出來了。
首先求出α,然後實現β,最後帶入公式得結果。
-------------------------------------------------------------------------------------------------------------------------------------------------------
其中的Hg(x,y)是什麼呢?他也給出了說明:
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));
第六步:色彩空間還原
映射效果:
總結:該算法是五種色調映射算法中,映射效果最好的。也可以用來圖像增強,以車牌號爲例。
但是增強效果一般。