利用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实现简单的可逆加密程序实例
Mar 05 Python
处理Python中的URLError异常的方法
Apr 30 Python
python使用tornado实现简单爬虫
Jul 28 Python
对python读写文件去重、RE、set的使用详解
Dec 11 Python
Django 日志配置按日期滚动的方法
Jan 31 Python
Python英文文本分词(无空格)模块wordninja的使用实例
Feb 20 Python
浅谈Python3中strip()、lstrip()、rstrip()用法详解
Apr 29 Python
python深copy和浅copy区别对比解析
Dec 26 Python
python机器学习库xgboost的使用
Jan 20 Python
pandas中的数据去重处理的实现方法
Feb 10 Python
用Python进行栅格数据的分区统计和批量提取
May 27 Python
python周期任务调度工具Schedule使用详解
Nov 23 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
JAVA/JSP学习系列之六
2006/10/09 PHP
php处理文件的小例子(解压缩,删除目录)
2013/02/03 PHP
coreseek 搜索英文的问题详解
2013/06/08 PHP
php绘图中显示不出图片的原因及解决
2014/03/05 PHP
PHP使用socket发送HTTP请求的方法
2016/02/14 PHP
在TP5数据库中四个字段实现无限分类的示例
2019/10/18 PHP
js 屏蔽鼠标右键脚本附破解方法
2009/12/03 Javascript
简略说明Javascript中的= =(等于)与= = =(全等于)区别
2013/04/16 Javascript
基于javascipt-dom编程 table对象的使用
2013/04/22 Javascript
js实现商城星星评分的效果
2015/12/29 Javascript
js定义类的几种方法(推荐)
2016/06/08 Javascript
前端编码规范(3)JavaScript 开发规范
2017/01/21 Javascript
仿淘宝JSsearch搜索下拉深度用法
2018/01/15 Javascript
详解vue-cli 本地开发mock数据使用方法
2018/05/29 Javascript
jQuery实现下拉菜单动态添加数据点击滑出收起其他功能
2018/06/14 jQuery
vue中$set的使用(结合在实际应用中遇到的坑)
2018/07/10 Javascript
详解angular分页插件tm.pagination二次触发问题解决方案
2018/07/20 Javascript
cordova+vue+webapp使用html5获取地理位置的方法
2019/07/06 Javascript
JavaScript实现的联动菜单特效示例
2019/07/08 Javascript
微信小程序实现手指拖动选项排序
2020/04/22 Javascript
详解Python中的多线程编程
2015/04/09 Python
python matplotlib画图实例代码分享
2017/12/27 Python
Python 实现Serial 与STM32J进行串口通讯
2019/12/18 Python
django数据模型(Model)的字段类型解析
2019/12/25 Python
CentOS7下安装python3.6.8的教程详解
2020/01/03 Python
Python3实现英文字母转换哥特式字体实例代码
2020/09/01 Python
python把一个字符串切开的实例方法
2020/09/27 Python
大学生个人求职信范文
2013/09/21 职场文书
租赁意向书范本
2014/04/01 职场文书
投标服务承诺书
2014/05/28 职场文书
机电一体化毕业生自荐信
2014/06/19 职场文书
大三学年自我鉴定范文(3篇)
2014/09/28 职场文书
2014年环保工作总结
2014/11/26 职场文书
股东大会通知
2015/04/24 职场文书
巴黎圣母院观后感
2015/06/10 职场文书
初中语文教学反思范文
2016/03/03 职场文书