687 words
3 minutes
智能猫眼项目技术详解(YUYV转BGRA)
1. 为什么要转换?
- 摄像头输出:YUYV(YUV422) 人眼对亮度敏感,对颜色不敏感,所以摄像头用压缩颜色的格式,节省带宽。
- 4:4:4 表示色度频道没有下采样,即一个Y分量对应着一个U分量和一个V分量。
- 4:2:2 表示 2:1 的水平下采样,没有垂直下采样,即每两个Y分量共用一个U分量和一个V分量。
- 4:2:0 表示 2:1 的水平下采样,2:1 的垂直下采样,即每四个Y分量共用一个U分量和一个V分量。
- 屏幕显示需要:BGRA(RGB888) 屏幕只认红、绿、蓝三通道,不认 YUV。
结论:
必须把摄像头的 YUYV 转换成屏幕能识别的 RGB! 这就是转换的意义。
2. YUYV 是什么?(原理核心)
YUYV = 亮度(Y)+ 色差(U/V)
格式排列:
Y0 U0 Y1 V0 → 表示 2 个像素- Y:亮度(黑白图像)
- U/Cb:蓝色差
- V/Cr:红色差
特点:
- 2 个像素共用一组 UV
- 数据量小,适合摄像头传输
- 屏幕不能直接显示
3. BGRA 是什么?
屏幕显示格式:
B G R A → 1 个像素- R = 红
- G = 绿
- B = 蓝
- A = 透明度(固定 0xFF)
屏幕只吃这个格式!
4. 转换公式原理(核心)
YUV → RGB 标准公式(ITU 标准)
R = Y + 1.4075 * VG = Y - 0.3455 * U - 0.7169 * VB = Y + 1.7790 * U全部放大 256 倍用整数计算:
R = (298*Y + 409*V + 128) >> 8G = (298*Y - 100*U - 208*V + 128) >> 8B = (298*Y + 516*U + 128) >> 85. 转换逻辑
int c = y_val - 16; // Y 分量归一化int d = u_val - 128; // U 色差归一化int e = v_val - 128; // V 色差归一化
int r = (298 * c + 409 * e + 128) >> 8;int g = (298 * c - 100 * d - 208 * e + 128) >> 8;int b = (298 * c + 516 * d + 128) >> 8;这就是 YUV 转 RGB 的标准整数算法!
6. 你代码特别处理:YUYV 是 2 像素一组
像素0:Y0 U0像素1:Y1 V0所以代码里:
int src_idx = (src_y * src_width + (src_x & ~1)) * 2;unsigned char y_val = (src_x & 1) ? y1 : y0;作用:
- 偶数x → 取 Y0
- 奇数x → 取 Y1
- 两个像素共用 U 和 V
这是 YUV422 格式的标准读取方式。
7. 最终输出 BGRA 格式
dst[dst_idx] = b | g<<8 | r<<16 | 0xff<<24;因为帧缓冲 /dev/fb0 要求:
- 字节顺序:B G R A
- 所以要移位排列
终极总结(一句话记住)
转换原理:
摄像头输出 YUYV(亮度+压缩颜色) → 通过 YUV→RGB 公式计算 → 生成屏幕能识别的 BGRA 格式 → 直接写入帧缓冲 /dev/fb0 显示
智能猫眼项目技术详解(YUYV转BGRA)
https://blog.huangzy.xyz/posts/智能猫眼项目技术详解yuyv转bgra/ Some information may be outdated