用python读取YUV文件 转RGB 8bit/10bit通用
生活随笔
收集整理的這篇文章主要介紹了
用python读取YUV文件 转RGB 8bit/10bit通用
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
注:本文所指的YUV均為YUV420中的I420格式(最常見(jiàn)的一種),其他格式不能用以下的代碼。
位深為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,需要指定從第幾幀開(kāi)始讀、一共讀多少幀。
它返回三個(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 pltdef readyuv420(filename, bitdepth, W, H, startframe, totalframe, show=False):# 從第startframe(含)開(kāi)始讀(0-based),共讀totalframe幀uv_H = H // 2uv_W = W // 2if 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 // 2fp = 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,Vif __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 pltdef yuv2rgb(yuvfilename, W, H, startframe, totalframe, show=False, out=False):# 從第startframe(含)開(kāi)始讀(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 // 2fp.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_RGBreturn arrif __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?
總結(jié)
以上是生活随笔為你收集整理的用python读取YUV文件 转RGB 8bit/10bit通用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 3d可视化软件之管理驾驶舱,3d管理驾驶
- 下一篇: 人工智能的终局:让机器理解人类的思维方式