Rendre la figure MATLAB en mémoire

Existe-t-il des alternatives à l'utilisation de getframe et saveas pour sauvegarder le contenu d'une figure dans une image matricielle pour traitement ultérieur?

approche 1: getframe

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

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

content = frame2im(getframe(h));

ceci a le grave inconvénient de montrer la figure pour effectuer une capture d'écran dans l'appel à getframe() et il est problématique lors de l'exécution d'un tel rendu dans une boucle (c.-à-d. sauver content à chaque itération en tant que cadre vidéo).

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

cette approche a le sérieux inconvénient d'écrire sur le disque, ce qui est problématique dans les applications multithread, en plus d'être plus lent que le rendu directement en mémoire. Puisque saveas() va évidemment rendre en mémoire avant d'invoquer L'encodeur PNG, ce que je veux est possible, mais je ne trouve aucune fonction dans la documentation de MATLAB. qui n'exécute que la partie de rendu.

Question :

connaissez-vous une autre façon de rendre un contenu axes arbitraire à une image matricielle?

23
demandé sur Cœur 2010-11-09 22:29:47

4 réponses

si vous créez un fichier avi avec avifile , puis y ajoutez des cadres avec addframe , MATLAB n'ouvre pas de figures supplémentaires visibles comme il le fait avec getframe .

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

% ...
for something = 1:1000
    cla
    % (draw stuff...)
    avi = addframe(avi, figure_handle);
end
8
répondu rescdsk 2012-09-20 18:23:09

je me rends compte que c'est un vieux fil, mais j'ai rencontré ce problème à nouveau récemment, donc je voulais résumer mes conclusions. Ma source principale est cette page ( en cache ). Selon lui, il existe trois alternatives:

  1. utilisant ADDFRAME directement avec le manche de la figure (sans utiliser GETFRAME ). C'est exactement ce que @rescdsk a montré dans sa réponse.

    hFig = figure('Visible','off');
    
    aviobj = avifile('file.avi');
    for k=1:N
        %#plot(...)
        aviobj = addframe(aviobj, hFig);
    end
    aviobj = close(aviobj);
    
  2. utilisant PRINT / SAVEAS / HGEXPORT pour exporter la figure vers un fichier image, puis la lecture de l'image à partir du disque. C'est l'approche n ° 2 que vous indiquez vous-même dans la question ci-dessus.

    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. utilisant la fonction de copie papier non documentée pour saisir la figure en mémoire.

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

    en fait, c'est la fonction sous-jacente que d'autres fonctions utilisent directement ou indirectement. En inspectant les codes sources dans la mesure du possible, voici une illustration des dépendances des fonctions associées où A --> B dénote 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]
    

    d'un autre côté, GETFRAME n'appelle pas de copie papier mais une fonction intégrée non documentée appelée CAPTURESCREEN (bien qu'il semble qu'il sera utilisation de L'impression pour le prochain HG2 système où il ya un nouveau -RGBImage drapeau d'impression):

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

Note: depuis AVIFILE est maintenant déprécié, vous pouvez le remplacer par le plus récent VIDEOWRITER dans (2) et (3), mais pas dans (1), car il ne supporte pas la gestion de chiffre de passage directement.

16
répondu Amro 2017-05-23 11:53:26

Démarrer MATLAB dans headless mode: matlab -noFigureWindows

MATLAB fonctionne en mode sans tête. Les fenêtres de Figure ne seront pas affichées.

alors simplement tracer et enregistrer les chiffres comme d'habitude (vous ne verrez pas de sortie graphique, bien sûr). Exemple:

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

j'ai testé ce qui précède sur une machine Windows r2010a. Je n'ai pas accès à une machine Unix en ce moment, mais j'ai répondu question similaire dans le passé, et il a fonctionné très bien à l'époque (vous aurez besoin de désactiver la variable $DISPLAY avant de commencer MATLAB)


modifier

une autre option, dans le cas où vous voulez garder votre espace de travail normal, est de démarrer une nouvelle instance MATLAB en arrière-plan qui générera et sauvegardera les tracés ( source ).

exécutez ceci à partir de l'invite de commande de votre session MATLAB actuelle (tous sur la même ligne):

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

cela lancera une nouvelle session MATLAB en arrière-plan (en utilisant com Automation), et exécutera un script appelé myscript (un simple M-file) qui contient tout votre code de pointage:

c:\yourpath\myscript.m

surf(peaks);
saveas(gcf, 'output.eps');
6
répondu Amro 2017-05-23 12:34:04

avec avifile déprécié, c'est comme ça qu'on fait avec 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);
2
répondu Uri Cohen 2015-05-06 07:18:49