Отобразить фигуру 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
растровому изображению?
Ответы
Ответ 1
Если вы создаете 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
Ответ 2
Я понимаю, что это старый поток, но я снова столкнулся с этой проблемой в последнее время, поэтому хотел обобщить мои выводы. Мой основной источник эта страница (кешировано). В соответствии с этим существует три альтернативы:
-
используя 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), так как он не поддерживает прямой передатчик фигуры.
Ответ 3
Запустите 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) и выполнит script, называемый myscript
(простой M файл), содержащий весь ваш код построения:
C:\yourpath\myscript.m
surf(peaks);
saveas(gcf, 'output.eps');
Ответ 4
Если 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);