当前位置 主页 > 网站技术 > 代码类 >

    Python 读取 YUV(NV12) 视频文件实例

    栏目:代码类 时间:2019-12-09 12:06

    一、YUV 简介

    YUV:是一种颜色编码方法,常使用在各个视频处理组件中

    Y'UV, YCbCr, YPbPr等专有名词都可以称为 YUV,彼此有重叠

    Y表示明亮度(单取此通道即可得灰度图),U和V则是色度、浓度

    主流的采样方式有三种,YUV4:4:4,YUV4:2:2,YUV4:2:0

    可以根据其采样格式来从码流中还原每个像素点的 YUV 值,进而通过 YUV 与 RGB 的转换公式提取出每个像素点的 RGB 值,然后显示出来

    YUV4:2:0 数据在内存中的长度是 3 / 2 * heigth * width,是 RGB24(heigth * width * 3) 格式视频数据内存的一半

    二、YUV420(NV12、NV21、I420、YV12)

    # NV12、NV21 的存储格式为 Y 平面,UV 打包,即:Y 信息存储在一个数组中,UV 信息存储在一个矩阵中。
    # 不同点在于 UV 的排列顺序
    NV12: YYYYYYYY UVUV  => YUV420SP
    NV21: YYYYYYYY VUVU  => YUV420SP
    
    # I420、YV12 三个分量均为平面格式,即:分别存放在三个 Byte 型数组中
    I420: YYYYYYYY UU VV => YUV420P
    YV12: YYYYYYYY VV UU => YUV420P

    假设一个分辨率为8X4的 YUV 图像,它们的格式如下图:

    三、读取 YUV(NV12) 视频文件并保存

    #!/usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    import cv2
    import numpy as np
    
    
    def yuv2bgr(filename, height, width, startfrm):
     """
     :param filename: 待处理 YUV 视频的名字
     :param height: YUV 视频中图像的高
     :param width: YUV 视频中图像的宽
     :param startfrm: 起始帧
     :return: None
     """
     fp = open(filename, 'rb')
    
     framesize = height * width * 3 // 2 # 一帧图像所含的像素个数
     h_h = height // 2
     h_w = width // 2
    
     fp.seek(0, 2) # 设置文件指针到文件流的尾部
     ps = fp.tell() # 当前文件指针位置
     numfrm = ps // framesize # 计算输出帧数
     fp.seek(framesize * startfrm, 0)
    
     for i in range(numfrm - startfrm):
      Yt = np.zeros(shape=(height, width), dtype='uint8', order='C')
      Ut = np.zeros(shape=(h_h, h_w), dtype='uint8', order='C')
      Vt = np.zeros(shape=(h_h, h_w), dtype='uint8', order='C')
    
      for m in range(height):
       for n in range(width):
        Yt[m, n] = ord(fp.read(1))
      for m in range(h_h):
       for n in range(h_w):
        Ut[m, n] = ord(fp.read(1))
      for m in range(h_h):
       for n in range(h_w):
        Vt[m, n] = ord(fp.read(1))
    
      img = np.concatenate((Yt.reshape(-1), Ut.reshape(-1), Vt.reshape(-1)))
      img = img.reshape((height * 3 // 2, width)).astype('uint8') # YUV 的存储格式为:NV12(YYYY UV)
    
      # 由于 opencv 不能直接读取 YUV 格式的文件, 所以要转换一下格式
      bgr_img = cv2.cvtColor(img, cv2.COLOR_YUV2BGR_NV12) # 注意 YUV 的存储格式
      cv2.imwrite('yuv2bgr/%d.jpg' % (i + 1), bgr_img)
      print("Extract frame %d " % (i + 1))
    
     fp.close()
     print("job done!")
     return None
    
    
    if __name__ == '__main__':
     _ = yuv2bgr(filename='xxx.yuv', height=1080, width=1920, startfrm=0)
    

    以上这篇Python 读取 YUV(NV12) 视频文件实例就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持IIS7站长之家。