![depthmap thing](https://i.stack.imgur.com/mdxLq.png)
Oggi, sono andato a bere con i miei colleghi, e dopo cinque birre e alcuni tequillas ho trovato questo domanda e pensiero, "ho a voi!" Così ho sofferto 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 è eseguito 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 utilizzando OpenGL. Quindi il programma utilizza glGetViewport() e glReadPixels() per ottenere i buffer OpenGL. Quindi crea una matrice, la riempie con i valori di profondità e la passa alla seconda funzione, chiamata "trytodisplaydepthmap". Mostra solo la mappa di profondità usando la funzione imshow. Si noti che la funzione MEX può anche restituire valori, quindi forse la postelaborazione non dovrebbe essere un'altra funzione, ma non sono in grado di capire come è fatta. Dovrebbe essere banale, però. Oggi sto lavorando con MEX per la prima volta.
Senza ulteriore ritardo, ci sono codici sorgenti I usati:
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 tutto di th ese nella stessa directory, compilare test.c con (tipo quella di console Matlab):
mex test.c Q:\MATLAB\R2008a\sys\lcc\lib\opengl32.lib
Dove "D: \ MATLAB \ R2008a \ sys \ LCC \ lib \ opengl32.lib" è percorso a "opengl32 .lib "file.
Infine, eseguire 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à. Si noti che i buffer fronte e retro sono scambiati nel momento in cui il codice "C" legge il buffer di profondità, quindi potrebbe essere necessario eseguire lo script due volte per ottenere qualsiasi risultato (quindi il buffer frontale che ora contiene nuovamente i risultati con back buffer, e la profondità può essere letta).Questo potrebbe essere fatto automaticamente da "C", oppure puoi provare includendo getframe (gcf); alla fine del tuo script (che si legge 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 esegue e sputa quanto segue:
>>test
GL_VIEWPORT = [0, 0, 560, 419]
0x11150020 0x0bd39620 0x12b20030 419
E ovviamente visualizza le immagini. Notare che la gamma del buffer di profondità dipende da Matlab e può essere piuttosto elevata, quindi non è facile dare un senso alle immagini generate.
si può sempre provare a offrire una taglia per aumentare l'attenzione che riceve una domanda. – PeterT
Intendo, ma ho scoperto solo quando ho postato la domanda che ho bisogno di aspettare due giorni fino a quando questa domanda attuale diventa ammissibile. – twerdster
Accettate le risposte che riguardano solo Matlab? Non ho idea di JOGL. –