Renderizar la figura de MATLAB en la memoria

¿Hay alguna alternativa al uso de getframe y getframe para guardar el contenido de una figura en una imagen rasterizada para su posterior procesamiento?

Enfoque 1: getframe

 h = figure('visible', 'off'); a = axes('parent', h); % render using `scatter3()` or other plot function. content = frame2im(getframe(h)); 

Esto tiene el serio inconveniente de mostrar la figura para realizar una captura de pantalla en la llamada a getframe() y es problemático cuando se realiza dicha reproducción en un bucle (es decir, guardar el content en cada iteración como un fotogtwig de video).

Enfoque 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'); 

Este enfoque tiene el serio inconveniente de escribir en el disco, lo cual es problemático en aplicaciones multiproceso, además de ser más lento que el renderizado directo a la memoria. Como saveas() obviamente renderizará en la memoria antes de invocar el codificador PNG, lo que deseo es posible, pero no puedo encontrar ninguna función en la documentación de MATLAB que solo realiza la parte de representación.

Pregunta :

¿Conoces una forma alternativa de representar un contenido de axes arbitrario en una imagen de ttwig?

Si crea un archivo avi con avifile y luego le agrega marcos con addframe , MATLAB no abrirá figuras visibles adicionales como lo hace con getframe .

 avi = avifile('/path/to/output'); figure_handle = figure('visible', 'off'); % ... for something = 1:1000 cla % (draw stuff...) avi = addframe(avi, figure_handle); end 

Me doy cuenta de que este es un hilo viejo, pero me encontré con este problema nuevamente, así que quería resumir mis hallazgos. Mi fuente principal es esta página (en caché ). Según él, hay tres alternativas:

  1. utilizando ADDFRAME directamente con el controlador de figura (sin usar GETFRAME ). Esto es exactamente lo que @rescdsk ha demostrado en su respuesta.

     hFig = figure('Visible','off'); aviobj = avifile('file.avi'); for k=1:N %#plot(...) aviobj = addframe(aviobj, hFig); end aviobj = close(aviobj); 
  2. usando PRINT / SAVEAS / HGEXPORT para exportar la figura a un archivo de imagen y luego volver a leer la imagen desde el disco. Este es el enfoque n. ° 2 que usted mencionó en la pregunta anterior.

     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. usando la función HARDCOPY no documentada para capturar la figura en la memoria.

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

    De hecho, esta es la función subyacente que otras funciones usan directa o indirectamente. Al inspeccionar los códigos fuente siempre que sea posible, aquí hay una ilustración de las dependencias de las funciones relacionadas donde A --> B denota 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] 

    Por otro lado, GETFRAME no llama a HARDCOPY sino a una función incorporada no documentada llamada CAPTURESCREEN (aunque parece que usará PRINT para el próximo sistema HG2 donde hay una nueva bandera de impresión -RGBImage ):

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

Nota: Dado que AVIFILE ahora está en desuso, puede reemplazarlo con el VIDEOWRITER más reciente en (2) y (3), pero no en (1), ya que no admite el manejo directo de la figura que pasa.

Inicie MATLAB en modo headless: matlab -noFigureWindows

MATLAB se ejecuta en modo sin cabeza. Las ventanas de la figura no se mostrarán.

simplemente trace y guarde las figuras como de costumbre (no verá ninguna salida gráfica, por supuesto). Ejemplo:

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

Probé lo anterior en una máquina con Windows que ejecuta R2010a. No tengo acceso a una máquina Unix en este momento, pero respondí una pregunta similar en el pasado, y funcionó bien en ese momento (tendrá que desactivar la variable $DISPLAY antes de iniciar MATLAB)


EDITAR

Otra opción, en caso de que desee mantener su espacio de trabajo normal, es iniciar una nueva instancia de MATLAB en el fondo que generará y guardará las plots ( fuente ).

Ejecute esto desde el símbolo del sistema de su sesión actual de MATLAB (todos en la misma línea):

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

Esto iniciará una nueva sesión de MATLAB en segundo plano (usando COM Automation) y ejecutará un script llamado myscript (un simple archivo M) que contiene todo su código de trazado:

c: \ yourpath \ myscript.m

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

Con avifile obsoleto, así es como lo haces con 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);