版权声明:本文为博主 ( 黃彥霖 ) 原创文章,未经博主允许不得转载。 https://blog.csdn.net/weixin_38884324/article/details/82253768
主要參考這幾位大老實現
論文 : Adaptive Local Tone Mapping Based on Retinex for High Dynamic Range Images
程式碼 : https://www.cnblogs.com/Imageshop/p/9460334.html
主要公式 :
_
Lw : 輸入的 Log 亮度平均值
Lg : 自適應的結果 ( 可以理解為權重 )
Lwamx : 輸入亮度的最大值
δ : 極小值 ( 防止直接對 0 處理 )
輸出結果 :
原圖 :
執行結果 :
程式碼 :
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEngine;
using UnityEngine.UI;
public class RetinexHDR : MonoBehaviour
{
public Texture2D inputTexture;
public RawImage img;
void Start()
{
// -----------------------------------------------------------
// 計算 Lwmax ( 亮度最大值 )
float Lwmax = 0;
for (int y = 0; y < inputTexture.height; y++)
{
for (int x = 0; x < inputTexture.width; x++)
{
Color c = inputTexture.GetPixel(x, y);
float Lw = 0.299f * c.r + 0.587f * c.g + 0.114f * c.b;
if (Lw > Lwmax)
{
Lwmax = Lw;
}
}
}
// -----------------------------------------------------------
// 計算 Lwaver ( 亮度平均值 )
float Lwaver;
float sum = 0;
for (int y = 0; y < inputTexture.height; y++)
{
for (int x = 0; x < inputTexture.width; x++)
{
Color c = inputTexture.GetPixel(x, y);
float Lw = 0.299f * c.r + 0.587f * c.g + 0.114f * c.b;
sum += Mathf.Log10(0.001f + Lw);
}
}
sum /= inputTexture.width * inputTexture.height;
Lwaver = Mathf.Exp(sum);
// -----------------------------------------------------------
// 對原圖進行計算,並輸出結果
Texture2D t = new Texture2D(inputTexture.width, inputTexture.height);
for (int y = 0; y < inputTexture.height; y++)
{
for (int x = 0; x < inputTexture.width; x++)
{
Color c = inputTexture.GetPixel(x, y);
float Lw = 0.299f * c.r + 0.587f * c.g + 0.114f * c.b;
float Lg = Mathf.Log10(Lw / Lwaver + 1) / Mathf.Log10(Lwmax / Lwaver + 1);
float gain = Lg / Lw;
Color color = new Color(c.r * gain, c.g * gain, c.b * gain);
t.SetPixel(x, y, color);
}
}
t.Apply();
img.texture = t;
// -----------------------------------------------------------
// 保存
File.WriteAllBytes("C:/A/1.Old.png", inputTexture.EncodeToPNG()); // 原圖
File.WriteAllBytes("C:/A/2.New.png", t.EncodeToPNG()); // 新圖
}
float[] ColorToYCbCr(Color color)
{
float[] yuv = new float[3];
yuv[0] = 0.299f * color.r + 0.587f * color.g + 0.114f * color.b;
yuv[1] = 0.564f * (color.b - yuv[0]);
yuv[2] = 0.713f * (color.r - yuv[0]);
return yuv;
}
Color YCbCrToColor(float[] yuv)
{
float r = yuv[0] + 1.402f * yuv[2];
float g = yuv[0] - 0.344f * yuv[1] - 0.714f * yuv[2];
float b = yuv[0] + 1.772f * yuv[1];
return new Color(r, g, b);
}
}