template < class T > double * compute_jointprob (T * img1, T * img2, long len, long maxstatenum, int &nstate1, int &nstate2) { //get and check size information long i, j; if (!img1 || !img2 || len < 0) { printf ("Line %d: At least one of the input vectors is invalid.\n", __LINE__); exit (1); } int b_findstatenum = 1; // int nstate1 = 0, nstate2 = 0; int b_returnprob = 1; //copy data into new INT type array (hence quantization) and then reange them begin from 0 (i.e. state1) int *vec1 = new int[len]; int *vec2 = new int[len]; if (!vec1 || !vec2) { printf ("Line %d: Fail to allocate memory.\n", __LINE__); exit (0); } int nrealstate1 = 0, nrealstate2 = 0; copyvecdata (img1, len, vec1, nrealstate1); copyvecdata (img2, len, vec2, nrealstate2); //update the #state when necessary nstate1 = (nstate1 < nrealstate1) ? nrealstate1 : nstate1; //printf("First vector #state = %i\n",nrealstate1); nstate2 = (nstate2 < nrealstate2) ? nrealstate2 : nstate2; //printf("Second vector #state = %i\n",nrealstate2); // if (nstate1!=maxstatenum || nstate2!=maxstatenum) // printf("find nstate1=%d nstate2=%d\n", nstate1, nstate2); //generate the joint-distribution table double *hab = new double[nstate1 * nstate2]; double **hab2d = new double *[nstate2]; if (!hab || !hab2d) { printf ("Line %d: Fail to allocate memory.\n", __LINE__); exit (0); } for (j = 0; j < nstate2; j++) hab2d[j] = hab + (long) j *nstate1; for (i = 0; i < nstate1; i++) for (j = 0; j < nstate2; j++) { hab2d[j][i] = 0; } for (i = 0; i < len; i++) { //old method -- slow // indx = (long)(vec2[i]) * nstate1 + vec1[i]; // hab[indx] += 1; //new method -- fast hab2d[vec2[i]][vec1[i]] += 1; //printf("vec2[%d]=%d vec1[%d]=%d\n", i, vec2[i], i, vec1[i]); } //return the probabilities, otherwise return count numbers if (b_returnprob) { for (i = 0; i < nstate1; i++) for (j = 0; j < nstate2; j++) { hab2d[j][i] /= len; } } //finish if (hab2d) { delete[]hab2d; hab2d = 0; } if (vec1) { delete[]vec1; vec1 = 0; } if (vec2) { delete[]vec2; vec2 = 0; } return hab; }
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // check the arguments if(nrhs != 3 && nrhs !=2 && nrhs!=4) mexErrMsgTxt("Usage [jointprob_table, marginprob_1, marginprob2] = progname(vector1, vector2, maxstatenum, b_returnprob). \n(Both vectors can be images). Max range handled: INT type of the OS"); if(nlhs > 3) mexErrMsgTxt("Too many output argument <jointprob_table>."); if (!mxIsInt8(prhs[0]) && !mxIsUint8(prhs[0]) && !mxIsDouble(prhs[0]) ) mexErrMsgTxt("The first input argument must be types of INT8 or UINT8 or DOUBLE."); if (!mxIsInt8(prhs[1]) && !mxIsUint8(prhs[1]) && !mxIsDouble(prhs[1]) ) mexErrMsgTxt("The second input argument must be types of INT8 or UINT8 or DOUBLE."); //get and check size information long i,j; void *img1 = (void *)mxGetData(prhs[0]); long len1 = mxGetNumberOfElements(prhs[0]); mxClassID type1 = mxGetClassID(prhs[0]); void *img2 = (void *)mxGetData(prhs[1]); long len2 = mxGetNumberOfElements(prhs[1]); mxClassID type2 = mxGetClassID(prhs[1]); if (!img1 || !img2 || !len1 || !len2) mexErrMsgTxt("At least one of the input vectors is invalid."); if (len1!=len2) mexErrMsgTxt("The two vectors/images should have the same length."); int b_findstatenum = 1; int nstate1 = 0, nstate2 = 0; if (nrhs>=3) { b_findstatenum = 0; long MaxGrayLevel = (long) mxGetScalar(prhs[2]); nstate1 = nstate2 = MaxGrayLevel; if (MaxGrayLevel<=1) { printf("The argument #state is invalid. This program will decide #state itself.\n"); b_findstatenum = 1; } } int b_returnprob = 1; if (nrhs>=4) { b_returnprob = (mxGetScalar(prhs[3])!=0); } //copy data into new INT type array (hence quantization) and then reange them begin from 0 (i.e. state1) int * vec1 = new int[len1]; int * vec2 = new int[len2]; int nrealstate1=0, nrealstate2=0; switch(type1) { case mxINT8_CLASS: copyvecdata((char *)img1,len1,vec1,nrealstate1); break; case mxUINT8_CLASS: copyvecdata((unsigned char *)img1,len1,vec1,nrealstate1); break; case mxDOUBLE_CLASS: copyvecdata((double *)img1,len1,vec1,nrealstate1); break; } switch(type2) { case mxINT8_CLASS: copyvecdata((char *)img2,len2,vec2,nrealstate2); break; case mxUINT8_CLASS: copyvecdata((unsigned char *)img2,len2,vec2,nrealstate2); break; case mxDOUBLE_CLASS: copyvecdata((double *)img2,len2,vec2,nrealstate2); break; } //update the #state when necessary if (nstate1<nrealstate1) { nstate1 = nrealstate1; // printf("First vector #state = %i\n",nrealstate1); } if (nstate2<nrealstate2) { nstate2 = nrealstate2; // printf("Second vector #state = %i\n",nrealstate2); } //generate the joint-distribution table plhs[0] = mxCreateDoubleMatrix(nstate1,nstate2,mxREAL); double *hab = (double *) mxGetPr(plhs[0]); double **hab2d = new double * [nstate2]; for(j=0;j<nstate2;j++) hab2d[j] = hab + (long)j*nstate1; for (i=0; i<nstate1;i++) for (j=0; j<nstate2;j++) { hab2d[j][i] = 0; } for (i=0;i<len1;i++) { //old method -- slow // indx = (long)(vec2[i]) * nstate1 + vec1[i]; // hab[indx] += 1; //new method -- fast hab2d[vec2[i]][vec1[i]] += 1; } //return the probabilities, otherwise return count numbers if(b_returnprob) { for (i=0; i<nstate1;i++) for (j=0; j<nstate2;j++) { hab2d[j][i] /= len1; } } //for nlhs>=2 if (nlhs>=2) { plhs[1] = mxCreateDoubleMatrix(nstate1,1,mxREAL); double *ha = (double *)mxGetPr(plhs[1]); for (i=0;i<nstate1;i++) {ha[i] = 0;} for (i=0;i<nstate1;i++) for (j=0;j<nstate2;j++) { ha[i] += hab2d[j][i]; } } if (nlhs>=3) { plhs[2] = mxCreateDoubleMatrix(nstate2,1,mxREAL); double *hb = (double *)mxGetPr(plhs[2]); for (j=0;j<nstate2;j++) {hb[j] = 0;} for (i=0;i<nstate1;i++) for (j=0;j<nstate2;j++) { hb[j] += hab2d[j][i]; } } //finish if (hab2d) {delete []hab2d;} if (vec1) delete []vec1; if (vec2) delete []vec2; return; }