1. YUV与RAW基础概念:颜色空间与拜耳阵列的物理意义
各位同学,咱们今天聊点实在的。YUV和RAW,这两个词在嵌入式图像处理里天天见。但说实话,我见过不少做了两三年的工程师,对它们的理解还停留在「YUV就是亮度加色差,RAW就是原始数据」这种表面层次。
嗯,这不够。咱们得从物理层面把它吃透。
1.1 颜色空间:为什么非要用YUV?
先问个问题:人眼对什么最敏感?
亮度。说白了,人眼对亮度的分辨能力远高于对颜色的分辨能力。RGB格式呢?它把亮度和颜色信息混在一起,每个通道地位平等。这就有个问题——你想压缩数据的时候,没法单独处理亮度信息。
YUV就是来解决这个问题的。Y代表亮度(Luma),UV代表色度(Chroma)。
我记得刚入行那会儿,有个项目要把1080p的视频通过USB传输到上位机显示。RGB888一帧要1920×1080×3字节,带宽根本扛不住。后来换成YUV422,数据量直接砍掉三分之一,人眼看不出区别。这就是YUV的威力——利用人眼特性,把色度信息降采样。
核心公式(简化版):
Y = 0.299R + 0.587G + 0.114B
U = -0.147R - 0.289G + 0.436B
V = 0.615R - 0.515G - 0.100B
注意:不同标准(BT.601、BT.709)系数略有差异,实际开发中要查芯片手册确认。
1.2 YUV的几种常见采样格式
实际项目中,YUV的存储格式五花八门。我列几个最常见的:
| 格式 | 描述 | 每像素比特 | 典型应用 |
|---|---|---|---|
| YUV444 | 每个像素都有完整的Y、U、V | 24bit | 专业视频处理 |
| YUV422 | 每2个像素共享一组UV | 16bit | 摄像头输出、视频传输 |
| YUV420 | 每4个像素共享一组UV | 12bit | H.264/H.265编码、存储 |
| YUV411 | 每4个像素共享一组UV(水平方向) | 12bit | 低带宽应用 |
这里有个坑,我必须要说。YUV420在内存中的排列方式有两种:NV12和NV21。NV12是先存Y平面,再交错存UV;NV21是先存Y平面,再交错存VU。Android摄像头默认输出NV21,而大部分硬件编码器要NV12。我曾经因为这个顺序搞反,折腾了一整天,画面全是绿的。你想想看,这种低级错误多冤。
个人经验:在HAL层做YUV转换时,我习惯先确认硬件模块的文档。有些ISP输出的YUV是打包格式(packed),有些是平面格式(planar)。别想当然,先看datasheet。
1.3 RAW数据:传感器最原始的呼吸
RAW是什么?说白了,就是图像传感器每个像素点直接输出的电信号值,未经任何处理。每个像素只记录一种颜色——红色、绿色或蓝色。这就是拜耳阵列(Bayer Pattern)的由来。
为什么会这样?因为传感器上的每个感光单元本身是色盲的,它只能感知光的强度。为了获得彩色信息,工程师在传感器表面覆盖了一层彩色滤光片阵列(CFA),最常见的排列就是拜耳模式:
R G R G R G
G B G B G B
R G R G R G
G B G B G B
看到没?绿色像素数量是红色和蓝色的两倍。为什么?因为人眼对绿色最敏感。这跟YUV的设计思路一脉相承——把资源用在刀刃上。
我记得有一次调试一款500万像素的传感器,输出RAW10格式。每个像素10bit,但存储时按16bit对齐。我当时没注意对齐方式,直接按10bit连续读取,结果图像全是条纹。后来发现,硬件在传输时每4个像素打包成5字节。嗯,这种细节,datasheet里一行小字就写清楚了,但你不踩坑就不会记住。
1.4 拜耳阵列的物理意义
拜耳阵列不是随便排的。它的核心思想是:用更少的红色和蓝色采样点,通过插值算法恢复出全彩色图像。这个过程叫去马赛克(Demosaic)。
常见的拜耳模式有四种:
- RGGB:第一行RGRG,第二行GBGB(最常见)
- BGGR:第一行BGBG,第二行GRGR
- GRBG:第一行GRGR,第二行BGBG
- GBRG:第一行GBGB,第二行RGRG
你可能会问:这四种有什么区别?
从算法角度看,没本质区别。但从硬件设计角度看,不同传感器厂商会选择不同的排列,主要是为了优化电路布局和信号串扰。我在项目中遇到过一款安森美的传感器,默认输出BGGR,而海思平台默认期望RGGB。如果不做通道重映射,出来的图像颜色完全是错的。
避坑指南:我曾经在调试一款OV的传感器时,发现图像偏绿。查了半天,发现是拜耳模式配置错了。传感器输出的是GBRG,但ISP配置成了RGGB。这种问题在HAL层调试时特别容易忽略,因为图像不是全黑全白,只是颜色不对,很容易被误认为是白平衡问题。
1.5 YUV与RAW的转换关系
从RAW到YUV,中间要经过ISP管线。大致流程是:
- 黑电平校正:减去暗电流带来的偏移
- 去马赛克:从拜耳阵列插值出RGB
- 白平衡:调整R/G/B增益,使白色物体呈现白色
- 颜色校正矩阵:将传感器RGB转换到标准RGB空间
- Gamma校正:调整亮度响应曲线
- RGB转YUV:最终输出YUV格式
在HAL层开发中,你通常不会手动实现这些算法。但你必须理解每个阶段的数据格式和位宽变化。比如,RAW数据进来是10bit或12bit,经过ISP处理后变成8bit的YUV。如果你在HAL层直接操作RAW buffer,必须知道它的位深和排列方式。
关键点:RAW数据是线性的,YUV数据是经过Gamma校正的非线性数据。如果你在HAL层做图像处理(比如叠加OSD),一定要搞清楚当前buffer是线性还是非线性。否则叠加出来的效果会偏暗或偏亮。
1.6 小结
这一章咱们把YUV和RAW的物理意义讲清楚了。说白了,YUV是利用人眼特性做的颜色空间压缩,RAW是传感器最原始的呼吸。理解这两者的本质区别,是后续做HAL层驱动开发的基础。
下一章,我会带大家深入HAL层,看看YUV和RAW buffer在内存中到底怎么布局,以及如何高效地进行格式转换。到时候我会拿一个实际项目中的代码来拆解,保证干货满满。
嗯,今天就到这儿。有问题随时交流。