views:

44

answers:

2

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);
A: 

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);
Jonas
I use the following codes to trigger loadFileYuv function. Do you think it's correct? nFrames=2000; mov(1:nFrames)=struct('cdata',zeros(352,288,3,'uint8'),'colormap',[]);for k=1:nFrames mov(k).cdata=loadFileYuv(...); end
appi
@yoursclark: That looks correct, as long as you pass `k` as your fourth input argument. Does it work?
Jonas
Hi Jonas. Thanks for your fast reply. I put k as the fourth input argument in loadFileYuv() function. But when I try to show the content of cdata by typing 'mov(1).cdata', the pixels turn out to be all zeros, which means the frame data is not stored in the cdata field, isn't it?
appi
@yoursclark: It certainly looks like it. I suggest you put a breakpoint into the file `loadFileYuv` (click on the dash next to one of the first line numbers in the editor, and a red dot should appear; when the function stops executing, you can step through with the `step` button in the toolbar). This will let you find out whether `loadFileYUV` is working properly. Hover over variable names or look at them in the array editor to see whether they're all zero.
Jonas
Thanks Jonas. Following your suggestion, I successfully get the YUV components that I want. Thanks for your explanatioin!
appi
A: 

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
    ...
yuk
Thanks yuk! You are right. There is no need to return imgRgb because it is not what I want. Thanks for pointing that out!
appi