问题
Hey guys. I'm currently playing with YUV file. Do you have any suggestion on how to extract y,u,v components from a yuv video? I found a piece of program which was shown below. But I don't know which part is the valid components that I want. Thanks.
% function mov = loadFileYuv(fileName, width, height, idxFrame)
function [mov,imgRgb] = loadFileYuv(fileName, width, height, idxFrame)
% load RGB movie [0, 255] from YUV 4:2:0 file
fileId = fopen(fileName, 'r');
subSampleMat = [1, 1; 1, 1];
nrFrame = length(idxFrame);
for f = 1 : 1 : nrFrame
% search fileId position
sizeFrame = 1.5 * width * height;
fseek(fileId, (idxFrame(f) - 1) * sizeFrame, 'bof');
% read Y component
buf = fread(fileId, width * height, 'uchar');
imgYuv(:, :, 1) = reshape(buf, width, height).'; % reshape RESHAPE(X,M,N) returns the M-by-N matrix
%whose elements are taken columnwise from X.
%An error results if X does not have M*N elements
% read U component
buf = fread(fileId, width / 2 * height / 2, 'uchar');
imgYuv(:, :, 2) = kron(reshape(buf, width / 2, height / 2).', subSampleMat); % reshape and upsample
% read V component
buf = fread(fileId, width / 2 * height / 2, 'uchar');
imgYuv(:, :, 3) = kron(reshape(buf, width / 2, height / 2).', subSampleMat); % reshape and upsample
% normalize YUV values
% imgYuv = imgYuv / 255;
% convert YUV to RGB
imgRgb = reshape(convertYuvToRgb(reshape(imgYuv, height * width, 3)), height, width, 3);
% imgRgb = ycbcr2rgb(imgYuv);
%imwrite(imgRgb,'ActualBackground.bmp','bmp');
mov(f) = im2frame(imgRgb);
% mov(f).cdata = uint8(imgRgb);
% mov(f).colormap = [];
% imwrite(imgRgb,'ActualBackground.bmp','bmp');
%figure, imshow(imgRgb);
%name = 'ActualBackground.bmp';
%Image = imread(name, 'bmp');
%figure, imshow(Image);
end
fclose(fileId);
回答1:
Not sure whether I have some fundamental misunderstanding about YUV files, but if you edit the function like I did below, you have the YUV components for every frame in a single variable called imgYUV
. Note that you may run out of memory in the process, you maybe you don't want to load all the frames of the movie in one go.
function imgYUV = loadFileYuv(fileName, width, height, idxFrame)
% load YUV data from YUV 4:2:0 file
fileId = fopen(fileName, 'r');
subSampleMat = [1, 1; 1, 1];
nrFrame = length(idxFrame);
%# preassign imgYUV. In case we can't keep everything in RAM,
%# it is better that the function crashes here, rather than after
%# having wasted time slowly filling up the memory.
%# Since the images are likely to be of class 'uint8',
%# you can save on a lot of memory by initializing
%# imgYUV as zeros(width/2,height/2,3,nrFrame,'uint8');
imgYUV = zeros(width/2 height/2, 3, nrFrame);
for f = 1 : 1 : nrFrame
%# search fileId position
sizeFrame = 1.5 * width * height;
fseek(fileId, (idxFrame(f) - 1) * sizeFrame, 'bof');
%# read Y component
buf = fread(fileId, width * height, 'uchar');
imgYuv(:, :, 1, f) = reshape(buf, width, height).';
%# read U component
buf = fread(fileId, width / 2 * height / 2, 'uchar');
imgYuv(:, :, 2, f) = kron(reshape(buf, width / 2, height / 2).', subSampleMat); % reshape and upsample
% read V component
buf = fread(fileId, width / 2 * height / 2, 'uchar');
imgYuv(:, :, 3, f) = kron(reshape(buf, width / 2, height / 2).', subSampleMat); % reshape and upsample
end
fclose(fileId);
回答2:
I would just change the function definition:
function [mov,imgYuv] = loadFileYuv(fileName, width, height, idxFrame)
There is no need to return imgRgb, since it's the same as mov(numel(idxFrame)).cdata
.
Specify two output variables and you will get YUV components of the last frame in the second variable.
I would change the function to check if buffer is empty to avoid error if you ask for more frames than the file contains.
...
status = fseek(fileId, (idxFrame(f) - 1) * sizeFrame, 'bof');
if status == -1
error('Cannot read frame %d',idxFrame(f));
end
% read Y component
buf = fread(fileId, width * height, 'uchar');
if isempty(buf)
error('Cannot read frame %d',idxFrame(f));
end
imgYuv(:, :, 1) = reshape(buf, width, height).'; % reshape
% read U component
buf = fread(fileId, width / 2 * height / 2, 'uchar');
if isempty(buf)
error('Cannot read frame %d',idxFrame(f));
end
imgYuv(:, :, 2) = kron(reshape(buf, width / 2, height / 2).', subSampleMat); % reshape and upsample
% read V component
buf = fread(fileId, width / 2 * height / 2, 'uchar');
if isempty(buf)
error('Cannot read frame %d',idxFrame(f));
end
...
来源:https://stackoverflow.com/questions/3887494/how-to-extract-y-u-and-v-components-from-a-given-yuv-file-using-matlab-each-co