利用python读取YUV文件 转RGB 8bit/10bit通用


Posted in Python onDecember 09, 2019

注:本文所指的YUV均为YUV420中的I420格式(最常见的一种),其他格式不能用以下的代码。

位深为8bit时,每个像素占用1字节,对应文件指针的fp.read(1);

位深为10bit时,每个像素占用2字节,对应文件指针的fp.read(2);

然后使用 int.from_bytes() 方法将二进制转换为int型数字。

以下程序可以读8bit或10bit位深的YUV,需要指定从第几帧开始读、一共读多少帧。

它返回三个数组,其shape分别为:Y [frame,W,H] U [frame,W/2,H/2] V [frame,W/2,H/2]

当只读1帧时它返回:Y [W,H] U [W/2,H/2] V [W/2,H/2]

# -*- coding: utf-8 -*-
 
import math
from functools import partial
import numpy as np
import matplotlib.pyplot as plt
 
 
def readyuv420(filename, bitdepth, W, H, startframe, totalframe, show=False):
  # 从第startframe(含)开始读(0-based),共读totalframe帧
 
  uv_H = H // 2
  uv_W = W // 2
 
  if bitdepth == 8:
    Y = np.zeros((totalframe, H, W), np.uint8)
    U = np.zeros((totalframe, uv_H, uv_W), np.uint8)
    V = np.zeros((totalframe, uv_H, uv_W), np.uint8)
  elif bitdepth == 10:
    Y = np.zeros((totalframe, H, W), np.uint16)
    U = np.zeros((totalframe, uv_H, uv_W), np.uint16)
    V = np.zeros((totalframe, uv_H, uv_W), np.uint16)
 
  plt.ion()
 
  bytes2num = partial(int.from_bytes, byteorder='little', signed=False)
 
  bytesPerPixel = math.ceil(bitdepth / 8)
  seekPixels = startframe * H * W * 3 // 2
  fp = open(filename, 'rb')
  fp.seek(bytesPerPixel * seekPixels)
 
  for i in range(totalframe):
 
    for m in range(H):
      for n in range(W):
        if bitdepth == 8:
          pel = bytes2num(fp.read(1))
          Y[i, m, n] = np.uint8(pel)
        elif bitdepth == 10:
          pel = bytes2num(fp.read(2))
          Y[i, m, n] = np.uint16(pel)
 
    for m in range(uv_H):
      for n in range(uv_W):
        if bitdepth == 8:
          pel = bytes2num(fp.read(1))
          U[i, m, n] = np.uint8(pel)
        elif bitdepth == 10:
          pel = bytes2num(fp.read(2))
          U[i, m, n] = np.uint16(pel)
 
    for m in range(uv_H):
      for n in range(uv_W):
        if bitdepth == 8:
          pel = bytes2num(fp.read(1))
          V[i, m, n] = np.uint8(pel)
        elif bitdepth == 10:
          pel = bytes2num(fp.read(2))
          V[i, m, n] = np.uint16(pel)
 
    if show:
      print(i)
      plt.subplot(131)
      plt.imshow(Y[i, :, :], cmap='gray')
      plt.subplot(132)
      plt.imshow(U[i, :, :], cmap='gray')
      plt.subplot(133)
      plt.imshow(V[i, :, :], cmap='gray')
      plt.show()
      plt.pause(1)
      #plt.pause(0.001)
 
  if totalframe==1:
    return Y[0], U[0], V[0]
  else:
    return Y,U,V
 
 
if __name__ == '__main__':
  #y, u, v = readyuv420(r'F:\_commondata\video\176x144 qcif\football_qcif.yuv', 8, 176, 144, 1, 5, True)
  y, u, v = readyuv420(r'F:\_commondata\video\1920x1080 B\RitualDance_1920x1080_60fps_10bit_420.yuv', 10, 1920, 1080, 0, 5, True)
  print(y.shape,u.shape,v.shape)

以下程序将YUV转为RGB(只能读8bit位深的YUV),返回1个数组,其shape为: [frame,W,H,3]

