Domanda

Ho fatto una domanda simile prima e non sono riuscito a trovare un diretto Rispondere.

Qualcuno potrebbe fornire codice di esempio per estrarre il buffer di profondità del rendering di un oggetto in una figura in MATLAB?

Quindi diciamo che carichi un file OBJ o anche solo una semplice chiamata di surf, lo rendi e ora voglio raggiungere il suo buffer di profondità, quindi quale codice lo farà per me usando sia Matlab che OpenGL. Cioè come posso impostare questo e quindi accedere ai dati effettivi?

Essenzialmente voglio essere in grado di utilizzare potenti funzioni di tracciamento di Matlab e quindi essere in grado di accedere al contesto grafico sottostante per ottenere il buffer di profondità.

Nota: la taglie specifica Jogl ma non è un must. Qualsiasi codice che agisce come sopra e può fornirmi il buffer di profondità dopo averlo eseguito in matlab)

È stato utile?

Soluzione

depthmap thing

Oggi sono andato a bere con i miei colleghi, e dopo cinque birre e alcuni tequillas ho trovato questa domanda e ho pensato: "Ho a te!" Quindi stavo lottando per un po ', ma poi ho trovato una soluzione semplice usando Mex. Ho teorizzato che il contesto OpenGL, creato dall'ultima finestra, potrebbe essere lasciato attivo e quindi potrebbe essere accessibile da "C", se lo script funzionasse nello stesso thread.

Ho creato un semplice programma "C" che chiama una funzione MATLAB, chiamata "TestofMyFilter" che traccia la risposta in frequenza di un filtro (che era l'unico script che avevo a portata di mano). Questo è reso usando OpenGL. Quindi il programma utilizza GlgetViewport () e GLREADPIXELS () per raggiungere i buffer OpenGL. Quindi crea una matrice, la riempie con i valori di profondità e la passa alla seconda funzione, chiamata "TrytodisplayDepthmap". Visualizza semplicemente la mappa di profondità usando la funzione IMSHOW. Si noti che anche la funzione MEX è autorizzata a restituire i valori, quindi forse la postprocessing non dovrebbe essere un'altra funzione, ma non sono in grado di capire come è fatto. Dovrebbe essere banale, però. Sto lavorando con Mex per la prima volta oggi.

Senza ulteriori ritardi, ci sono codici di origine che ho usato:

TestofMyFilter.m

imp = zeros(10000,1);
imp(5000) = 1;
% impulse

[bwb,bwa] = butter(3, 0.1, 'high');
b = filter(bwb, bwa, imp);
% filter impulse by the filter

fs = 44100; % sampling frequency (all frequencies are relative to fs)
frequency_response=fft(b); % calculate response (complex numbers)
amplitude_response=20*log10(abs(frequency_response)); % calculate module of the response, convert to dB
frequency_axis=(0:length(b)-1)*fs/length(b); % generate frequency values for each response value
min_f=2;
max_f=fix(length(b)/2)+1; % min, max frequency

figure(1);
lighting gouraud
set(gcf,'Renderer','OpenGL')

semilogx(frequency_axis(min_f:max_f),amplitude_response(min_f:max_f),'r-') % plot with logarithmic axis using red line
axis([frequency_axis(min_f) frequency_axis(max_f) -90 10])  % set axis limits

xlabel('frequency [Hz]');
ylabel('amplitude [dB]'); % legend

grid on % draw grid

test.c

//You can include any C libraries that you normally use
#include "windows.h"
#include "stdio.h"
#include "math.h"
#include "mex.h"   //--This one is required

extern WINAPI void glGetIntegerv(int n_enum, int *p_value);

extern WINAPI void glReadPixels(int     x, 
    int     y, 
    int     width, 
    int     height, 
    int     format, 
    int     type, 
    void *      data);

#define GL_VIEWPORT                       0x0BA2
#define GL_DEPTH_COMPONENT                0x1902
#define GL_FLOAT                          0x1406

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    int viewport[4], i, x, y;
    int colLen;
    float *data;
    double *matrix;
    mxArray *arg[1];

    mexCallMATLAB(0, NULL, 0, NULL, "testofmyfilter");
    // call an .m file which creates OpenGL window and draws a plot inside

    glGetIntegerv(GL_VIEWPORT, viewport);
    printf("GL_VIEWPORT = [%d, %d, %d, %d]\n", viewport[0], viewport[1], viewport[2], viewport[3]);
    // print viewport dimensions, should be [0, 0, m, n]
    // where m and n are size of the GL window

    data = (float*)malloc(viewport[2] * viewport[3] * sizeof(float));
    glReadPixels(0, 0, viewport[2], viewport[3], GL_DEPTH_COMPONENT, GL_FLOAT, data);
    // alloc data and read the depth buffer

    /*for(i = 0; i < 10; ++ i)
        printf("%f\n", data[i]);*/
    // debug

    arg[0] = mxCreateNumericMatrix(viewport[3], viewport[2], mxDOUBLE_CLASS, mxREAL);
    matrix = mxGetPr(arg[0]);
    colLen = mxGetM(arg[0]);
    printf("0x%08x 0x%08x 0x%08x %d\n", data, arg[0], matrix, colLen); // debug
    for(x = 0; x < viewport[2]; ++ x) {
        for(y = 0; y < viewport[3]; ++ y)
            matrix[x * colLen + y] = data[x + (viewport[3] - 1 - y) * viewport[2]];
    }
    // create matrix, copy data (this is stupid, but matlab switches
    // rows/cols, also convert float to double - but OpenGL could have done that)

    free(data);
    // don't need this anymore

    mexCallMATLAB(0, NULL, 1, arg, "trytodisplaydepthmap");
    // pass the array to a function (returnig something from here
    // is beyond my understanding of mex, but should be doable)

    mxDestroyArray(arg[0]);
    // cleanup

    return;
}

