Визуализировать фигуру MATLAB в памяти

Есть ли альтернативы использованию getframe а также saveas для сохранения содержимого рисунка в растровое изображение для дальнейшей обработки?

Подход 1:getframe

h = figure('visible', 'off');
a = axes('parent', h);

% render using `scatter3()` or other plot function.

content = frame2im(getframe(h));

Это имеет серьезный недостаток - показывать фигуру для выполнения снимка экрана при вызове getframe() и это проблематично при выполнении такого рендеринга в цикле (т.е. сохранение content на каждой итерации как видеокадр).

Подход 2:saveas

h = figure('visible', 'off');
a = axes('parent', h);

% render using `scatter3()` or other plot function.

saveas(h, '/path/to/file.png');
content = imread(/path/to/file.png');

Этот подход имеет серьезный недостаток записи на диск, что проблематично в многопоточных приложениях, а также медленнее, чем рендеринг непосредственно в память. поскольку saveas() Очевидно, что будет выполняться рендеринг в память перед вызовом PNG-кодировщика, то, что я хочу, возможно, но я не могу найти какую-либо функцию в документации MATLAB, которая выполняет только часть рендеринга.

Вопрос:

Знаете ли вы об альтернативном способе рендеринга произвольного axes контент для растрового изображения?

4 ответа

Решение

Если вы создаете файл AVI с avifile, а затем добавить кадры к нему с addframeMATLAB не открывает дополнительные видимые фигуры, как с getframe,

avi = avifile('/path/to/output');
figure_handle = figure('visible', 'off');

% ...
for something = 1:1000
    cla
    % (draw stuff...)
    avi = addframe(avi, figure_handle);
end

Я понимаю, что это старая тема, но в последнее время я снова столкнулся с этой проблемой, поэтому я хотел обобщить свои выводы. Мой основной источник - эта страница ( кэшированная). Согласно этому есть три альтернативы:

  1. используя ADDFRAME непосредственно с дескриптором рисунка (без использования GETFRAME). Это именно то, что @rescdsk показал в своем ответе.

    hFig = figure('Visible','off');
    
    aviobj = avifile('file.avi');
    for k=1:N
        %#plot(...)
        aviobj = addframe(aviobj, hFig);
    end
    aviobj = close(aviobj);
    
  2. используя PRINT/ SAVEAS/ HGEXPORT для экспорта рисунка в файл изображения, затем считывая изображение обратно с диска. Это подход № 2, который вы перечислили себе в вопросе выше.

    hFig = figure('Visible','off');
    set(hFig, 'PaperPositionMode','auto', 'InvertHardCopy','off')
    
    aviobj = avifile('file.avi');
    for k=1:N
        %#plot(...)
        print(['-f' num2str(hFig)], '-zbuffer', '-r0', '-dpng', 'file.png')
        img = imread('file.png');
        aviobj = addframe(aviobj, im2frame(img));
    end
    aviobj = close(aviobj);
    
  3. использование недокументированной функции HARDCOPY для захвата фигуры в памяти.

    hFig = figure('Visible','off');
    set(hFig, 'PaperPositionMode','auto')
    
    aviobj = avifile('file.avi');
    for k=1:N
        %#plot(...)
        img = hardcopy(hFig, '-dzbuffer', '-r0');
        aviobj = addframe(aviobj, im2frame(img));
    end
    aviobj = close(aviobj);
    

    Фактически, это основная функция, которую другие функции используют прямо или косвенно. Изучая исходные коды, где это возможно, приведем иллюстрацию зависимостей связанных функций, где A --> B обозначает A calls B:

    saveas [M-file] --> print [M-file] --> render [private M-file] --> hardcopy [P-file]
    hgexport [P-file] --> print [M-file] --> ...
    @avifile/addframe [M-file] --> hardcopy [P-file]
    

    С другой стороны, GETFRAME вызывает не HARDCOPY, а недокументированную встроенную функцию с именем CAPTURESCREEN (хотя кажется, что она будет использовать PRINT для будущей системы HG2, где есть новая -RGBImage печать флага):

    getframe [M-file] --> capturescreen [builtin]
    

Примечание. Поскольку AVIFILE теперь устарел, вы можете заменить его более новым VIDEOWRITER в (2) и (3), но не в (1), поскольку он не поддерживает непосредственную передачу дескриптора фигуры.

Запустите MATLAB в режиме без головы: matlab -noFigureWindows

MATLAB работает в режиме без головы. Рисунок окна не будет отображаться.

затем просто нанесите и сохраните цифры как обычно (конечно, вы не увидите никакого графического вывода). Пример:

surf(peaks);
print output.eps     %# SAVEAS works as well
close

Я протестировал вышеупомянутое на машине под управлением Windows R2010a. У меня нет доступа к Unix-машине прямо сейчас, но я отвечал на аналогичный вопрос в прошлом, и в то время он работал нормально (вам нужно будет сбросить $DISPLAY переменная перед запуском MATLAB)


РЕДАКТИРОВАТЬ

Другой вариант, если вы хотите сохранить свое обычное рабочее пространство, это запустить новый экземпляр MATLAB в фоновом режиме, который будет генерировать и сохранять графики ( исходные).

Запустите это из командной строки вашего текущего сеанса MATLAB (все в одной строке):

!start /B /MIN matlab -noFigureWindows 
                      -automation 
                      -r "cd('c:\yourpath'); myscript; quit"

Это запустит новый сеанс MATLAB в фоновом режиме (с использованием COM Automation) и выполнит скрипт с именем myscript (простой M-файл), который содержит весь ваш код для построения:

C:\yourpath\myscript.m

surf(peaks);
saveas(gcf, 'output.eps');

С avifile будучи устаревшим, вот как вы делаете это с VideoWriter:

hFig = figure('Visible','off');
set(hFig, 'PaperPositionMode','auto')

aviobj = VideoWriter('file','Archival');
for k=1:N
    %#plot(...)
    img = hardcopy(hFig, '-dzbuffer', '-r0');
    writeVideo(aviobj, im2frame(img));
end
close(aviobj);
Другие вопросы по тегам