Search code examples
matlabvideobufferrgbyuv

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

Solution

  • 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);