Как извлечь компоненты Y, U и V из данного файла yuv с помощью Matlab? Каждый компонент используется для дальнейшего манипулирования уровнем пикселей.

Привет, ребята. В настоящее время я играю с файлом YUV. Есть ли у вас какие-либо предложения о том, как извлечь компоненты y, u, v из видео yuv? Я найдено фрагмент программы, показанный ниже. Но я не знаю, какая часть является допустимыми компонентами, которые мне нужны. Спасибо.

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

person view    schedule 08.10.2010    source источник


Ответы (2)


Не уверен, есть ли у меня какое-то фундаментальное непонимание файлов YUV, но если вы отредактируете функцию, как я сделал ниже, у вас будут компоненты YUV для каждого кадра в одной переменной с именем imgYUV. Обратите внимание, что в процессе у вас может закончиться память, возможно, вы не хотите загружать все кадры фильма за один раз.

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);
person Jonas    schedule 10.10.2010
comment
Я использую следующие коды для запуска функции loadFileYuv. Как вы думаете, это правильно? количество кадров=2000; mov(1:nFrames)=struct('cdata',zeros(352,288,3,'uint8'),'colormap',[]);for k=1:nFrames mov(k).cdata=loadFileYuv(... ); конец - person view; 11.10.2010
comment
@yoursclark: Это выглядит правильно, если вы передаете k в качестве четвертого входного аргумента. Это работает? - person Jonas; 11.10.2010
comment
Привет Йонас. Спасибо за быстрый ответ. Я поставил k в качестве четвертого входного аргумента в функции loadFileYuv(). Но когда я пытаюсь показать содержимое cdata, набрав 'mov(1).cdata', все пиксели оказываются нулями, что означает, что данные кадра не хранятся в поле cdata, не так ли? - person view; 11.10.2010
comment
@yoursclark: Это действительно похоже на это. Я предлагаю вам поставить точку останова в файле loadFileYuv (нажмите на тире рядом с одним из первых номеров строк в редакторе, и должна появиться красная точка; когда функция перестанет выполняться, вы можете перейти с помощью кнопки step в панель инструментов). Это позволит вам узнать, правильно ли работает loadFileYUV. Наведите указатель мыши на имена переменных или посмотрите на них в редакторе массивов, чтобы увидеть, все ли они равны нулю. - person Jonas; 11.10.2010
comment
Спасибо Джонас. Следуя вашему предложению, я успешно получаю компоненты YUV, которые мне нужны. Спасибо за ваше объяснение! - person view; 11.10.2010

Я бы просто изменил определение функции:

function [mov,imgYuv] = loadFileYuv(fileName, width, height, idxFrame)

Нет необходимости возвращать imgRgb, так как это то же самое, что и mov(numel(idxFrame)).cdata.

Укажите две выходные переменные, и вы получите YUV-компоненты последнего кадра во второй переменной.


Я бы изменил функцию, чтобы проверить, пуст ли буфер, чтобы избежать ошибки, если вы запрашиваете больше кадров, чем содержит файл.

    ...
    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
    ...
person yuk    schedule 11.10.2010
comment
Спасибо юк! Ты прав. Нет необходимости возвращать imgRgb, потому что это не то, что я хочу. Спасибо что подметил это! - person view; 11.10.2010