Advertisement

Relationship between YUV and RGB

阅读量:

Relationship between YUV and RGB

    • 1. YUV格式

      • 1.1 基本概念
      • 1.2 YUV420
        • 1.2.1 YUV420P
    • 1.2.2 YUV420SP

    • 2. YUV420sp to RGB

      • 2.1 YUV420sp 8bits
      • 2.2 YUV420sp 10bits
    • 3. RGB to YUV444

      • 3.1 RGB to YUV 444
      • 3.2 RGB to YUV420

此信息也可在维基百科中查阅:如维基百科所述:https://zh.wikipedia.org/wiki/YUV>
色彩深度: 如维基百科所述:https://en.wikipedia.org/wiki/Color_depth>

1. YUV格式

1.1 基本概念

YUV的颜色空间中所使用的像素位深分别为8-bit、10-bit、12-bit及16-bit。
每个像素占用的内存量会有所差异。
对于8-bit的值来说,在编程实现时可以直接使用int8类型进行表示。
而针对10位以上的情况,则需要根据具体应用场景来决定数值的具体读取方式:
一般而言,在处理不同比特深度时,
优先采用int16类型来进行数值运算;
如果遇到无法完全填充的情况,
则会将多余的高位部分赋值为零。
在多数情况下,默认顺序是先存储Y数据块,
随后按照不同的压缩格式分别处理U和V通道的数据。
这些压缩格式主要包括以下几种:
YCbCr_4:2:0、YCbCr_4:2:2、
YCbCr_4:1:1以及标准全分辨率格式下的
YCbCr_4:4:4编码方案。

  • 4:4:4表示完全取样。
    占用的空间内存为:
    size = height * width * 3

  • 4:2:2表示2:1的水平采样,垂直完全采样。
    占用的空间内存为:
    size = height * width * (1+1)

  • 4:2:0表示2:1的水平采样,垂直2:1采样。
    占用的空间内存为:
    size = height * width * (1+ 1/2)

  • 4:1:1表示4:1的水平采样,垂直完全采样。
    占用的空间内存为:
    size = height * width * (1+ 1/2)

1.2 YUV420

通常YUV420的存储格式为:

1

通常情况下,在数据处理流程中我们会按照一定的顺序执行各项操作;在YUV格式中遵循特定规则对图像进行编码时会遇到不同的处理方式:首先我们会对图像进行Y通道提取随后处理U通道最后处理V通道以完成整个编码过程;对于常见的YUV420格式其基本形式包括YUV420P(平面形式)和YUV420SP(半平面形式)。

1.2.1 YUV420P

对于YUV420P格式及其相关编码方式中包含I420和YV12两种编码格式:其中YU12(I420): YYYYYYYY UUVV即顺序为先读取Y分量再依次读取U分量和V分量

2

YV12: YYYYYYYY VVUU
先读取Y后读取V最后读取V

3
1.2.2 YUV420SP

遵循YUV420SP标准的图像阵列遵循先读取亮度分量(Y)后依次读取色差分量(U或V)的方式存储按照U-V或V-U顺序依次存储

NV12:先存储Y后,UV交替存储,即YYYYUVUV

4

NV21:先存储Y后,VU交替存储,即 YYYYVUVU

5

2. YUV420sp to RGB

复制代码
    # -*- coding: utf-8 -*-
    from PIL import Image
    import time, shutil, sys
    from time import perf_counter
    import numpy as np
    from matplotlib import pyplot as plt
    from skimage import io
    path = '10_0.yuv'
    def readyuv(path, r, c, bits):
    with open(path,'rb') as fp: 
         if bits == 8:
             data_bytes = fp.read(r*c+int(r*c/2))
             data_bytes = np.fromstring(data_bytes,'int8')
         if bits == 10:
             data_bytes = fp.read(2*(r*c+int(r*c/2)))
             data_bytes = np.fromstring(data_bytes,'int16')  
         my = data_bytes[0 : r*c]
         mu = data_bytes[r*c:r*c+int(r*c/2):2]
         mv = data_bytes[r*c+1: r*c+int(r*c/2):2]
         imy = np.reshape(my, (c, r))
         imu = np.reshape(mu, (int(c/2), int(r/2)))
         imv = np.reshape(mv, (int(c/2), int(r/2)))
         if bits == 10:
             imy1 = imy1 / 1023 
             imy = imy1.astype(int)
             imu1 = imu1 / 1023 
             imu = imu1.astype(int)
             imv1 = imv1 / 1023 
             imv = imv1.astype(int)
    return imy, imu, imv
    data = read_yuv1(path2, 4000, 3000, bits=10)
    plt.figure()
    plt.imshow(data)
    data1 = data.astype(int)
    plt.figure()
    plt.imshow(data1)

