您的位置:首页 > 编程语言 > MATLAB

Matlab C/C++混合编程实例学习

2015-03-15 16:25 501 查看
  在某些情况下,我们需要使用Matlab C/C++混合编程的方法,或达到提高Matlab运行效率,或解决内存不足等问题。推荐阅读Matlab C/C++, Fortran, and Python API Reference,在阅读这篇手册的时候,我们可以重点关注如下一些api:

mexFunction,void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mxGetData

mxGetPr
mxGetScalar

mxGetNumberOfDimensions
mxGetDimensions

mxGetNumberOfElements

mxCalloc

mxFree
mxCreateNumericMatrix

mxSetData

mxSetPr
mxSetDimensions

mxClassID

mxGetClassID

mexAtExit
mexPrintf
mexErrMsgIdAndTxt

掌握好这几个典型的api,基本上就可以开始享受matlab混合编程的乐趣了。不同于冗长的API讲解,ispforfun在这里提供一个干活,供大家理解这些api。

  代码功能描述:对输入像素进行Gamma矫正。数学原理:



  

  代码如下:

/*
*   isp_gamma_correction.c
*-----------------------------
* Created by ispforfun
*
* The calling syntax is:
* out_img = isp_gamma_correction(in_img, gamma_param, in_img_bps, out_img_bps)
*
* Revision: 1.0
*/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "matrix.h"
#include "mex.h"

#define GAMMA_LUT_SIZE  512

static void initial_Gamma_LUT(unsigned short * lut_array, int out_img_bps, double gamma_param)
{
int i;
int out_img_max_level = (1 << out_img_bps) - 1;
double output;

for (i = 0; i < GAMMA_LUT_SIZE; i++){
output = pow(((double)i)/GAMMA_LUT_SIZE, gamma_param);
lut_array[i] = (unsigned short)(output * out_img_max_level);
}
}

/* mexFunction is the gateway routine for the MEX-file. */
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
mxClassID in_param_category;
unsigned short *pInputImg;
unsigned char *pOutputImgUint8;
unsigned short *pOutputImgUint16;
unsigned short in_pix, out_pix;
int in_pix_integer_part, in_pix_frac_part;
unsigned short lut_0, lut_1;
mwSize input_img_dims;
const mwSize *input_img_dims_array;
unsigned short *LutArray;
int in_img_bps, out_img_bps;
double gamma_param;
int i, num_pix_elements, in_pix_shift_cnt;

if (nrhs != 4){
mexErrMsgIdAndTxt("Matlab:isp_gamma_correction:the input parameters are not correct",
"out_img = isp_gamma_correction(in_img, gamma_param, in_img_bps, out_img_bps)");
return;
}

in_param_category = mxGetClassID(prhs[0]);
if (in_param_category != mxUINT16_CLASS){
mexErrMsgIdAndTxt("Matlab:isp_gamma_correction:the input image's data type should be uint16",
"uin16 input image required.");
} else {
pInputImg = (unsigned short *)mxGetData(prhs[0]);
//mexPrintf("Image width = %d\n", mxGetN(prhs[0]));
//mexPrintf("Image height = %d\n", mxGetM(prhs[0]));
//mexPrintf("Image size = %d\n", mxGetNumberOfElements(prhs[0]));

gamma_param = mxGetScalar(prhs[1]);
in_img_bps = (int)mxGetScalar(prhs[2]);
out_img_bps = (int)mxGetScalar(prhs[3]);

// ...
input_img_dims = mxGetNumberOfDimensions(prhs[0]);
mexPrintf("Image has %d dimensions\n", input_img_dims);
input_img_dims_array = mxGetDimensions(prhs[0]);
for (i = 0; i < input_img_dims; i++){
mexPrintf("Image's dim[%d] = %d\n", i, input_img_dims_array[i]);
}
num_pix_elements = (int)mxGetNumberOfElements(prhs[0]);
mexPrintf("Image's size = %d\n", num_pix_elements);

if (out_img_bps == 8){
pOutputImgUint8 = (unsigned char *)mxCalloc(num_pix_elements, sizeof(unsigned char));
} else {
pOutputImgUint16 = (unsigned short *)mxCalloc(num_pix_elements, sizeof(unsigned short));
}

LutArray = (unsigned short *)mxCalloc(GAMMA_LUT_SIZE, sizeof(unsigned short));

initial_Gamma_LUT(LutArray, out_img_bps, gamma_param);

in_pix_shift_cnt = in_img_bps - 9;
if (in_pix_shift_cnt >= 0){
for (i = 0; i < num_pix_elements; i++){
in_pix = pInputImg[i];

// debug pixel is (242, 1028)
//if ( i == (241*input_img_dims_array[0] + 1027) ){
//    mexPrintf("Debug: in pixel = %d\n", in_pix);
//}

in_pix_integer_part = in_pix >> in_pix_shift_cnt;
in_pix_frac_part = in_pix - (in_pix_integer_part << in_pix_shift_cnt);
lut_0 = LutArray[in_pix_integer_part];
if (in_pix_integer_part >= (GAMMA_LUT_SIZE - 1)){
lut_1 = (1 << out_img_bps) - 1;
} else {
lut_1 = LutArray[in_pix_integer_part + 1];
}

out_pix = (lut_0 * ((int)((1 << in_pix_shift_cnt) - in_pix_frac_part)) + lut_1 * in_pix_frac_part) >> in_pix_shift_cnt;

//if ( i == (241*input_img_dims_array[0] + 1027) ){
//    mexPrintf("Debug: out pixel = %d\n", out_pix);
//}

if (out_img_bps == 8) {
if (out_pix > 255){
out_pix = 255;
}
pOutputImgUint8[i] = (unsigned char)out_pix;
} else {
pOutputImgUint16[i] = (unsigned short)out_pix;
}
}

} else {

}

mxFree(LutArray);

if (out_img_bps == 8){
plhs[0] = mxCreateNumericMatrix(0, 0, mxUINT8_CLASS, mxREAL);
mxSetData(plhs[0], (void *)pOutputImgUint8);
} else {
plhs[0] = mxCreateNumericMatrix(0, 0, mxUINT16_CLASS, mxREAL);
mxSetData(plhs[0], (void *)pOutputImgUint16);
}

mxSetDimensions(plhs[0], input_img_dims_array, input_img_dims);

}

}


  调用方法一:

demo_img = isp_gamma_correction(demo_img, 0.45, 14, 8);


调用方法二:

demo_img_R = isp_gamma_correction(demo_img(:,:,1), 0.45, 14, 8);
demo_img_G = isp_gamma_correction(demo_img(:,:,2), 0.45, 14, 8);
demo_img_B = isp_gamma_correction(demo_img(:,:,3), 0.45, 14, 8);
demo_img = cat(3, demo_img_R, demo_img_G, demo_img_B);


无论采用哪种调用方法,用

figure;
imshow(demo_img);
都可以显示出Gamma校正以后的图像。

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: