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?
- 兼容性:YUV格式允许黑白设备仅解码Y分量,彩色设备解码YUV全分量。
- 压缩效率:人眼对亮度更敏感,色度分量可进行下采样(如YUV420),减少数据量。
- 色彩空间转换: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格式内存布局
// I420格式:YYYYYYYY UU VV
// 假设宽度=4,高度=2
unsigned char y_plane[4*2] = {Y0,Y1,Y2,Y3, Y4,Y5,Y6,Y7};
unsigned char u_plane[2*1] = {U0,U1}; // 水平/垂直均2:1下采样
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语言):
void rgb_to_yuv(unsigned char r, unsigned char g, unsigned char b,
unsigned char *y, unsigned char *u, unsigned char *v) {
*y = (unsigned char)(0.299 * r + 0.587 * g + 0.114 * b);
*u = (unsigned char)(-0.147 * r - 0.289 * g + 0.436 * b + 128);
*v = (unsigned char)(0.615 * r - 0.515 * g - 0.100 * b + 128);
}
四、YUV图像处理基础操作
1. 色度下采样与上采样
下采样(如YUV420转YUV422):需通过插值算法恢复色度分量。
// 简单线性插值示例(水平方向)
void upsample_u_horizontal(unsigned char *src_u, unsigned char *dst_u, int width) {
for (int i = 0; i < width*2; i++) {
int src_pos = i / 2;
if (i % 2 == 0) {
dst_u[i] = src_u[src_pos];
} else {
// 线性插值
dst_u[i] = (src_u[src_pos] + src_u[src_pos+1]) / 2;
}
}
}
2. YUV图像缩放
缩放需分别处理Y和UV分量。对于YUV420,UV分量的缩放比例应为Y的一半。
// 简单双线性插值缩放Y分量
void scale_y_plane(unsigned char *src, unsigned char *dst,
int src_width, int src_height,
int dst_width, int dst_height) {
float x_ratio = (float)src_width / dst_width;
float y_ratio = (float)src_height / dst_height;
for (int y = 0; y < dst_height; y++) {
for (int x = 0; x < dst_width; x++) {
int src_x = (int)(x * x_ratio);
int src_y = (int)(y * y_ratio);
dst[y*dst_width + x] = src[src_y*src_width + src_x];
}
}
}
3. 色彩空间调整
通过修改YUV分量实现亮度/对比度/饱和度调整:
// 亮度调整(Y分量加减常数)
void adjust_brightness(unsigned char *y_plane, int size, int delta) {
for (int i = 0; i < size; i++) {
int new_y = y_plane[i] + delta;
y_plane[i] = (new_y > 255) ? 255 : ((new_y < 0) ? 0 : new_y);
}
}
五、实际应用建议
- 选择合适格式:根据场景选择YUV420(节省带宽)或YUV444(保留高质量色度)。
- 内存对齐:处理YUV数据时注意内存对齐,避免性能损失。
- 使用硬件加速:现代GPU/DSP支持YUV硬解码,优先利用硬件能力。
- 测试工具:使用FFmpeg或GStreamer验证YUV数据处理流程。
六、总结
本文从YUV的基础概念出发,详细介绍了其格式分类、存储方式、与RGB的转换方法,以及基础处理操作(如缩放、色度调整)。对于初学者,建议从理解YUV420格式开始,逐步掌握色度下采样和简单插值算法。后续可深入学习YUV在视频编码(如H.264/H.265)中的应用,以及如何利用SIMD指令优化YUV处理性能。
发表评论
登录后可评论,请前往 登录 或 注册