将YUV转化为RGB,范围是[0, 255],需要进行计算
计算公式如下所示:

\begin{bmatrix} {R}\\ {G}\\ {B}\\ \end{bmatrix} = \begin{bmatrix} {298}&{0}&{459}\\ {298}&{-55}&{-137}\\ {298}&{541}&{0}\\ \end{bmatrix} * \begin{bmatrix} {Y-16}\\ {U-128}\\ {V-128}\\ \end{bmatrix} + \begin{bmatrix} {128}\\ {128}\\ {128}\\ \end{bmatrix} >> \begin{bmatrix} {8}\\ {8}\\ {8}\\ \end{bmatrix}
公式的准确度待考证, 目前没有见到更加官方的公式来计算。很多公式感觉比较乱,而且系数的差异不大。计算的时候需要对每个像素点的范围进行约束,范围需要到[0, 255],如果超过可这个范围,整个图像会发雾。

复制代码
    def read_yuv1(path, r, c, bits):  
    with open(path,'rb') as fp:
         imy1, imu1, imv1 = readyuv(path, r, c, bits)
         
         imy1 = imy1 / 1023 
         imy = imy1.astype(int)
         imu1 = imu1 / 1023 
         imu = imu1.astype(int)
         imv1 = imv1 / 1023 
         imv = imv1.astype(int)
         
         rgb = np.zeros((c, r, 3))
         for i in range(0, c, 2):
             for j in range(0, r, 2):
                 m = int(i/2)
                 n = int(j/2)
                 rgb[i][j][0] = (298*(imy[i][j]-16) + 459*(imv[m][n]-128)+128) >>8
                 if rgb[i][j][0] < 0:
                     rgb[i][j][0] = 0
                 if rgb[i][j][0] > 255:
                     rgb[i][j][0] = 255
                 rgb[i][j][1] = (298*(imy[i][j]-16) - 55*(imu[m][n]-128) - 137 *(imv[m][n]-128) +128) >>8  
                 if rgb[i][j][1] < 0:
                     rgb[i][j][1] = 0
                 if rgb[i][j][1] > 255:
                     rgb[i][j][1] = 255
                 rgb[i][j][2] = (298*(imy[i][j]-16) + 541*(imu[m][n]-128) +128) >>8
                 if rgb[i][j][2] < 0:
                     rgb[i][j][2] = 0
                 if rgb[i][j][2] > 255:
                     rgb[i][j][2] = 255
                  #[i, j+1]
                 rgb[i][j+1][0] = (298*(imy[i][j+1]-16) + 459*(imv[m][n]-128)+128) >>8
                 if rgb[i][j+1][0] < 0:
                     rgb[i][j+1][0] = 0
                 if rgb[i][j+1][0] > 255:
                     rgb[i][j+1][0] = 255
                 rgb[i][j+1][1] = (298*(imy[i][j+1]-16) - 55*(imu[m][n]-128) - 137 *(imv[m][n]-128) +128) >>8 
                 if rgb[i][j+1][1] < 0:
                     rgb[i][j+1][1] = 0
                 if rgb[i][j+1][1] > 255:
                     rgb[i][j+1][1] = 255
                 rgb[i][j+1][2] = (298*(imy[i][j+1]-16) + 541*(imu[m][n]-128) +128) >>8
                 if rgb[i][j+1][2] < 0:
                     rgb[i][j+1][2] = 0
                 if rgb[i][j+1][2] > 255:
                     rgb[i][j+1][2] = 255
                  #[i+1, j]
                 rgb[i+1][j][0] = (298*(imy[i+1][j]-16) + 459*(imv[m][n]-128)+128) >>8
                 if rgb[i+1][j][0] < 0:
                     rgb[i+1][j][0] = 0
                 if rgb[i+1][j][0] > 255:
                     rgb[i+1][j][0] = 255
                 rgb[i+1][j][1] = (298*(imy[i+1][j]-16) - 55*(imu[m][n]-128) - 137 *(imv[m][n]-128) +128) >>8  
                 if rgb[i+1][j][1] < 0:
                     rgb[i+1][j][1] = 0
                 if rgb[i+1][j][1] > 255:
                     rgb[i+1][j][1] = 255
                 rgb[i+1][j][2] = (298*(imy[i+1][j]-16) + 541*(imu[m][n]-128) +128) >>8
                 if rgb[i+1][j][2] < 0:
                     rgb[i+1][j][2] = 0
                 if rgb[i+1][j][2] > 255:
                     rgb[i+1][j][2] = 255
                  #[i+1, j+1]
                 rgb[i+1][j+1][0] = (298*(imy[i+1][j+1]-16) + 459*(imv[m][n]-128)+128) >>8
                 if rgb[i+1][j+1][0] < 0:
                     rgb[i+1][j+1][0] = 0
                 if rgb[i+1][j+1][0] > 255:
                     rgb[i+1][j+1][0] = 255
                 rgb[i+1][j+1][1] = (298*(imy[i+1][j+1]-16) - 55*(imu[m][n]-128) - 137 *(imv[m][n]-128) +128) >>8 
                 if rgb[i+1][j+1][1] < 0:
                     rgb[i+1][j+1][1] = 0
                 if rgb[i+1][j+1][1] > 255:
                     rgb[i+1][j+1][1] = 255
                 rgb[i+1][j+1][2] = (298*(imy[i+1][j+1]-16) + 541*(imu[m][n]-128) +128) >>8
                 if rgb[i+1][j+1][2] < 0:
                     rgb[i+1][j+1][2] = 0
                 if rgb[i+1][j+1][2] > 255:
                     rgb[i+1][j+1][2] = 255
    return rgb

