How to extract Y,U, and V components from a given yuv file using Matlab? Each component is used for further pixels level manipulation
문제
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);
해결책
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);
다른 팁
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
...