Seb*_*ahl 5 gamma colors image-processing yuv
如何将存储为Y'CrCb的颜色(使用建议709)正确转换为sRGB?
我正在使用HDTV视频,并且正在使用libavcodec提取原始数据。虽然我成功进行了转换,但我仍然没有确定自己做的正确。VLC提供了一个结果,使用“ compose”结果将Gimp转换为另一个结果,并且使用Web上的代码也不一致。因此,我还没有找到可以比较的可靠参考。
我的研究和目前最好的选择如下。(值的浮点范围为0.0-1.0)我最不确定的是伽马校正。它比我预期的要轻一些,但是我也不能说它看起来不对...
对于8位,Y'的范围从16到235。Cr和Cb的范围从16到240,并且以128为中心。
y = (y - (16 / 255.0)) * ( 1 + 16.0 / 255.0 + (256-235) / 255.0 );
u = (u - (16 / 255.0)) * ( 1 + 16.0 / 255.0 + (256-240) / 255.0 );
v = (v - (16 / 255.0)) * ( 1 + 16.0 / 255.0 + (256-240) / 255.0 );
//Move chroma
u -= 0.5;
v -= 0.5;
Run Code Online (Sandbox Code Playgroud)
我不确定是否可以肯定地说您永远不会获得超出范围的值,或者是否需要限制它。
对于更高的位深度,规范指出,将忽略LSB。这意味着什么?我也在处理10位编码的材料,因此这对我很感兴趣。
记录。709规范介绍了如何将RGB转换为Y'CrCb:
E'y = 0.2126 * E'r + 0.7152 * E'g + 0.0722 * E'b
E'cb = 0.5389 * ( E'b - E'y )
E'cr = 0.6350 * ( E'r - E'y )
Run Code Online (Sandbox Code Playgroud)
Wikipedia提供了对Cb和Cr似乎更准确的定义:
Pb = 0.5 * (B' - Y') / (1 - Kb)
Pr = 0.5 * (R' - Y') / (1 - Kr)
Run Code Online (Sandbox Code Playgroud)
其中Kb和Kr是E'b和E'r的因子。规格值。从这些方程看来似乎是四舍五入的。
可以通过逆转方程式来找到RGB(使用Wikipedia版本):
double r = y + 2*(1.0-kr) * v;
double b = y + 2*(1.0-kb) * u;
double g = ( y - kr * rr - kb*rb ) / kg;
Run Code Online (Sandbox Code Playgroud)
G可以直接使用Cr和Cb来完成:
double g = y - 2*kr*(1-kr)/kg * v - 2*kb*(1-kb)/kg * u;
Run Code Online (Sandbox Code Playgroud)
(y的系数为(1-kr-kb)/ kg,当kr + kb + kg = 1时为kg / kg)
我完全没有看到任何包含此步骤的代码示例。我们需要转换rec指定的色彩空间。709至sRGB中指定的一个。AFAIK,两者之间的唯一区别是传递函数(即伽马)。rec指定的XY坐标。709与sRGB匹配,但我不知道为什么sRGB在记录时包括'Z'坐标。709没有。这有什么不同吗?(我对CIE XYZ一无所知。)
记录。709指定如何对线性RGB进行伽玛编码:
V = 1.099 * L^0.45 - 0.099 for 1 >= L >= 0.018
V = 4.500 * L for 0.018 > L >= 0
Run Code Online (Sandbox Code Playgroud)
我们需要将其反转,但是在两个方程中,线性截止值0.018的V值都不相同。那么反向版本的范围是多少?:
L = ( ( V + 0.099 ) / 1.099 ) ^ (1/0.45) for 1 >= V >= ?
L = V / 4.5000 for ? > V >= 0
Run Code Online (Sandbox Code Playgroud)
sRGB也有相同的问题,但被更正为0.0031308,这更加准确。我记得有人设计了一个分数来精确地代表sRGB,但我再也找不到了...
我目前正在使用以下内容:
double cutoff = 1.099 * pow( 0.018, 0.45 ) - 0.099;
v = ( v < cutoff ) ? 1.0/4.5 * v : pow( (v+0.099)/1.099, 1.0/0.45 );
v = ( v <= 0.0031308 ) ? 12.92 * v : 1.055*pow( v, 1.0/2.4 ) - 0.055;
Run Code Online (Sandbox Code Playgroud)
为了正确地将线性 sRGB 转换为非线性 sRGB(压缩扩展过程)以及相反过程(逆压缩扩展),我使用以下函数:
public double Companding(double channel)
{
double v = channel;
double V = v <= 0.0031308 ? 12.92 * v : 1.055 * Math.Pow(v, 1 / 2.4d) - 0.055;
return V;
}
public double InverseCompanding(double channel)
{
double V = channel;
double v = V <= 0.04045 ? V / 12.92 : Math.Pow((V + 0.055) / 1.055, 2.4);
return v;
}
Run Code Online (Sandbox Code Playgroud)
注:v是线性的,V是非线性的。
这些函数基于此处找到的方程式: http://www.brucelindbloom.com/index.html?Eqn_RGB_to_XYZ.html
还有一个选项是使用带有压扩函数v = V ^ gamma的简化 sRGB,其中gamma为 2.2,如网站上所述。