利用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中使用百度音乐搜索的api下载指定歌曲的lrc歌词
Jul 18 Python
python之wxPython菜单使用详解
Sep 28 Python
python 截取 取出一部分的字符串方法
Mar 01 Python
Python 装饰器使用详解
Jul 29 Python
python爬虫之模拟登陆csdn的实例代码
May 18 Python
python re正则匹配网页中图片url地址的方法
Dec 20 Python
Python实现微信自动好友验证,自动回复,发送群聊链接方法
Feb 21 Python
python中的数据结构比较
May 13 Python
Python 共享变量加锁、释放详解
Aug 28 Python
Pycharm插件(Grep Console)自定义规则输出颜色日志的方法
May 27 Python
python中scipy.stats产生随机数实例讲解
Feb 19 Python
深入理解Pytorch微调torchvision模型
Nov 11 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中inlcude()性能对比详解
2012/09/16 PHP
php里array_work用法实例分析
2015/07/13 PHP
jquery中实现简单的tabs插件功能的代码
2011/03/02 Javascript
jquery实现不同大小浏览器使用不同的css样式表的方法
2014/04/02 Javascript
JavaScript实现穷举排列(permutation)算法谜题解答
2014/12/29 Javascript
javascript运动详解
2015/07/06 Javascript
轻松实现js图片预览功能
2016/01/18 Javascript
jQuery多文件异步上传带进度条实例代码
2016/08/16 Javascript
vue 怎么创建组件及组件使用方法
2017/07/27 Javascript
详述 Sublime Text 打开 GBK 格式中文乱码的解决方法
2017/10/26 Javascript
如何在Vue.js中实现标签页组件详解
2019/01/02 Javascript
小程序云开发之用户注册登录
2019/05/18 Javascript
layui点击弹框页面 表单请求的方法
2019/09/21 Javascript
vue控制多行文字展开收起的实现示例
2019/10/11 Javascript
vue 实现 rem 布局或vw 布局的方法
2019/11/13 Javascript
微信小程序wx.request的简单封装
2019/11/13 Javascript
vue 中 elment-ui table合并上下两行相同数据单元格
2019/12/26 Javascript
node.js中process进程的概念和child_process子进程模块的使用方法示例
2020/02/11 Javascript
Python中实现从目录中过滤出指定文件类型的文件
2015/02/02 Python
python使用正则表达式替换匹配成功的组
2017/11/17 Python
python代码实现ID3决策树算法
2017/12/20 Python
Python利用pandas处理Excel数据的应用详解
2019/06/18 Python
关于pytorch多GPU训练实例与性能对比分析
2019/08/19 Python
Pytorch 实现focal_loss 多类别和二分类示例
2020/01/14 Python
利用python绘制中国地图(含省界、河流等)
2020/09/21 Python
Python日志打印里logging.getLogger源码分析详解
2021/01/17 Python
html5/css3响应式页面开发总结
2018/10/16 HTML / CSS
非洲NO.1网上商店:Jumia肯尼亚
2016/08/18 全球购物
Araks官网:纽约内衣品牌
2020/10/15 全球购物
绿色环保演讲稿
2014/05/10 职场文书
2014年公务员退休工资改革方案
2014/10/01 职场文书
幼儿园教学工作总结2015
2015/05/12 职场文书
用Python制作灯光秀短视频的思路详解
2021/04/13 Python
用Python远程登陆服务器的步骤
2021/04/16 Python
MySQL里面的子查询的基本使用
2021/08/02 MySQL
MySQL中一条update语句是如何执行的
2022/03/16 MySQL