利用python讀取YUV文件 轉(zhuǎn)RGB 8bit/10bit通用
注:本文所指的YUV均為YUV420中的I420格式(最常見的一種),其他格式不能用以下的代碼。
位深為8bit時(shí),每個(gè)像素占用1字節(jié),對(duì)應(yīng)文件指針的fp.read(1);
位深為10bit時(shí),每個(gè)像素占用2字節(jié),對(duì)應(yīng)文件指針的fp.read(2);
然后使用 int.from_bytes() 方法將二進(jìn)制轉(zhuǎn)換為int型數(shù)字。
以下程序可以讀8bit或10bit位深的YUV,需要指定從第幾幀開始讀、一共讀多少幀。
它返回三個(gè)數(shù)組,其shape分別為:Y [frame,W,H] U [frame,W/2,H/2] V [frame,W/2,H/2]
當(dāng)只讀1幀時(shí)它返回: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)
以下程序?qū)UV轉(zhuǎn)為RGB(只能讀8bit位深的YUV),返回1個(gè)數(shù)組,其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) #跳過(guò)前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幀輸出成一個(gè)png:
ffmpeg -s 176x144 -i akiyo_qcif.yuv -filter:v select="between(n\,8\,8)" out.png
以上這篇利用python讀取YUV文件 轉(zhuǎn)RGB 8bit/10bit通用就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
python代碼實(shí)現(xiàn)圖書管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了python代碼實(shí)現(xiàn)圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11
python判斷字符串編碼的簡(jiǎn)單實(shí)現(xiàn)方法(使用chardet)
這篇文章主要介紹了python判斷字符串編碼的簡(jiǎn)單實(shí)現(xiàn)方法,涉及chardet模塊的安裝與簡(jiǎn)單使用方法,需要的朋友可以參考下2016-07-07
PyCharm安裝庫(kù)numpy失敗問(wèn)題的詳細(xì)解決方法
今天使用pycharm編譯python程序時(shí),由于要調(diào)用numpy包,但又未曾安裝numpy,于是就根據(jù)pycharm的提示進(jìn)行安裝,最后竟然提示出錯(cuò),下面這篇文章主要給大家介紹了關(guān)于PyCharm安裝庫(kù)numpy失敗問(wèn)題的詳細(xì)解決方法,需要的朋友可以參考下2022-06-06
Python3利用Qt5實(shí)現(xiàn)簡(jiǎn)易的五子棋游戲
這篇文章主要為大家詳細(xì)介紹了Python3利用Qt5實(shí)現(xiàn)簡(jiǎn)易的五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05
Python實(shí)現(xiàn)登陸文件驗(yàn)證方法
本篇文章中我們給大家分享了關(guān)于Python實(shí)現(xiàn)登陸文件驗(yàn)證的方法和技巧,有興趣的朋友們參考學(xué)習(xí)下。2018-10-10
對(duì)Python中列表和數(shù)組的賦值,淺拷貝和深拷貝的實(shí)例講解
今天小編就為大家分享一篇對(duì)Python中列表和數(shù)組的賦值,淺拷貝和深拷貝的實(shí)例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-06-06

