3、YUV域基础:颜色空间转换、采样格式与ISP中的位置

好,我们进入YUV域。说实话,很多做图像处理的工程师,做了好几年,对YUV的理解还是停留在“Y是亮度,UV是色度”这个层面。但真要动手做降噪,你会发现,不懂YUV的细节,根本调不好参数。

我个人习惯把YUV域称为“工程域”。为什么?因为人眼对亮度敏感,对颜色不敏感。YUV就是利用这个特性,把亮度和颜色分开处理。你想想看,降噪算法要是直接在RGB上做,三个通道一起抖,计算量大不说,还容易把颜色搞偏。YUV域就不一样了——你可以对Y通道做强降噪,对UV通道做弱降噪,甚至不做。效果又好,速度又快。

核心认知: YUV不是一种“颜色”,而是一种“分工”。亮度通道负责细节和纹理,色度通道负责色调和饱和度。降噪策略必须分开设计。

3.1 颜色空间转换:RGB → YUV

先看数学。RGB到YUV的转换,本质是一个线性变换。不同标准(BT.601、BT.709、BT.2020)的系数略有不同,但结构一样。我项目中用得最多的是BT.601标准,适合720p及以下分辨率。4K以上我建议用BT.709。

公式长这样(BT.601,有限范围):

Y  =  0.299 * R + 0.587 * G + 0.114 * B
U  = -0.169 * R - 0.331 * G + 0.500 * B + 128
V  =  0.500 * R - 0.419 * G - 0.081 * B + 128

注意那个+128。U和V是有符号数,范围-128~127,加上128后变成0~255的无符号数。很多新手在这里栽跟头——直接拿公式算,结果UV通道一片黑。嗯,我刚开始也犯过这个错。

反过来,YUV到RGB的转换:

R = Y + 1.402 * (V - 128)
G = Y - 0.344 * (U - 128) - 0.714 * (V - 128)
B = Y + 1.772 * (U - 128)
精度陷阱: 整数实现时,建议用移位+查表代替浮点乘法。比如把系数放大到2^14,乘完再右移14位。否则在嵌入式平台上,每一帧转换都能吃掉你10ms。

3.2 YUV采样格式:4:4:4 / 4:2:2 / 4:2:0

采样格式,说白了就是“UV通道的分辨率打几折”。人眼对颜色细节不敏感,所以我们可以把UV的分辨率降下来,节省带宽和存储。这是视频编码和ISP pipeline里的基本操作。

格式 Y分辨率 U分辨率 V分辨率 数据量(相对RGB) 典型场景
4:4:4 全分辨率 全分辨率 全分辨率 100% 专业调色、屏幕截图
4:2:2 全分辨率 水平1/2 水平1/2 67% 广播级视频、HDMI采集
4:2:0 全分辨率 水平1/2,垂直1/2 水平1/2,垂直1/2 50% 消费级视频、JPEG、H.264

4:2:0是最常见的格式。你手机拍的照片、录的视频,绝大多数都是4:2:0。为什么?因为省一半带宽,画质损失肉眼几乎看不出来。

但注意——降噪算法如果在4:2:0的YUV上直接做,UV通道的分辨率已经丢了。你处理U和V的时候,其实是在处理“半张图”。我遇到过有人把UV降噪强度设得和Y一样,结果色块边缘出现奇怪的锯齿。后来查了半天,才发现是UV分辨率不匹配导致的。

我的建议: 如果条件允许,降噪尽量在4:4:4域做。或者至少把4:2:0上采样到4:4:4再处理。虽然多一步插值,但能避免很多采样伪影。

3.3 YUV在ISP中的位置

ISP pipeline里,YUV域的位置非常关键。它通常在去马赛克(Demosaic)之后、色彩校正(CCM)之后、但还在编码(JPEG/H.264)之前。说白了,RGB域做完颜色还原,转到YUV域做降噪和锐化,最后再编码输出。

我画了一张流程图,帮你理清这个位置关系:

ISP Pipeline 中 YUV 域的位置 RAW 输入 去马赛克 CCM RGB → YUV Y 降噪 UV 降噪 锐化 编码输出 关键说明: • YUV 域是降噪和锐化的主战场 • Y 和 UV 降噪策略必须分开设计 • 锐化只在 Y 通道做,避免色噪放大

从图上你能看到:RAW进来,先去马赛克变成RGB,再经过CCM做色彩校正,然后转到YUV域。在YUV域里,Y通道和UV通道是分开处理的。Y通道做降噪+锐化,UV通道只做降噪。最后合在一起编码输出。

为什么锐化只做在Y通道?因为锐化本质是增强高频信息。UV通道的高频基本都是噪声,你一锐化,色噪全出来了。我见过有人把锐化做到RGB三个通道上,结果图像边缘出现彩色过冲,看着特别假。

实战经验: 在YUV域做降噪,Y通道可以用BM3D或NLM这类强降噪算法,UV通道用双边滤波就够了。UV通道的噪声主要是色度噪声,低频为主,双边滤波效果很好,计算量也小。

3.4 避坑指南

最后,我总结几个我在项目中踩过的坑:

  • 转换精度不够: 我曾经在定点DSP上实现RGB2YUV,直接用8位整数算,结果Y通道出现条带。后来改成16位中间精度,问题解决。
  • UV边界处理: 4:2:0的UV分辨率只有Y的1/4。做降噪时,滤波核大小要按UV的实际分辨率来算。别把Y的核直接套到UV上。
  • 色彩溢出: YUV转RGB时,如果Y和UV的范围没对齐,转出来的RGB可能超出0~255。一定要做clamp,否则图像会出现诡异的颜色。
  • 编码器不认: 有些编码器只接受特定范围的YUV(比如有限范围16~235)。你输出全范围0~255,编码器会裁掉暗部和亮部细节。记得在编码前做range mapping。

嗯,YUV域的基础就这些。记住一句话:YUV域是降噪算法的舒适区。把亮度和颜色分开,你的算法设计会轻松很多。