最近做图像压缩方面的一些工作,处理的是yuv格式的视频,这也是HEVC编码中常用的压缩格式.
问题,从yuv视频流中读取到Y,U,V,三个分量后,进行处理.有了处理后的Y,U,V三个,分量怎么可以快速合成yuv视频,进行压缩编码,查了下,都是用C++写的,一时间没怎么细看,找到一段很简单的Matlab代码.
1.yuv视频读取(python):
下面是8bit和10bit yuv视频文件读取代码
def yuv_import_8_bits(filename, dims ,startfrm,numframe):
fp = open(filename, 'rb')
frame_size = np.prod(dims) * 3 / 2
fp.seek(0, 2)#文件首尾指针
ps = fp.tell() # 当前文件指针位置
totalfrm = int(ps // frame_size) # 计算输出帧数
d00 = dims[0] // 2
d01 = dims[1] // 2
# print('num',totalfrm,filename)
# numfrm = totalfrm - startfrm
assert startfrm+numframe<=totalfrm
Y = np.zeros(shape=(numframe, 1,dims[0], dims[1]), dtype=np.uint8, order='C')
U = np.zeros(shape=(numframe, 1,d00, d01),dtype= np.uint8, order='C')
V = np.zeros(shape=(numframe, 1,d00, d01),dtype= np.uint8, order='C')
fp.seek(int(frame_size * startfrm), 0)
for i in range(startfrm,startfrm+numframe):
for m in range(dims[0]):
for n in range(dims[1]):
pel8bit = int.from_bytes(fp.read(1), byteorder='little',signed=False)
Y[i-startfrm,0, m, n] = np.uint8(pel8bit)
# Y[i-startfrm,0, m, n] = int.from_bytes(fp.read(1), byteorder='little', signed=False)
for m in range(d00):
for n in range(d01):
pel8bit = int.from_bytes(fp.read(1), byteorder='little',signed=False)
U[i-startfrm,0, m, n] = np.uint8(pel8bit)
# U[i-startfrm,0, m, n] = int.from_bytes(fp.read(2), byteorder='little', signed=False)
for m in range(d00):
for n in range(d01):
pel8bit = int.from_bytes(fp.read(1), byteorder='little',signed=False)
V[i-startfrm,0, m, n] = np.uint8(pel8bit)
# V[i-startfrm,0, m, n] = int.from_bytes(fp.read(2), byteorder='little', signed=False)
fp.close()
Y = Y.astype(np.float32)
U = U.astype(np.float32)
V = V.astype(np.float32)
return Y, U, V
def yuv_import_10bits(filename, dims ,startfrm,numframe):
fp = open(filename, 'rb')
frame_size = np.prod(dims) * 3
# fp.seek(0, 2)#文件首尾指针
# ps = fp.tell() # 当前文件指针位置
# totalfrm = int(ps // frame_size) # 计算输出帧数
d00 = dims[0] // 2
d01 = dims[1] // 2
# print('num',totalfrm,filename)
# assert startfrm+numframe<=totalfrm
Y = np.zeros(shape=(numframe, 1,dims[0], dims[1]), dtype=np.uint16, order='C')
U = np.zeros(shape=(numframe, 1,d00, d01),dtype= np.uint16, order='C')
V = np.zeros(shape=(numframe, 1,d00, d01),dtype= np.uint16, order='C')
fp.seek(int(frame_size * startfrm), 0)
for i in range(startfrm,startfrm+numframe):
for m in range(dims[0]):
for n in range(dims[1]):
pel10bit = int.from_bytes(fp.read(2), byteorder='little', signed=False)
Y[i-startfrm,0, m, n] = pel10bit
# print(Y[i-startfrm,0, m, n] )
for m in range(d00):
for n in range(d01):
pel10bit_u = int.from_bytes(fp.read(2), byteorder='little', signed=False)
U[i-startfrm,0, m, n]= pel10bit_u
# U[i-startfrm,0, m, n] = int.from_bytes(fp.read(2), byteorder='little', signed=False)
for m in range(d00):
for n in range(d01):
pel10bit_v = int.from_bytes(fp.read(2), byteorder='little', signed=False)
V[i-startfrm,0, m, n] = pel10bit_v
# V[i-startfrm,0, m, n] = int.from_bytes(fp.read(2), byteorder='little', signed=False)
fp.close()
Y = Y.astype(np.float32)
U = U.astype(np.float32)
V = V.astype(np.float32)
return Y, U, V
2.yuv视频合成(matlab)
close all;
clear all;
clc;
%输出的yuv视频路径
outfid=fopen([yuv_video_folder, '/' ,num2str(video_num-2,'%04d'),'_',num2str(w*2),'x',num2str(h*2),'.yuv'],'wb');
%len:yuv视频的帧数
%h,w:Y通道视频的高度和宽度
for frame_num=1:len
frame_num;
Y_array = imread([Y_image(frame_num).folder,'/',Y_image(frame_num).name]);
U_array = imread([U_image(frame_num).folder,'/',U_image(frame_num).name]);
V_array = imread([V_image(frame_num).folder,'/',V_image(frame_num).name]);
[Y_h,Y_w] = size(Y_array);
[U_h,U_w] = size(U_array);
[V_h,V_w] = size(V_array);
for i1 = 1:Y_h
fwrite(outfid,uint8(Y_array(i1,:)));
end
for i1 = 1:U_h
fwrite(outfid,uint8(U_array(i1,:)));
end
for i1 = 1:V_h
fwrite(outfid,uint8(V_array(i1,:)));
end