Pregunta

He hecho una pregunta similar antes y no logré encontrar un directo responder.

¿Podría alguien proporcionar un código de muestra para extraer el búfer de profundidad de la representación de un objeto en una figura en MATLAB?

Entonces, digamos que carga un archivo OBJ o incluso una simple llamada de surf, lo representa y ahora quiero llegar a su búfer de profundidad, entonces qué código hará eso por mí usando MATLAB y OpenGL. Es decir, ¿cómo configuro esto y luego acceder a los datos reales?

Básicamente, quiero poder usar funciones de trazado potentes de Matlabs y luego poder acceder al contexto gráfico subyacente para obtener el búfer de profundidad.

Nota: La recompensa especifica JOGL, pero eso no es imprescindible. Cualquier código que actúe como se indica anteriormente y puede proporcionarme el búfer de profundidad después de ejecutarlo en Matlab es suficiente)

¿Fue útil?

Solución

depthmap thing

Hoy, fui a beber con mis colegas, y después de cinco cervezas y algunas tequillas encontré esta pregunta y pensé: "¡Te tengo!" Así que estuve luchando por un tiempo, pero luego encontré una solución simple usando MEX. Teoricé que el contexto OpenGL, creado por la última ventana, podría dejarse activo y, por lo tanto, podría ser accesible desde "C", si el script se ejecutó en el mismo hilo.

Creé un programa simple "C" que llama a una función MATLAB, llamada "testOfMyFilter" que traza la respuesta de frecuencia de un filtro (ese fue el único script que tenía a mano). Esto se representa usando OpenGL. Luego, el programa usa GlGetViewPort () y GlreadPixels () para llegar a los buffers OpenGL. Luego crea una matriz, la llena con los valores de profundidad y la pasa a la segunda función, llamada "TryTodisplayDepThMap". Simplemente muestra el mapa de profundidad utilizando la función Imshow. Tenga en cuenta que la función MEX también puede devolver los valores, por lo que tal vez el postprocesamiento no tenga que ser otra función, pero no estoy en ningún estado para 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 de origen que utilicé:

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 esto en el mismo directorio, compile test.c con (escriba eso en la consola MATLAB):

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

Donde "q: matlab r2008a sys lcc lib opengl32.lib" es ruta al archivo "OpenGL32.Lib".

Y finalmente ejecutarlo todo simplemente escribiendo "prueba" en la consola MATLAB. Debe levantar una ventana con respuesta de frecuencia de filtro y otra ventana con el búfer de profundidad. Tenga en cuenta que los buffers delanteros y posteriores se intercambian en el momento en que el código "C" lee el búfer de profundidad, por lo que podría ser necesario ejecutar el script dos veces para obtener cualquier resultado (por lo que el búfer delantero que ahora contiene los resultados de los resultados con el búfer posterior, y la profundidad se puede leer). Esto podría hacerse automáticamente por "C", o puede intentar incluir GetFrame (GCF); Al final de su guión (que también se lee de OpenGL para que cambie los buffers por usted, o algo así).

Esto funciona para mí en Matlab 7.6.0.324 (R2008A). El script 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 de tampón de profundidad depende de MATLAB, y puede ser bastante alto, por lo que tener cualquier sentido de las imágenes generadas puede no ser sencilla.

Otros consejos

el cerdoLa respuesta es la correcta. Aquí hay una versión ligeramente formateada y más simple que es multiplataforma.

Crea un archivo llamado 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;
}

Entonces si está en Windows compilar usando

mex mexGetDepth.c "path to OpenGL32.lib"

o si estás en un sistema Nix

mex mexGetDepth.c "path to opengl32.a"

Luego ejecute el siguiente script pequeño para probar la nueva función

peaks;
figure(1);
depthData=mexGetDepth;
figure
imshow(depthData);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top