clear
clc
cd('F:\qcifAvi');
myFile = dir('*.avi'); % 无损压缩的.avi文件集合
for i = 1 : length(myFile) % qcifAvi目录下.avi文件的个数为: length(myFile)
name{i} = myFile(i).name(1:length(myFile(i).name)); % .avi文件全名
videoName = name{i};
obj = mmreader(videoName); % multimedia reader
vidFrames = read(obj); % 所有帧
numFrames = obj.numberOfFrames; % 帧数
for k = 1 : min(numFrames, 300)
mov(k).cdata = vidFrames(:,:,:,k);
mov(k).colormap = []; % 不可少
end
fileName{i} = myFile(i).name(1:length(myFile(i).name) - length('-qcif_original.avi')); % .avi文件的部分名
fileName{i} = [fileName{i}, '_qcif.yuv'];
saveFileYuv(mov, fileName{i});
end
% 把mov结构体存成YUV420
function saveFileYuv(mov, fileName)
fid = fopen(fileName, 'w');
dim = size(mov(1).cdata); % dim是一个向量,比如[144 176 3]
height = dim(1);
width = dim(2);
numFrames = length(mov); % numFrames是帧的数量
for f = 1 : numFrames
imgRgb = frame2im(mov(f)); % matlab内部函数
% rgb2yuv (matlab中转换函数常用的命名格式,还比如num2str)
imgYuv = reshape(rgb2yuv(reshape(imgRgb, height * width, 3)), height, width, 3);
% Y分量
buf = reshape(imgYuv(:, :, 1).', [], 1);
fwrite(fid, buf, 'uchar');
% U分量
buf = reshape(imgYuv(1 : 2 : end, 1 : 2 : end, 2).', [], 1); % 下采样
fwrite(fid, buf, 'uchar');
% V分量
buf = reshape(imgYuv(1 : 2 : end, 1 : 2 : end, 3).', [], 1); % 下采样
fwrite(fid, buf, 'uchar');
end
fclose(fid);
function yuv = rgb2yuv(rgbUint8) % rgbUint8是一个矩阵,比如大小为25344*3
[m, n] = size(rgbUint8);
% 下面这个转换非常重要,以前错过,如果是uint8, 那么负数将被转换成0,所以要转成double型
rgb = double(rgbUint8);
% 构造一个零矩阵,便于统一操作,免得用循环. 好方法.
yuv = uint8(zeros(m, 3));
yuv(:, 1) = min( 255, max(0, 0.299 * rgb(:, 1) + 0.587 * rgb(:, 2) + 0.114 * rgb(:, 3)) );
yuv(:, 2) = min( 255, max(0, -0.1687 * rgb(:, 1) - 0.3313 * rgb(:, 2) + 0.5 * rgb(:, 3) + 128) );
yuv(:, 3) = min( 255, max(0, 0.5 * rgb(:, 1) - 0.4187 * rgb(:, 2) - 0.0813 * rgb(:, 3) + 128) );