如何正确转换存储为Y‘’CrCb的颜色(使用rec )。到sRGB?
我正在处理HDTV视频,我正在使用libavcodec提取原始数据。虽然我已经成功地进行了转换,但我仍然没有信心我做的是正确的。VLC提供一个结果,在Gimp中使用另一个结果中的“组合”结果进行转换,使用来自web的代码也是不一致的。所以我还没有找到一个可靠的参考资料。
我的研究和目前的最佳选择如下。(数值为浮点,范围为0.0-1.0)我最不确定的是伽马校正。它比我想象的要轻一点,但我也不能说它看起来不对.
演播室-摆动移除
8位从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;我不确定是否可以安全地假设您永远不会得到超出范围的值,或者您是否需要限制它。
对于更高的位深度,规范说LSB被忽略了。那是什么意思?我也在用10位编码的材料,所以这是我感兴趣的。
从Y‘’CrCb到RGB
裁判。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 )维基百科为Cb和Cr提供了一个似乎更准确的定义:
Pb = 0.5 * (B' - Y') / (1 - Kb)
Pr = 0.5 * (R' - Y') / (1 - Kr)其中Kb和Kr是E'b和E'r的因子。似乎是从这些方程中舍入的。
通过逆转方程(使用Wikipedia版本)可以找到RGB:
double r = y + 2*(1.0-kr) * v;
double b = y + 2*(1.0-kb) * u;
double g = ( y - kr * rr - kb*rb ) / kg;G可直接使用Cr和Cb:
double g = y - 2*kr*(1-kr)/kg * v - 2*kb*(1-kb)/kg * u;(y因子为(1-kr-kb)/kg,为kr+kb+kg=1的kg/kg )。
RGB到sRGB
我还没有看到任何代码示例,包括这个步骤。我们需要转换rec指定的颜色空间。709到sRGB中指定的。AFAIK,两者之间唯一的区别是传递函数(即伽马)。rec指定的XY坐标。709与sRGB匹配,但我不知道为什么sRGB在rec时包含'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我们需要反转它,但是线性截止值0.018在这两个方程中都没有给出V的相同值。那么反向版本的范围是多少呢?:
L = ( ( V + 0.099 ) / 1.099 ) ^ (1/0.45) for 1 >= V >= ?
L = V / 4.5000 for ? > V >= 0sRGB也有同样的问题,但被修正为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;发布于 2014-05-02 23:21:56
为了正确地将线性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;
}注:v是线性的,V是非线性的.
这些函数是基于这里找到的一个方程:XYZ.html
还有一个选项是使用压缩函数V=V^ gamma的简化sRGB,其中gamma为2.2,正如网站上所指出的。
发布于 2021-05-13 04:14:51
rec指定的XY坐标。709个与sRGB匹配,
那些是xy,不是XY,它和XYZ的XY不一样。
叹息,首先,XYZ是在线性化之后,您不需要去那里,因为sRGB已经使用BT.709初选,正如你说的。RGB线性,R'G'B‘是非线性的.Y‘’Cb‘’Cr‘也是非线性的。
我也在用10位编码的材料,所以这是我感兴趣的。
这意味着你可以把它圈起来,得到正确的8位值。如果最后两位10位值是10位或11位,则整到下一个8位值,否则下降(00,01是舍入)。LSB意味着最不重要的部分。只是不要忘记,1023应该四舍五入到255,而不是溢出。
我们需要反转它,但是线性截止值0.018在这两个方程中都没有给出V的相同值。
不,你不需要逆转任何东西。REC.601/REC.709/REC.2020的EOTF不是OETF的反面,EOTF在BT.1886中被指定,对于理想的OLED显示是2.4完美的伽玛,在200勒克斯环境光下几乎是用于不完美的液晶显示器的sRGB EOTF。这就是为什么Chrome只对BT.709使用sRGB EOTF,这意味着“没有”EOTF,因为windows默认使用它。
我记得有人设计了一个分数,精确地代表了sRGB,
只有0.04045/12.92 == 0.003130804954,809/258400。
https://stackoverflow.com/questions/17536417
复制相似问题