纸翼 · 加载中
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 * V
G = Y - 0.3455 * U - 0.7169 * V
B = Y + 1.7790 * U

全部放大 256 倍用整数计算

R = (298*Y + 409*V + 128) >> 8
G = (298*Y - 100*U - 208*V + 128) >> 8
B = (298*Y + 516*U + 128) >> 8

5. 转换逻辑#

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/
Author
纸翼
Published at
2026-03-31
License
CC BY-NC-SA 4.0

Some information may be outdated