
Hôm nay, tôi đã đi uống rượu với đồng nghiệp của tôi, và sau năm bia và một số tequillas Tôi thấy điều này câu hỏi và suy nghĩ, "có lúc ya!" Vì vậy, tôi đã đấu tranh một thời gian nhưng sau đó tôi tìm thấy một giải pháp đơn giản bằng cách sử dụng MEX. Tôi giả định rằng bối cảnh OpenGL, được tạo ra bởi cửa sổ cuối cùng, có thể được để lại hoạt động và do đó có thể truy cập từ "C", nếu kịch bản chạy trong cùng một luồng.
Tôi đã tạo một chương trình "C" đơn giản gọi một hàm matlab, được gọi là "testofmyfilter" biểu thị phản hồi tần số của bộ lọc (đó là tập lệnh duy nhất tôi có trong tay). Điều này được hiển thị bằng cách sử dụng OpenGL. Sau đó, chương trình sử dụng glGetViewport() và glReadPixels() để truy cập vào bộ đệm OpenGL. Sau đó, nó tạo ra một ma trận, điền nó với các giá trị độ sâu, và chuyển nó đến hàm thứ hai, được gọi là "trytodisplaydepthmap". Nó chỉ hiển thị độ sâu bằng cách sử dụng hàm imshow. Lưu ý rằng hàm MEX cũng được phép trả về các giá trị, vì vậy có lẽ quá trình hậu xử lý sẽ không phải là một hàm khác, nhưng tôi không có trạng thái nào để có thể hiểu được nó được thực hiện như thế nào. Nên là tầm thường, mặc dù. Tôi đang làm việc với MEX lần đầu tiên ngày hôm nay.
Không chậm trễ hơn nữa, có những mã nguồn tôi đã sử dụng:
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
Lưu tất cả ese vào cùng thư mục, biên dịch test.c với (gõ đó để Matlab console):
mex test.c Q:\MATLAB\R2008a\sys\lcc\lib\opengl32.lib
đâu "Q: \ MATLAB \ R2008a \ sys \ lcc \ lib \ opengl32.lib" là đường dẫn đến "opengl32 .lib "tệp.
Và cuối cùng thực hiện tất cả bằng cách chỉ cần nhập "kiểm tra" trong bảng điều khiển MATLAB. Nó sẽ mang đến một cửa sổ với đáp ứng tần số bộ lọc và một cửa sổ khác với bộ đệm độ sâu. Lưu ý các bộ đệm trước và sau được hoán đổi tại thời điểm mã "C" đọc bộ đệm độ sâu, vì vậy có thể cần chạy kịch bản hai lần để nhận bất kỳ kết quả nào (vì vậy bộ đệm phía trước hiện có chứa các kết quả hoán đổi với bộ đệm sau) và chiều sâu có thể được đọc).Điều này có thể được thực hiện tự động bằng "C", hoặc bạn có thể thử bao gồm getframe (gcf); ở cuối kịch bản của bạn (mà đọc lại từ OpenGL cũng như vậy nó hoán đổi bộ đệm cho bạn, hoặc một cái gì đó).
Điều này phù hợp với tôi trong Matlab 7.6.0.324 (R2008a). Tập lệnh chạy và phun ra như sau:
>>test
GL_VIEWPORT = [0, 0, 560, 419]
0x11150020 0x0bd39620 0x12b20030 419
Và tất nhiên nó sẽ hiển thị hình ảnh. Lưu ý phạm vi bộ đệm độ sâu phụ thuộc vào Matlab, và có thể khá cao, do đó, làm cho bất kỳ ý nghĩa của hình ảnh được tạo ra có thể không được đơn giản.
bạn luôn có thể thử cung cấp tiền thưởng để tăng sự chú ý mà một câu hỏi nhận được. – PeterT
Tôi dự định nhưng chỉ phát hiện ra khi tôi đăng câu hỏi mà tôi cần phải đợi hai ngày cho đến khi câu hỏi hiện tại này đủ điều kiện. – twerdster
Bạn có chấp nhận câu trả lời liên quan đến Matlab không? Tôi không biết gì về JOGL. –