Визуализация фигуры MATLAB в памяти - PullRequest
24 голосов
/ 09 ноября 2010

Существуют ли альтернативы использованию 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 ]

17 голосов
/ 26 октября 2012

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

  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), поскольку это не так поддержка передачи фигурной ручки напрямую.

9 голосов
/ 10 ноября 2010

Если вы создаете файл avi с помощью avifile, а затем добавляете в него фреймы с помощью addframe, MATLAB не открывает дополнительные видимые фигуры, как это происходит с getframe.

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

% ...
for something = 1:1000
    cla
    % (draw stuff...)
    avi = addframe(avi, figure_handle);
end
6 голосов
/ 10 ноября 2010

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

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

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

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

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


EDIT

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

Запустите это из командной строки вашего текущего сеанса 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');
2 голосов
/ 06 мая 2015

С устаревшим 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);
...