logo

YUV图像处理入门1

作者:半吊子全栈工匠2025.09.19 11:24浏览量:0

简介:本文从YUV图像基础概念出发,系统讲解其格式分类、存储原理及简单处理操作,帮助初学者快速掌握YUV图像处理的核心知识。

YUV图像处理入门1:理解基础与简单操作

一、YUV图像基础概念

YUV是一种用于视频和图像处理的色彩编码系统,与常见的RGB(红绿蓝)三色模型不同,YUV将亮度(Y)与色度(U、V)分离。这种设计源于早期电视广播系统,旨在兼容黑白电视与彩色电视的信号传输。Y代表亮度(Luminance),U和V代表色度(Chrominance),分别表示蓝色和红色的色差分量。

为什么选择YUV?

  1. 兼容性:YUV格式允许黑白设备仅解码Y分量,彩色设备解码YUV全分量。
  2. 压缩效率:人眼对亮度更敏感,色度分量可进行下采样(如YUV420),减少数据量。
  3. 色彩空间转换:YUV与RGB可相互转换,便于不同场景下的处理。

二、YUV格式分类与存储

YUV格式根据色度分量的采样方式分为多种类型,常见的有:

  • YUV444:每个Y分量对应一个U和一个V,无压缩,数据量最大。
  • YUV422:水平方向上每两个Y分量共享一组U、V,垂直方向全采样。
  • YUV420:水平和垂直方向均下采样,每四个Y分量共享一组U、V,数据量最小,广泛用于视频压缩(如H.264)。

存储方式
YUV数据通常以平面(Planar)或打包(Packed)格式存储。

  • 平面格式:Y、U、V分量分别存储在连续的内存块中(如I420)。
  • 打包格式:YUV分量交替存储(如NV12),可能包含交错排列的宏块。

示例:I420格式内存布局

  1. // I420格式:YYYYYYYY UU VV
  2. // 假设宽度=4,高度=2
  3. unsigned char y_plane[4*2] = {Y0,Y1,Y2,Y3, Y4,Y5,Y6,Y7};
  4. unsigned char u_plane[2*1] = {U0,U1}; // 水平/垂直均2:1下采样
  5. unsigned char v_plane[2*1] = {V0,V1};

三、YUV与RGB的转换

YUV与RGB的转换需通过矩阵运算实现,公式如下(以BT.601标准为例):

RGB转YUV
[
\begin{align}
Y &= 0.299R + 0.587G + 0.114B \
U &= -0.147R - 0.289G + 0.436B + 128 \
V &= 0.615R - 0.515G - 0.100B + 128 \
\end{align
}
]

YUV转RGB
[
\begin{align}
R &= Y + 1.402(V-128) \
G &= Y - 0.344(U-128) - 0.714(V-128) \
B &= Y + 1.772(U-128) \
\end{align
}
]

代码示例(C语言)

  1. void rgb_to_yuv(unsigned char r, unsigned char g, unsigned char b,
  2. unsigned char *y, unsigned char *u, unsigned char *v) {
  3. *y = (unsigned char)(0.299 * r + 0.587 * g + 0.114 * b);
  4. *u = (unsigned char)(-0.147 * r - 0.289 * g + 0.436 * b + 128);
  5. *v = (unsigned char)(0.615 * r - 0.515 * g - 0.100 * b + 128);
  6. }

四、YUV图像处理基础操作

1. 色度下采样与上采样

下采样(如YUV420转YUV422):需通过插值算法恢复色度分量。

  1. // 简单线性插值示例(水平方向)
  2. void upsample_u_horizontal(unsigned char *src_u, unsigned char *dst_u, int width) {
  3. for (int i = 0; i < width*2; i++) {
  4. int src_pos = i / 2;
  5. if (i % 2 == 0) {
  6. dst_u[i] = src_u[src_pos];
  7. } else {
  8. // 线性插值
  9. dst_u[i] = (src_u[src_pos] + src_u[src_pos+1]) / 2;
  10. }
  11. }
  12. }

2. YUV图像缩放

缩放需分别处理Y和UV分量。对于YUV420,UV分量的缩放比例应为Y的一半。

  1. // 简单双线性插值缩放Y分量
  2. void scale_y_plane(unsigned char *src, unsigned char *dst,
  3. int src_width, int src_height,
  4. int dst_width, int dst_height) {
  5. float x_ratio = (float)src_width / dst_width;
  6. float y_ratio = (float)src_height / dst_height;
  7. for (int y = 0; y < dst_height; y++) {
  8. for (int x = 0; x < dst_width; x++) {
  9. int src_x = (int)(x * x_ratio);
  10. int src_y = (int)(y * y_ratio);
  11. dst[y*dst_width + x] = src[src_y*src_width + src_x];
  12. }
  13. }
  14. }

3. 色彩空间调整

通过修改YUV分量实现亮度/对比度/饱和度调整:

  1. // 亮度调整(Y分量加减常数)
  2. void adjust_brightness(unsigned char *y_plane, int size, int delta) {
  3. for (int i = 0; i < size; i++) {
  4. int new_y = y_plane[i] + delta;
  5. y_plane[i] = (new_y > 255) ? 255 : ((new_y < 0) ? 0 : new_y);
  6. }
  7. }

五、实际应用建议

  1. 选择合适格式:根据场景选择YUV420(节省带宽)或YUV444(保留高质量色度)。
  2. 内存对齐:处理YUV数据时注意内存对齐,避免性能损失。
  3. 使用硬件加速:现代GPU/DSP支持YUV硬解码,优先利用硬件能力。
  4. 测试工具:使用FFmpeg或GStreamer验证YUV数据处理流程。

六、总结

本文从YUV的基础概念出发,详细介绍了其格式分类、存储方式、与RGB的转换方法,以及基础处理操作(如缩放、色度调整)。对于初学者,建议从理解YUV420格式开始,逐步掌握色度下采样和简单插值算法。后续可深入学习YUV在视频编码(如H.264/H.265)中的应用,以及如何利用SIMD指令优化YUV处理性能。

相关文章推荐

发表评论