令人迷惑的YUV存储模式
奇怪的知识增加了
除YUV之外,经常提到的还有 YPbPr 和 YCbCr。YPbPr 指模拟分量信号(或接口),P(Parallel)表示并行,b 下标表示蓝,r 下标表示红。YCbCr 指的是数字分量信号(或接口),C(Chroma)表示色度。YCbCr 还可指色彩空间,YCbCr 色彩空间是 YUV 色彩空间的缩放和偏移版本。
YUV采样方式
主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0。这些采样方式,不压缩 Y 分量,对 UV 分量的压缩程度不同。
YUV存储方式
存储模式分成三大类:
packed:将 Y、U、V 分量交织存放在一起,和 RGB 的存放方式类似。内存中排列形式类似:YVYUYVYUYVYUYVYU…。在具体的存储模式命名中,packed 格式不带后缀 P。
planar:将 Y、U、V 的三个分量分别存放在不同的矩阵(平面)中。内存中排列形式类似:YYYYYY…,UUUUUU…,VVVVVV…。在具体的存储模式命名中,planar 格式带后缀 P。
semi-planar:将 Y、U、V 三个分量放在两个矩阵(平面)中。Y 占用一个平面,UV 共用一个平面。内存中排列形式类似:YYYYYY…,UVUVUV…。在具体的存储模式命名中,semi-planar 格式带后缀 SP。
存储方式加上采样方式
https://developer.aliyun.com/article/782082
其中有些常用的
semi-planar 存储模式 YUV420SP
NV12:
1 2 3 4 5 6 7
| Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y ------- U V U V U V U V
|
NV21:
1 2 3 4 5 6 7
| Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y ------- V U V U V U V U
|
planar 存储模式 YUV420P
YU12/IYUV/I420:
1 2 3 4 5 6 7 8 9 10
| Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y ------- U U U U --- V V V V
|
YV12:
1 2 3 4 5 6 7 8 9 10
| Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y Y ------- V V V V --- U U U U
|
一段读取YUV420数据的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| class VideoCaptureYUV: def __init__(self, filename, size):
self.width, self.height = size
self.Y_len = self.width * self.height
self.UV_len = self.width * self.height // 4
self.f = open(filename, 'rb')
self.Y_shape = (self.height, self.width)
self.UV_shape = (self.height//2, self.width//2)
def read_raw(self):
raw = self.f.read(self.Y_len)
Y = np.frombuffer(raw, dtype=np.uint8)
Y = Y.reshape(self.Y_shape)
raw = self.f.read(self.UV_len)
u = np.frombuffer(raw, dtype=np.uint8)
u = u.reshape(self.UV_shape)
raw = self.f.read(self.UV_len)
v = np.frombuffer(raw, dtype=np.uint8)
v = v.reshape(self.UV_shape)
return Y,u,v
def read(self):
Y,u,v = self.read_raw()
img = np.concatenate((Y.reshape(-1), u.reshape(-1), v.reshape(-1)))
img = img.reshape((self.height * 3 // 2, self.width)).astype('uint8') # YUV 的存储格式为:I420(YYYY UUVV)
\#print(yuv.shape)
bgr = cv2.cvtColor(img, cv2.COLOR_YUV2BGR_I420)
return bgr
|