// MATLAB entry point void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { if (nrhs != 1) { mexErrMsgTxt("Improper number of input arguments.\n\n" "FLANDMARK_LOAD_MODEL loads model for flandmark detector to memory.\n\n" "Synopsis: \n" "model = flandmark_load_model(fname)\n" "\n" "Input: \n" " fname [string]\n" "Output: \n" " model [binary data]\n" ); } int address_offset, dynamic_begin, lbp_pointer, disp_pointer; int model_size = 0, dynamic_offset = 0; double start, ms; char * fname = mxArrayToString(prhs[0]); int tsize = 0; FLANDMARK_PSIG * PsiGi = NULL; // check input if (fname == NULL) { mexErrMsgTxt("Improper argument type \"fname\"\n\n" " fname must be a string."); } /* read model */ start = (double)cvGetTickCount(); FLANDMARK_Model * model = flandmark_init(fname); if (model == 0) { mexErrMsgTxt("Error opening file with model structure.\n"); } start = (double)cvGetTickCount() - start; ms = cvRound( start / ((double)cvGetTickFrequency() * 1000.0) ); mexPrintf("Structure model loaded in %.6f ms\n", ms); uint8_t M = model->data.options.M; // Compute size of model_size ------------------------------------------- model_size += sizeof(FLANDMARK_Model); model_size += model->W_ROWS*model->W_COLS*sizeof(double); model_size += model->data.options.bw[0]*model->data.options.bw[1]*sizeof(uint8_t); model_size += 4*sizeof(double); model_size += 2*sizeof(float); model_size += sizeof(FLANDMARK_LBP*); model_size += M*sizeof(FLANDMARK_LBP); for (int i = 0; i < M; ++i) { model_size += model->data.lbp[i].WINS_ROWS*model->data.lbp[i].WINS_COLS*sizeof(uint32_t); } model_size += 4*M*sizeof(double); model_size += sizeof(FLANDMARK_Options); model_size += 4*M*sizeof(int); for (int i = 0; i < 3; ++i) { switch (i) { case 0: PsiGi = model->data.options.PsiGS0; break; case 1: PsiGi = model->data.options.PsiGS1; break; case 2: PsiGi = model->data.options.PsiGS2; break; } tsize = model->data.options.PSIG_ROWS[i]*model->data.options.PSIG_COLS[i]; for (int idx = 0; idx < tsize; ++idx) { model_size += sizeof(FLANDMARK_PSIG); model_size += PsiGi[idx].ROWS*PsiGi[idx].COLS*sizeof(int); } } mexPrintf("model_size = %d\n", model_size); //mexErrMsgTxt("Exitting for sure...\n"); /* Create uint8 buffer for storing the structure into matlab memory */ plhs[0] = mxCreateNumericMatrix(model_size, 1, mxUINT8_CLASS, mxREAL); uint8_t *buffer = (uint8_t*)mxGetPr(plhs[0]); // copy data from structure to memory // Statically allocated parts ----------------------------------------------- // FLANDMARK_Model - static part address_offset = 0; memcpy(&buffer[address_offset], model, sizeof(FLANDMARK_Model)); // FLANDMARK_Data - static part address_offset = (char*)&(model->data) - (char*)model; memcpy(&buffer[address_offset], &model->data, sizeof(FLANDMARK_Data)); // FLANDMARK_Options - static part address_offset = (char*)&(model->data.options) - (char*)model; memcpy(&buffer[address_offset], &model->data.options, sizeof(FLANDMARK_Options)); // Dynamically allocated parts ---------------------------------------------- dynamic_offset = sizeof(FLANDMARK_Model); dynamic_begin = dynamic_offset; // model->W address_offset = dynamic_offset; memcpy(&buffer[address_offset], model->W, model->W_COLS*model->W_ROWS*sizeof(double)); dynamic_offset += model->W_COLS*model->W_ROWS*sizeof(double); // update pointer model->W *(double**)&buffer[(char*)&(model->W)-(char*)model]=(double*)&buffer[address_offset]; // model->normalizedImageFrame address_offset = dynamic_offset; memcpy(&buffer[address_offset], model->normalizedImageFrame, model->data.options.bw[0]*model->data.options.bw[1]*sizeof(uint8_t)); dynamic_offset += model->data.options.bw[0]*model->data.options.bw[1]*sizeof(uint8_t); // update pointer model->normalizedImageFrame *(uint8_t**)&buffer[(char*)&(model->normalizedImageFrame)-(char*)model]=(uint8_t*)&buffer[address_offset]; // model->bb address_offset = dynamic_offset; memcpy(&buffer[address_offset], model->bb, 4*sizeof(double)); dynamic_offset += 4*sizeof(double); // update pointer model->bb *(double**)&buffer[(char*)&(model->bb)-(char*)model]=(double*)&buffer[address_offset]; // model->sf address_offset = dynamic_offset; memcpy(&buffer[address_offset], model->sf, 2*sizeof(float)); dynamic_offset += 2*sizeof(float); // update pointer model->sf *(float**)&buffer[(char*)&(model->sf)-(char*)model]=(float*)&buffer[address_offset]; // model->data.mapTable address_offset = dynamic_offset; memcpy(&buffer[address_offset], model->data.mapTable, M*4*sizeof(int)); dynamic_offset += M*4*sizeof(int); // update pointer model->data.mapTable *(int**)&buffer[(char*)&(model->data.mapTable)-(char*)model]=(int*)&buffer[address_offset]; // model->data.options.S address_offset = dynamic_offset; memcpy(&buffer[address_offset], model->data.options.S, M*4*sizeof(int)); dynamic_offset += M*4*sizeof(int); // update pointer model->data.options.S *(int**)&buffer[(char*)&(model->data.options.S)-(char*)model]=(int*)&buffer[address_offset]; // model->data.lbp // lbp static part lbp_pointer = dynamic_offset; for (uint8_t i=0; i < M; ++i) { address_offset = dynamic_offset; memcpy(&buffer[address_offset], &model->data.lbp[i], sizeof(FLANDMARK_LBP)); dynamic_offset += sizeof(FLANDMARK_LBP); } // Update pointer *(FLANDMARK_LBP**)&buffer[(char*)&(model->data.lbp)-(char*)model]=(FLANDMARK_LBP*)&buffer[lbp_pointer]; // lbp dynamic part for (uint8_t i=0; i < M; ++i) { address_offset = dynamic_offset; memcpy(&buffer[address_offset], model->data.lbp[i].wins, model->data.lbp[i].WINS_COLS*model->data.lbp[i].WINS_ROWS*sizeof(uint32_t)); dynamic_offset += model->data.lbp[i].WINS_COLS*model->data.lbp[i].WINS_ROWS*sizeof(uint32_t); // update pointer *(uint32_t**)&buffer[lbp_pointer+i*sizeof(FLANDMARK_LBP)+(long long)((char*)&(model->data.lbp[i].wins))-(long long)((char*)&(model->data.lbp[i]))]=(uint32_t*)&buffer[address_offset]; } // model->data.options.PsiGSi for (int i=0; i < 3; ++i) { address_offset = dynamic_offset; switch(i) { case 0: PsiGi = model->data.options.PsiGS0; *(FLANDMARK_PSIG**)&buffer[(char*)&(model->data.options.PsiGS0)-(char*)model]=(FLANDMARK_PSIG*)&buffer[address_offset]; break; case 1: PsiGi = model->data.options.PsiGS1; *(FLANDMARK_PSIG**)&buffer[(char*)&(model->data.options.PsiGS1)-(char*)model]=(FLANDMARK_PSIG*)&buffer[address_offset]; break; case 2: PsiGi = model->data.options.PsiGS2; *(FLANDMARK_PSIG**)&buffer[(char*)&(model->data.options.PsiGS2)-(char*)model]=(FLANDMARK_PSIG*)&buffer[address_offset]; break; } tsize = model->data.options.PSIG_COLS[i]*model->data.options.PSIG_ROWS[i]; // static part disp_pointer = dynamic_offset; for (int idx=0; idx < tsize; ++idx) { address_offset = dynamic_offset; memcpy(&buffer[address_offset], &PsiGi[idx], sizeof(FLANDMARK_PSIG)); dynamic_offset += sizeof(FLANDMARK_PSIG); } // dynamic part for (int idx=0; idx < tsize; ++idx) { address_offset = dynamic_offset; memcpy(&buffer[address_offset], PsiGi[idx].disp, PsiGi[idx].ROWS*PsiGi[idx].COLS*sizeof(int)); dynamic_offset += PsiGi[idx].ROWS*PsiGi[idx].COLS*sizeof(int); // update pointer *(int**)&buffer[disp_pointer+idx*sizeof(FLANDMARK_PSIG)+(long long)((char*)&(PsiGi[idx].disp))-(long long)((char*)&(PsiGi[idx]))]=(int*)&buffer[address_offset]; } } /* CHECK MODEL */ mexPrintf("Checking model..."); FLANDMARK_Model *tmp = (FLANDMARK_Model*)buffer; EError_T err = flandmark_check_model(model, tmp); if (err == NO_ERR) { mexPrintf(" passed.\n"); } else { mexPrintf(" not passed!\n"); switch (err) { case NO_ERR: mexErrMsgTxt("No error.\n"); break; case ERROR_M: mexErrMsgTxt("model->M does not match!\n"); break; case ERROR_BW: mexErrMsgTxt("model->data.bw does not match!\n"); break; case ERROR_BW_MARGIN: mexErrMsgTxt("model->data.bw_margin does not match!\n"); break; case ERROR_W: mexErrMsgTxt("model->W does not match!\n"); break; case ERROR_DATA_IMAGES: mexErrMsgTxt("model->data.Images does not match!\n"); break; case ERROR_DATA_MAPTABLE: mexErrMsgTxt("model->data.mapTable does not match!\n"); break; case ERROR_DATA_LBP: mexErrMsgTxt("model->data.lbp does not match!\n"); break; case ERROR_DATA_OPTIONS_S: mexErrMsgTxt("model->data.options.S does not match!\n"); break; case ERROR_DATA_OPTIONS_PSIG: mexErrMsgTxt("model->data.options.PsiGSi does not match!\n"); break; case UNKNOWN_ERROR: mexErrMsgTxt("Uknown error!\n"); break; } } // clean model mexPrintf("Cleaning structure model... "); flandmark_free(model); mexPrintf(" done.\n"); }
// MATLAB entry point void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { if (nrhs < 2 || nrhs > 3) { mexErrMsgTxt("Improper number of input arguments.\n\n" "FLANDMARK_WRITE_MODEL loads model for flandmark detector and writes it to file.\n\n" "Synopsis: \n" "flandmark_write_model(model, fname)\n" "\n" "Input: \n" " model [structure]\n" " fname [string]\n" ); } // variables for interface to matlab const mwSize *dims, *tmp_dims; mxArray *field_ptr, *field_data_ptr, *tmp_field_ptr, *cell_ptr; // pointers to data types used in mat file double * p_double = 0; uint32_t * p_uint32 = 0; int tsize = -1, tmp_tsize = -1; EError_T retval = UNKNOWN_ERROR; char * fname = mxArrayToString(prhs[1]); // check input if (!mxIsStruct(prhs[0])) { mexErrMsgTxt("Improper argument type \"model\".\n\n" " model must be a structure containing joint parameter vector W and structure data.\n" ); } mxArray *in_w = mxGetField(prhs[0], 0, "W"); mxArray *in_data = mxGetField(prhs[0], 0, "data"); if (in_w == NULL || in_data == NULL) { mexErrMsgTxt("Improper argument type \"model\".\n\n" " model must be a structure containing joint parameter vector \"W\" and structure \"data\".\n" ); } if (fname == NULL) { mexErrMsgTxt("Improper argument type \"fname\"\n\n" " fname must be a string.\n" ); } // Model structure (see detector_model.h for details) FLANDMARK_Model * model = (FLANDMARK_Model*)malloc(sizeof(FLANDMARK_Model)); uint8_t M = 0; // model.data.options.M -------------------------------------------------- mexPrintf("Getting number of components M:\n"); field_data_ptr = mxGetField(prhs[0], 0, "data"); field_ptr = mxGetField(field_data_ptr, 0, "options"); tmp_field_ptr = mxGetField(field_ptr, 0, "M"); p_double = (double*)mxGetPr(tmp_field_ptr); model->data.options.M = (uint8_t)p_double[0]; M = model->data.options.M; mexPrintf("model->data.options.M = %d\n", model->data.options.M); // model->data.options.bw ------------------------------------------------- tmp_field_ptr = mxGetField(field_ptr, 0, "bw"); p_double = (double*)mxGetPr(tmp_field_ptr); model->data.options.bw[0] = (int)p_double[0]; model->data.options.bw[1] = (int)p_double[1]; mexPrintf("model->data.options.bw = [%d, %d]\n", model->data.options.bw[0], model->data.options.bw[1]); model->data.imSize[0] = model->data.options.bw[0]; model->data.imSize[1] = model->data.options.bw[1]; // model->data.options.bw_margin ------------------------------------------ tmp_field_ptr = mxGetField(field_ptr, 0, "bw_margin"); p_double = (double*)mxGetPr(tmp_field_ptr); model->data.options.bw_margin[0] = (int)p_double[0]; model->data.options.bw_margin[1] = (int)p_double[1]; mexPrintf("model->data.options.bw_margin = [%d, %d]\n", model->data.options.bw_margin[0], model->data.options.bw_margin[1]); // model->W --------------------------------------------------------------- // get model->W from mat file mexPrintf("Loading field model->W:\n"); field_ptr = mxGetField(prhs[0], 0, "W"); dims = mxGetDimensions(field_ptr); model->W_ROWS = dims[0]; model->W_COLS = dims[1]; mexPrintf("model->W = [%d x %d]\n", model->W_ROWS, model->W_COLS); p_double = (double*)mxGetPr(field_ptr); model->W = (double*)malloc(model->W_ROWS * sizeof(double)); for (int i = 0; i < model->W_ROWS; ++i) { model->W[i] = p_double[i]; } // model->data.mapTable ---------------------------------------------------- mexPrintf("Loading field model->data.mapTable:\n"); field_ptr = mxGetField(field_data_ptr, 0, "mapTable"); dims = mxGetDimensions(field_ptr); mexPrintf("mapTable = [%d x %d]\n", dims[0], dims[1]); mexPrintf(" = %d\n", dims[0]*dims[1]); if (dims[0]*dims[1] != model->data.options.M*4) { mexErrMsgTxt("Error. Possibly corrupted file.\n"); } model->data.mapTable = (int*)calloc(M*4, sizeof(int)); p_double = (double*)mxGetPr(field_ptr); mexPrintf("model->data.mapTable: \n"); for (int i = 0; i < model->data.options.M*4; ++i) { model->data.mapTable[i] = (int)p_double[i]; mexPrintf(" %d", model->data.mapTable[i]); } mexPrintf("\n"); // model->data.lbp --------------------------------------------------------- mexPrintf("Loading field model->data.lbp:\n"); field_ptr = mxGetField(field_data_ptr, 0, "lbp"); dims = mxGetDimensions(field_ptr); mexPrintf("lbp = [%d x %d]\n", dims[0], dims[1]); model->data.lbp = (FLANDMARK_LBP*)malloc(M*sizeof(FLANDMARK_LBP)); for (int idx = 0; idx < model->data.options.M; ++idx) { // get pointer to cell lbp{idx} cell_ptr = mxGetCell(field_ptr, idx); // get lbp{idx}.winSize tmp_field_ptr = mxGetField(cell_ptr, 0, "winSize"); tmp_dims = mxGetDimensions(tmp_field_ptr); mexPrintf("lbp[%d].winSize = [%d x %d]", idx, tmp_dims[0], tmp_dims[1]); p_double = (double*)mxGetPr(tmp_field_ptr); for (int i = 0; i < 2; ++i) { model->data.lbp[idx].winSize[i] = (int)p_double[i]; mexPrintf(" %d", model->data.lbp[idx].winSize[i]); } mexPrintf("\n"); // get lbp{idx}.hop model->data.lbp[idx].hop = 4; // get lbp{idx}.wins tmp_field_ptr = mxGetField(cell_ptr, 0, "wins"); tmp_dims = mxGetDimensions(tmp_field_ptr); model->data.lbp[idx].WINS_ROWS = tmp_dims[0]; model->data.lbp[idx].WINS_COLS = tmp_dims[1]; mexPrintf("lbp[%d].wins = [%d x %d]\n", idx, model->data.lbp[idx].WINS_ROWS, model->data.lbp[idx].WINS_COLS); p_uint32 = (uint32_t*)mxGetPr(tmp_field_ptr); tsize = model->data.lbp[idx].WINS_ROWS * model->data.lbp[idx].WINS_COLS; model->data.lbp[idx].wins = (uint32_t*)malloc(tsize * sizeof(uint32_t)); for (int i = 0; i < tsize; ++i) { model->data.lbp[idx].wins[i] = p_uint32[i]; } } // model->data.options.S --------------------------------------------------- mexPrintf("Loading field model->data.options.S:\n"); //field_data_ptr = mxGetField(prhs[0], 0, "data"); field_ptr = mxGetField(field_data_ptr, 0, "options"); tmp_field_ptr = mxGetField(field_ptr, 0, "S"); dims = mxGetDimensions(tmp_field_ptr); mexPrintf("options.S = [%d x %d]\n", dims[0], dims[1]); model->data.options.S = (int*)calloc(4*M, sizeof(int)); if (dims[0]*dims[1] != 4*model->data.options.M) { mexErrMsgTxt("Error. Possibly corrupted file.\n"); } p_double = (double*)mxGetPr(tmp_field_ptr); for (int i = 0; i < 4*model->data.options.M; ++i) { model->data.options.S[i] = (int)p_double[i]; mexPrintf(" %d", model->data.options.S[i]); } mexPrintf("\n"); // model->data.options.PsiG ------------------------------------------------ mexPrintf("Loading field model->data.options.PsiG:\n"); field_ptr = mxGetField(field_data_ptr, 0, "options"); FLANDMARK_PSIG * PsiGi = NULL; char psig_id[7] = "PsiGS#"; for (int psig_idx = 0; psig_idx < 3; ++psig_idx) { mexPrintf("PsiGS%d:\n", psig_idx); switch (psig_idx) { case 0: //PsiGi = model->data.options.PsiGS0; tmp_field_ptr = mxGetField(field_ptr, 0, "PsiGS0"); psig_id[5] = '0'; break; case 1: //PsiGi = model->data.options.PsiGS1; tmp_field_ptr = mxGetField(field_ptr, 0, "PsiGS1"); psig_id[5] = '1'; break; case 2: //PsiGi = model->data.options.PsiGS2; tmp_field_ptr = mxGetField(field_ptr, 0, "PsiGS2"); psig_id[5] = '2'; break; } if (tmp_field_ptr == NULL) { mexErrMsgTxt("Looks like you are trying to load a model using gtab version of deformation cost.\n" "We now support only loading models with gdisp deformation cost.\n" "\n" ); } dims = mxGetDimensions(tmp_field_ptr); tsize = dims[0]*dims[1]; model->data.options.PSIG_ROWS[psig_idx] = dims[0]; model->data.options.PSIG_COLS[psig_idx] = dims[1]; mexPrintf("options.%s = [%d x %d]\n", psig_id, model->data.options.PSIG_ROWS[psig_idx], model->data.options.PSIG_COLS[psig_idx]); switch (psig_idx) { case 0: model->data.options.PsiGS0 = (FLANDMARK_PSIG*)malloc(tsize*sizeof(FLANDMARK_PSIG)); PsiGi = model->data.options.PsiGS0; break; case 1: model->data.options.PsiGS1 = (FLANDMARK_PSIG*)malloc(tsize*sizeof(FLANDMARK_PSIG)); PsiGi = model->data.options.PsiGS1; break; case 2: model->data.options.PsiGS2 = (FLANDMARK_PSIG*)malloc(tsize*sizeof(FLANDMARK_PSIG)); PsiGi = model->data.options.PsiGS2; break; } for (int idx = 0; idx < tsize; ++idx) { cell_ptr = mxGetCell(tmp_field_ptr, idx); tmp_dims = mxGetDimensions(cell_ptr); tmp_tsize = tmp_dims[0]*tmp_dims[1]; PsiGi[idx].ROWS = tmp_dims[0]; PsiGi[idx].COLS = tmp_dims[1]; PsiGi[idx].disp = (int*)mxGetPr(cell_ptr); } } model->bb = 0; model->sf = 0; model->normalizedImageFrame = 0; mexPrintf("Structure model loaded.\n"); // write model mexPrintf("\n\n"); mexPrintf("Calling flandmark_writeModel...\n"); flandmark_write_model(fname, model); mexPrintf("Write model done.\n"); // read model mexPrintf("Calling flandmark_init...\n"); FLANDMARK_Model * tst = flandmark_init(fname); mexPrintf("Read model done.\n"); // chceck model mexPrintf("Calling flandmark_checkModel... "); retval = flandmark_check_model(model, tst); switch (retval) { case NO_ERR: mexPrintf("all done.\n"); break; case ERROR_M: mexErrMsgTxt("check model->data.options.M not passed.\n"); break; case ERROR_BW: mexErrMsgTxt("check model->data.options.bw not passed.\n"); break; case ERROR_BW_MARGIN: mexErrMsgTxt("check model->data.options.bw_margin not passed.\n"); break; case ERROR_W: mexErrMsgTxt("check model->w not passed.\n"); break; case ERROR_DATA_IMAGES: mexErrMsgTxt("check model->data.Images not passed.\n"); break; case ERROR_DATA_MAPTABLE: mexErrMsgTxt("check model->data.mapTable not passed.\n"); break; case ERROR_DATA_LBP: mexErrMsgTxt("check model->data.lbp not passed.\n"); break; case ERROR_DATA_OPTIONS_S: mexErrMsgTxt("check model->data.options.S not passed.\n"); break; case ERROR_DATA_OPTIONS_PSIG: mexErrMsgTxt("check model->data.options.PsiG not passed.\n"); break; default: mexErrMsgTxt("Unknown error.\n"); break; } // cleanup mexPrintf("Cleanup..."); flandmark_free(model); flandmark_free(tst); mexPrintf(" done.\n"); }