Визуализировать фигуру 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
, а затем добавить кадры к нему с 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
Я понимаю, что это старая тема, но в последнее время я снова столкнулся с этой проблемой, поэтому я хотел обобщить свои выводы. Мой основной источник - эта страница ( кэшированная). Согласно этому есть три альтернативы:
используя ADDFRAME непосредственно с дескриптором рисунка (без использования GETFRAME). Это именно то, что @rescdsk показал в своем ответе.
hFig = figure('Visible','off'); aviobj = avifile('file.avi'); for k=1:N %#plot(...) aviobj = addframe(aviobj, hFig); end aviobj = close(aviobj);
используя 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);
использование недокументированной функции 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);