1. 为什么需要从色域坐标推导转换矩阵第一次接触RGB与YUV转换时你可能直接套用过现成的转换系数。比如BT.601标准中常用的Y0.299R0.587G0.114B这个公式。但当你需要适配HDR视频或特殊显示设备时突然发现不同标准下的系数完全不同——这时候就需要理解这些数字背后的生成逻辑。色域坐标如x0.64,y0.33的红点坐标定义了颜色空间的边界。就像地图上的经纬度决定了国家版图色坐标决定了这个标准能显示多少种颜色。当摄像机使用BT.2020广色域拍摄而显示器只支持BT.709时就需要通过转换矩阵进行色彩映射。理解从色坐标到矩阵系数的推导过程你就能自定义非标准色域的转换参数排查跨设备色彩不一致的问题优化HDR视频转码的色域压缩2. 色域坐标到RGB转XYZ矩阵2.1 色度坐标与三原色定义以BT.709标准为例其色域坐标定义为红色x0.64, y0.33绿色x0.30, y0.60蓝色x0.15, y0.06白点D65x0.3127, y0.3290这些xy坐标需要先转换到XYZ色彩空间。XYZ是CIE定义的与设备无关的色彩空间其中Y分量直接对应人眼感知的亮度。转换公式为def xy_to_XYZ(x, y): X x / y Y 1.0 # 亮度归一化 Z (1 - x - y) / y return [X, Y, Z]2.2 构建RGB转XYZ矩阵通过白点平衡计算可以得到3x3的转换矩阵。这里用Python示例计算BT.709的矩阵# BT.709色坐标 red [0.64, 0.33] green [0.30, 0.60] blue [0.15, 0.06] white [0.3127, 0.3290] # 转换为XYZ坐标 RGB_XYZ np.array([ xy_to_XYZ(*red), xy_to_XYZ(*green), xy_to_XYZ(*blue) ]).T # 转置为3x3矩阵 # 白点平衡计算 white_XYZ xy_to_XYZ(*white) S np.linalg.inv(RGB_XYZ) white_XYZ M_RGB2XYZ RGB_XYZ * S # 最终矩阵得到的矩阵第二行[0.2126, 0.7152, 0.0722]就是RGB转灰度的系数来源——因为它对应人眼最敏感的亮度感知。3. 推导YUV转换系数3.1 Full Range系数计算YUV的Y分量直接使用RGB转XYZ矩阵的第二行亮度系数而UV分量则通过色差计算得到# 从RGB2XYZ矩阵提取亮度系数 kr, kg, kb M_RGB2XYZ[1] # 构建RGB转YUV矩阵 rgb2yuv np.zeros((3,3)) rgb2yuv[0] [kr, kg, kb] # Y行 rgb2yuv[1] [kr/(2*(1-kb)), kg/(2*(1-kb)), 0.5] # U行 rgb2yuv[2] [0.5, kg/(2*(1-kr)), kb/(2*(1-kr))] # V行 # 求逆得到YUV转RGB矩阵 yuv2rgb np.linalg.inv(rgb2yuv)这里UV分量的分母(2*(1-kb))是为了将色差归一化到[-0.5,0.5]范围。你可以尝试修改这个分母值观察对色彩饱和度的影响。3.2 Limit Range的调整电视信号常用的YCbCrLimit Range需要额外处理def full_to_limit(yuv2rgb, bit_depth8): max_val (1 bit_depth) - 1 ys 219 * (1 (bit_depth - 8)) # Y范围系数 uvs 224 * (1 (bit_depth - 8)) # UV范围系数 scale_mat np.diag([max_val/ys, max_val/uvs, max_val/uvs]) return yuv2rgb scale_mat # 矩阵乘法这个缩放操作解释了为什么8位YCbCr中Y的有效范围是16-235而不是0-255——这是为了给信号过冲留出余量。4. 不同标准的系数对比通过上述方法我们计算出三大标准的Full Range系数标准Y系数 (kr,kg,kb)YUV→RGB矩阵示例BT.6010.299, 0.587, 0.114[[1.0, 0.0, 1.402], ...]BT.7090.2126,0.7152,0.0722[[1.0, 0.0, 1.5748], ...]BT.20200.2627,0.6780,0.0593[[1.0, 0.0, 1.4746], ...]可以看到随着色域扩大BT.2020BT.709BT.601蓝色系数kb逐渐减小因为广色域需要更多绿色来保持亮度平衡。5. 实战自定义色域转换假设你要为某款专业显示器定制转换矩阵其色坐标为红x0.68,y0.32绿x0.25,y0.65蓝x0.12,y0.05白点D50(x0.3457,y0.3585)只需修改第2章的代码中的坐标值就能生成对应的转换矩阵。在实际应用中还需要考虑Gamma校正现代标准使用PQ或HLG传递函数色度子采样YUV420等格式需要特殊处理UV分量位深扩展10/12位数据需要调整缩放系数我曾在一个医疗影像项目中因为直接使用BT.709矩阵导致X光片色彩失真。通过重新计算设备实际的色域矩阵最终实现了准确的灰阶再现。这印证了理解底层原理的重要性——现成系数就像别人家的钥匙未必能打开你的门。