2.1 YUV420sp 8bits

RGB:

6

Y:

7

U:

8

V:

9

2.2 YUV420sp 10bits

RGB:

10

Y:

11

U:

12

V:

13

3. RGB to YUV444

RGB转YUV的公式如下所示:

3.1 RGB to YUV 444

\begin{bmatrix} {Y}\\ {U}\\ {V}\\ \end{bmatrix} = \begin{bmatrix} {0.299}&{0.587}&{0.114}\\ {-0.147}&{-0.289}&{0.436}\\ {0.615}&{-0.515}&{-0.1}\\ \end{bmatrix} * \begin{bmatrix} {R}\\ {G}\\ {B}\\ \end{bmatrix}

相应的代码为:

复制代码
    def rgb2yuv(path, r, c):
    
    I = io.imread(path1)
    Y = (0.299*I[:,:,0] +0.587*I[:,:,1] + 0.114*I[:,:,2]) 
    V = (0.615*I[:,:,0] -0.515*I[:,:,1] - 0.1*I[:,:,2])
    U = (-0.147*I[:,:,0] -0.289*I[:,:,1] + 0.436*I[:,:,2])
    
    return Y, U, V

Y:

14

V:

15

U:

16

3.2 RGB to YUV420

RGB to YUV420, 直接取UV的四个值里的第一个值作为U和V
代码

复制代码
    def rgb2yuv(path, r, c):
    
    I = io.imread(path1)
    Y = (0.299*I[:,:,0] +0.587*I[:,:,1] + 0.114*I[:,:,2]) 
    V = (0.615*I[:,:,0] -0.515*I[:,:,1] - 0.1*I[:,:,2])
    U = (-0.147*I[:,:,0] -0.289*I[:,:,1] + 0.436*I[:,:,2])
    u = np.zeros((int(c/2), int(r/2)))
    v = np.zeros((int(c/2), int(r/2)))
    
    for i in range(0, int(c/2)):
        for j in range(0, int(r/2)):
            u[i, j] = U[i*2, j*2]
            v[i, j] = V[i*2, j*2]
    return Y, U, V, u, v

全部评论 (0)

还没有任何评论哟~