# -*- coding: utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt
 
 
def yuv2rgb(yuvfilename, W, H, startframe, totalframe, show=False, out=False):
  # 从第startframe(含)开始读(0-based),共读totalframe帧
  arr = np.zeros((totalframe,H,W,3), np.uint8)
  
  plt.ion()
  with open(yuvfilename, 'rb') as fp:
    seekPixels = startframe * H * W * 3 // 2
    fp.seek(8 * seekPixels) #跳过前startframe帧
    for i in range(totalframe):
      print(i)
      oneframe_I420 = np.zeros((H*3//2,W),np.uint8)
      for j in range(H*3//2):
        for k in range(W):
          oneframe_I420[j,k] = int.from_bytes(fp.read(1), byteorder='little', signed=False)
      oneframe_RGB = cv2.cvtColor(oneframe_I420,cv2.COLOR_YUV2RGB_I420)
      if show:
        plt.imshow(oneframe_RGB)
        plt.show()
        plt.pause(0.001)
      if out:
        outname = yuvfilename[:-4]+'_'+str(startframe+i)+'.png'
        cv2.imwrite(outname,oneframe_RGB[:,:,::-1])
      arr[i] = oneframe_RGB
  return arr
 
if __name__ == '__main__':
  video = yuv2rgb(r'D:\_workspace\akiyo_qcif.yuv', 176, 144, 0, 10, False, True)

用ffmpeg也可以,比如你需要将yuv的第8帧输出成一个png:

ffmpeg -s 176x144 -i akiyo_qcif.yuv -filter:v select="between(n\,8\,8)" out.png

以上这篇利用python读取YUV文件 转RGB 8bit/10bit通用就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python 条件判断的缩写方法
Sep 06 Python
Pyramid Mako模板引入helper对象的步骤方法
Nov 27 Python
Python实现字典的key和values的交换
Aug 04 Python
Python3之简单搭建自带服务器的实例讲解
Jun 04 Python
在python中利用KNN实现对iris进行分类的方法
Dec 11 Python
Python中Numpy mat的使用详解
May 24 Python
python的range和linspace使用详解
Nov 27 Python
Python利用PyExecJS库执行JS函数的案例分析
Dec 18 Python
Python通过两个dataframe用for循环求笛卡尔积
Apr 29 Python
Django Path转换器自定义及正则代码实例
May 29 Python
Python 实现自动登录+点击+滑动验证功能
Jun 10 Python
如何利用python创作字符画
Jun 25 Python
YUV转为jpg图像的实现
Dec 09 #Python
Pandas+Matplotlib 箱式图异常值分析示例
Dec 09 #Python
Python箱型图处理离群点的例子
Dec 09 #Python
Python实现非正太分布的异常值检测方式
Dec 09 #Python
python 实现检验33品种数据是否是正态分布
Dec 09 #Python
Python远程开发环境部署与调试过程图解
Dec 09 #Python
使用 Python 合并多个格式一致的 Excel 文件(推荐)
Dec 09 #Python
You might like
php中使用Akismet防止垃圾评论的代码
2011/06/10 PHP
php制作中间带自己定义图片二维码的方法
2014/01/27 PHP
destoon各类调用汇总
2014/06/20 PHP
添加到收藏夹代码(兼容几乎所有的浏览器)
2007/01/09 Javascript
JQUERY 浏览器判断实现函数
2009/08/20 Javascript
DOM 脚本编程中的兄弟节点
2009/10/31 Javascript
XENON基于JSON变种
2010/07/27 Javascript
javascript获取隐藏dom的宽高 具体实现
2013/07/14 Javascript
Jquery增加鼠标中间功能mousewheel的实例代码
2013/09/05 Javascript
基于jquery css3实现点击动画弹出表单源码特效
2015/08/31 Javascript
JS+DIV+CSS排版布局实现美观的选项卡效果
2015/10/10 Javascript
jQuery购物网页经典制作案例
2016/08/19 Javascript
js改变html的原有内容实现方法
2016/10/05 Javascript
Bootstrap图片轮播组件Carousel使用方法详解
2016/10/20 Javascript
JS去除重复并统计数量的实现方法
2016/12/15 Javascript
js将字符串中的每一个单词的首字母变为大写其余均为小写
2017/01/05 Javascript
layui table设置前台过滤转义等方法
2018/08/17 Javascript
jQuery实现图片切换效果
2020/10/19 jQuery
[03:42]2016国际邀请赛中国区预选赛首日现场玩家采访
2016/06/26 DOTA
[49:43]VG vs FNATIC 2019国际邀请赛小组赛 BO2 第一场 8.15
2019/08/17 DOTA
python监控文件并且发送告警邮件
2018/06/21 Python
Python3变量与基本数据类型用法实例分析
2020/02/14 Python
python实现马丁策略的实例详解
2021/01/15 Python
安德玛比利时官网:Under Armour比利时
2019/08/28 全球购物
电子狗项圈:eDog Australia
2019/12/04 全球购物
如何将整数int转换成字串String
2014/03/21 面试题
自主招生自荐信范文
2013/12/04 职场文书
中学教师请假制度
2014/02/03 职场文书
2014乡镇“三八”国际劳动妇女节活动总结
2014/03/01 职场文书
软件毕业生个人鉴定
2014/03/03 职场文书
小区文明倡议书
2014/05/16 职场文书
物理课外活动总结
2014/08/27 职场文书
教师三严三实对照检查材料
2014/09/25 职场文书
体育教师个人总结
2015/02/09 职场文书
婚礼双方父亲致辞
2015/07/27 职场文书
Vue Element plus使用方法梳理
2022/12/24 Vue.js