问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

YUV色彩空间详解:从理论到实践

创作时间:
作者:
@小白创作中心

YUV色彩空间详解:从理论到实践

引用
CSDN
1.
https://m.blog.csdn.net/qq_40622955/article/details/143305336

YUV 图像格式

1. YUV 颜色空间简介

YUV是一种颜色编码方式,它将图像信息分为亮度(Y)色度(U 和 V)两个部分。该格式的优点在于,它将亮度信息与色度信息分开,使得对亮度和色度的处理可以独立进行。YUV的结构适用于视频图像的高效存储和传输,尤其是在视频压缩领域中应用广泛。

Y分量(亮度):亮度分量 Y 主要控制图像的亮暗细节,包含了大部分可见的信息。由于人眼对亮度的敏感度较高,在图像处理中保留更多的亮度信息对视觉效果的影响更大。

U分量(色度蓝色差分):U分量记录图像中蓝色相对于亮度的差异,用来描述蓝色和黄色之间的对比。

V分量(色度红色差分):V分量记录图像中红色相对于亮度的差异,用来描述红色和青色之间的对比。

2. YUV 采样格式

YUV有多个不同的采样格式,采样方式主要体现在对U和V分量的采样率不同,常见的采样方式包括:

  • YUV 4:4:4:每个像素都有完整的Y、U、V分量,色度采样比例为4:4:4。此格式保留了最高的图像质量,但数据量较大。

  • YUV 4:2:2:在该格式下,每两个水平像素共享一个U和V分量。即色度的采样率为亮度采样率的一半,形成4:2:2的采样比例。此格式在广播视频中常见,既节省数据又保证了良好的画质。

  • YUV 4:2:0:每四个像素共享一个U和V分量,色度采样率更低。该采样方式进一步压缩了色度信息,在一些高压缩视频应用中广泛使用,例如MPEG、H.264。

3. RGB 与 YUV 之间的转换

RGB(红、绿、蓝)是另一个颜色空间,通常用于显示设备。YUV与RGB颜色空间之间的转换可以通过线性变换实现,公式如下:

RGB 转 YUV

给定RGB颜色空间中的一个像素 ((R, G, B)),其转换为YUV的公式为:

$$
\begin{cases}
Y & = 0.299 \cdot R + 0.587 \cdot G + 0.114 \cdot B \
U & = 0.492 \cdot (B - Y) = -0.147 \cdot R - 0.289 \cdot G + 0.436 \cdot B \
V & = 0.877 \cdot (R - Y) = 0.615 \cdot R - 0.515 \cdot G - 0.100 \cdot B \
\end{cases}
$$

这些公式表明,Y分量是RGB的加权平均值,用于表示亮度,而U和V分量则用于记录色度信息,即蓝色和红色相对于亮度的差异。

YUV 转 RGB

将YUV颜色空间转换为RGB颜色空间,公式如下:

$$
\begin{cases}
R = Y + 1.13983 \cdot V \
G = Y - 0.39465 \cdot U - 0.58060 \cdot V \
B = Y + 2.03211 \cdot U \
\end{cases}
$$

在实际操作中,YUV的不同采样方式会影响色度的采样率。在4:2:2或4:2:0采样模式下,需要在转换到RGB之前将色度信息上采样到与亮度相同的分辨率。

4. YUV 格式的应用

  • 视频压缩:YUV格式被广泛用于视频压缩,特别是在MPEG、H.264等视频编码中。通过降低U和V色度分量的采样率,YUV可以大幅减少数据量,同时保持良好的图像质量。

  • 图像处理:在图像处理中,YUV格式能方便地进行颜色空间转换和颜色调整。由于亮度与色度的独立性,YUV更适合在颜色平衡和亮度调整中使用。

  • 电视广播:YUV在电视信号的传输中应用广泛,因其兼容模拟和数字标准,能够提供高质量的图像传输。

  • 数字摄影:在数码相机和视频摄影中,YUV格式常用于RAW数据的存储,使得在后期处理中有更高的颜色调整灵活性。

通过使用YUV颜色空间,可以在数据量和图像质量之间取得平衡,为数字图像和视频压缩提供了高效的解决方案。

5. 实例YUV422转为BGR:

读取一个YUV422格式的图像并转为BGR格式显示。

TEST(Demo, TestReadYUV)
{
    std::string image_path = "/media/hello/data/avm_resource/calibration_image/front.yuv";
    int width = 1920;  // 图像的宽度
    int height = 1536; // 图像的高度
    // 读取YUV图像文件
    FILE *file = fopen(image_path.c_str(), "rb");
    if (!file) {
        std::cerr << "无法打开文件: " << image_path << std::endl;
        return ;
    }
    // calculate the pixels size 
    int file_size = 0;
    fseek(file, 0, SEEK_END);
    file_size = ftell(file);
    fseek(file, 0, SEEK_SET);
    std::cout << "file size: " << file_size << 
        "\n width * height * 3 / 2: " << width * height * 3 / 2 << 
        "\n width * height * 2: " << width * height * 2 << std::endl;
    
    // 创建一个Mat对象来存储YUV数据
    cv::Mat yuv_image(height , width , CV_8UC2);
    fread(yuv_image.data, 1,  2 * width * height, file);
    fclose(file);
    // 将YUV图像转换为BGR图像
    cv::Mat bgr_image;
    cv::cvtColor(yuv_image, bgr_image, cv::COLOR_YUV2BGR_YUYV);
    
    std::cout << "bgr_image size: " << bgr_image.size() << std::endl;
    std::cout << "bgr_image channels: " << bgr_image.channels() << std::endl;
    // 显示图像
    cv::namedWindow("BGR Image", cv::WINDOW_NORMAL);
    cv::imshow("BGR Image", bgr_image);
    
    cv::waitKey(0);
}

输出:

$9│ Note: Google Test filter = Demo.TestReadYUV
$9│ [==========] Running 1 test from 1 test suite.
$9│ [----------] Global test environment set-up.
$9│ [----------] 1 test from Demo
$9│ [ RUN      ] Demo.TestReadYUV @ ./test/test_find_circle.cpp:45
$9│ │ file size: 5898240
$9│ │  width * height * 3 / 2: 4423680
$9│ │  width * height * 2: 5898240
$9│ │ bgr_image size: [1920 x 1536]
$9│ │ bgr_image channels: 3
$9│ [       OK ] Demo.TestReadYUV (2058 ms)
$9│ 
$9│ [----------] 1 test from Demo (2058 ms total)
$9│ 
$9│ [==========] 1 test from 1 test suite ran. (2058 ms total)
$9│ [  PASSED  ] 1 test.

参考链接

  1. https://wiki.videolan.org/YUV/
  2. https://en.wikipedia.org/wiki/Y%E2%80%B2UV
  3. https://answers.opencv.org/question/87083/yuyv422-to-bgr/

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号