Hoy en día, fui a beber con mis colegas, y después de cinco cervezas y algunos tequillas he encontrado esto pregunta y pensamiento, "¡ya te tengo!" Así que estuve luchando por un tiempo, pero luego encontré una solución simple usando MEX. Teoricé que el contexto de OpenGL, creado por la última ventana, podría permanecer activo y, por lo tanto, podría accederse desde "C", si el script se ejecutó en el mismo hilo.
Creé un sencillo programa "C" que llama a una función de matlab, llamada "testofmyfilter" que traza la respuesta de frecuencia de un filtro (que era el único script que tenía a mano). Esto se representa usando OpenGL. Luego, el programa usa glGetViewport() y glReadPixels() para acceder a los búferes de OpenGL. Luego crea una matriz, la rellena con los valores de profundidad y la pasa a la segunda función, llamada "trytodisplaydepthmap". Simplemente muestra el mapa de profundidad con la función imshow. Tenga en cuenta que la función MEX también puede devolver valores, por lo que tal vez el postprocesamiento no tenga que ser otra función, pero no estoy en condiciones de poder entender cómo se hace. Sin embargo, debería ser trivial. Estoy trabajando con MEX por primera vez hoy.
Sin más demora, hay códigos fuente I utilizados:
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
Guarde todo de th ESE en el mismo directorio, compilar test.c con (tipo que a la consola de Matlab):
mex test.c Q:\MATLAB\R2008a\sys\lcc\lib\opengl32.lib
donde "Q: \ MATLAB \ R2008a \ sys \ lcc \ lib \ opengl32.lib" es el camino a "opengl32 archivo .lib ".
Y finalmente ejecútelo simplemente escribiendo "test" en la consola de matlab. Debería mostrar una ventana con respuesta de frecuencia de filtro y otra ventana con el búfer de profundidad. Tenga en cuenta que los búferes anterior y posterior se intercambian en el momento en que el código "C" lee el búfer de profundidad, por lo que puede ser necesario ejecutar el script dos veces para obtener resultados (por lo que el búfer frontal que ahora contiene los intercambios se intercambia con búfer de nuevo, y la profundidad se puede leer).Esto se puede hacer automáticamente con "C", o puede intentar incluir getframe (gcf); al final de su script (que también se lee desde OpenGL para que intercambie los buffers por usted, o algo así).
Esto funciona para mí en Matlab 7.6.0.324 (R2008a). La secuencia de comandos se ejecuta y escupe lo siguiente:
>>test
GL_VIEWPORT = [0, 0, 560, 419]
0x11150020 0x0bd39620 0x12b20030 419
Y, por supuesto, muestra las imágenes. Tenga en cuenta que el rango del búfer de profundidad depende de Matlab, y puede ser bastante alto, por lo que tener sentido de las imágenes generadas puede no ser sencillo.
siempre puede tratar de ofrecer una recompensa para aumentar la atención que recibe una pregunta. – PeterT
Tengo la intención pero solo descubrí cuando publiqué la pregunta que necesito esperar dos días hasta que esta pregunta actual sea elegible. – twerdster
¿Aceptas respuestas que involucren solo a Matlab? No tengo idea sobre JOGL. –