trytodisplaydepthmap.m:

function [] = trytodisplaydepthmap(depthMap)

figure(2);
imshow(depthMap, []);
% see what's inside

Salva tutti questi nella stessa directory, compila test.c con (digitalo su matlab console):

mex test.c Q:\MATLAB\R2008a\sys\lcc\lib\opengl32.lib

Dove "Q: matlab r2008a sys lcc lib opengl32.lib" è il percorso del file "OpenGl32.lib".

E infine esegui tutto semplicemente digitando "test" nella console Matlab. Dovrebbe far apparire una finestra con la risposta in frequenza del filtro e un'altra finestra con il buffer di profondità. Nota che i buffer anteriori e posteriori vengono scambiati al momento in cui il codice "C" legge il buffer di profondità, quindi potrebbe essere necessario eseguire due volte lo script per ottenere risultati (quindi il buffer anteriore che ora contiene di nuovo gli swap sui risultati con il buffer posteriore, e la profondità può essere letta). Questo potrebbe essere fatto automaticamente da "C" o puoi provare a includere GetFrame (GCF); Alla fine della sceneggiatura (che torna anche da OpenGL, quindi scambia i buffer per te o qualcosa del genere).

Questo funziona per me in Matlab 7.6.0.324 (R2008A). Lo script funziona e sputa quanto segue:

>>test
GL_VIEWPORT = [0, 0, 560, 419]
0x11150020 0x0bd39620 0x12b20030 419

E ovviamente visualizza le immagini. Nota che la gamma di tamponi di profondità dipende da MATLAB e può essere piuttosto elevato, quindi dare un senso alle immagini generate potrebbe non essere semplice.

Altri suggerimenti

il suinoLa risposta è quella corretta. Ecco una versione leggermente formattata e più semplice che è multipiattaforma.

Crea un file chiamato mexgetdepth.c

#include "mex.h"   

#define GL_VIEWPORT                       0x0BA2
#define GL_DEPTH_COMPONENT                0x1902
#define GL_FLOAT                          0x1406

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
    int viewport[4], i, x, y;
    int colLen;
    float *data;
    double *matrix;

    glGetIntegerv(GL_VIEWPORT, viewport);
    data = (float*)malloc(viewport[2] * viewport[3] * sizeof(float));
    glReadPixels(0, 0, viewport[2], viewport[3], GL_DEPTH_COMPONENT, GL_FLOAT, data);

    plhs[0] = mxCreateNumericMatrix(viewport[3], viewport[2], mxDOUBLE_CLASS, mxREAL);
    matrix = mxGetPr(plhs[0]);
    colLen = mxGetM(plhs[0]);

    for(x = 0; x < viewport[2]; ++ x) {
        for(y = 0; y < viewport[3]; ++ y)
            matrix[x * colLen + y] = data[x + (viewport[3] - 1 - y) * viewport[2]];
    }

    free(data);
    return;
}

Quindi se si ottiene la compilazione di Windows utilizzando

mex mexGetDepth.c "path to OpenGL32.lib"

o se sei su un sistema Nix

mex mexGetDepth.c "path to opengl32.a"

Quindi eseguire il seguente piccolo script per testare la nuova funzione

peaks;
figure(1);
depthData=mexGetDepth;
figure
imshow(depthData);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top