void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { if (!(nlhs==1)) { mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nlhs","One output required."); } if (!(nrhs==2 || nrhs==3)) { mexErrMsgIdAndTxt("MyToolbox:arrayProduct:nrhs","Two double matrix and one optional structure are required."); } int i = 1; float tau = PAR_DEFAULT_TAU; float lambda = PAR_DEFAULT_LAMBDA; float theta = PAR_DEFAULT_THETA; int nscales = PAR_DEFAULT_NSCALES; float zfactor = PAR_DEFAULT_ZFACTOR; int nwarps = PAR_DEFAULT_NWARPS; float epsilon = PAR_DEFAULT_EPSILON; int verbose = PAR_DEFAULT_VERBOSE; if (nrhs==3) { int tmp=0; double* ptr; for( tmp=0; tmp<mxGetNumberOfFields(prhs[2]);tmp++) { if ( strcmp(mxGetFieldNameByNumber(prhs[2],tmp),"tau")==0) { if (!(mxIsDouble(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))) { mexErrMsgTxt("A double argument was expected."); } if (mxGetNumberOfElements((mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))!=1) { mexErrMsgTxt("Only one value was expected."); } ptr=mxGetPr(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],tmp))); if (ptr[0]> 0 && ptr[0]< 0.25) { tau=ptr[0]; } else { mexErrMsgTxt("The tau value is not acceptable. For more information, type \"help tvl1\""); } } if ( strcmp(mxGetFieldNameByNumber(prhs[2],tmp),"lambda")==0) { if (!(mxIsDouble(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))) { mexErrMsgTxt("A double argument was expected."); } if (mxGetNumberOfElements((mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))!=1) { mexErrMsgTxt("Only one value was expected."); } ptr=mxGetPr(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],tmp))); if (ptr[0]>0) { lambda=ptr[0]; } else { mexErrMsgTxt("The lambda value is not acceptable. For more information, type \"help tvl1\""); } } if ( strcmp(mxGetFieldNameByNumber(prhs[2],tmp),"theta")==0) { if (!(mxIsDouble(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))) { mexErrMsgTxt("A double argument was expected."); } if (mxGetNumberOfElements((mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))!=1) { mexErrMsgTxt("Only one value was expected."); } ptr=mxGetPr(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],tmp))); if (ptr[0]>0) { theta=ptr[0]; } else { mexErrMsgTxt("The theta value is not acceptable. For more information, type \"help tvl1\""); } } if ( strcmp(mxGetFieldNameByNumber(prhs[2],tmp),"nscales")==0) { if (!(mxIsDouble(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))) { mexErrMsgTxt("A double argument was expected."); } if (mxGetNumberOfElements((mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))!=1) { mexErrMsgTxt("Only one value was expected."); } ptr=mxGetPr(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],tmp))); if (ptr[0]>0) { nscales=ptr[0]; } else { mexErrMsgTxt("The nscales value is not acceptable. For more information, type \"help tvl1\""); } } if ( strcmp(mxGetFieldNameByNumber(prhs[2],tmp),"zfactor")==0) { if (!(mxIsDouble(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))) { mexErrMsgTxt("A double argument was expected."); } if (mxGetNumberOfElements((mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))!=1) { mexErrMsgTxt("Only one value was expected."); } ptr=mxGetPr(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],tmp))); if (ptr[0]>0) { zfactor=ptr[0]; } else { mexErrMsgTxt("The zfactor value is not acceptable. For more information, type \"help tvl1\""); } } if ( strcmp(mxGetFieldNameByNumber(prhs[2],tmp),"nwarps")==0) { if (!(mxIsDouble(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))) { mexErrMsgTxt("A double argument was expected."); } if (mxGetNumberOfElements((mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))!=1) { mexErrMsgTxt("Only one value was expected."); } ptr=mxGetPr(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],tmp))); if (ptr[0]>0) { nwarps=ptr[0]; } else { mexErrMsgTxt("The nwarps value is not acceptable. For more information, type \"help tvl1\""); } } if ( strcmp(mxGetFieldNameByNumber(prhs[2],tmp),"epsilon")==0) { if (!(mxIsDouble(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))) { mexErrMsgTxt("A double argument was expected."); } if (mxGetNumberOfElements((mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],0))))!=1) { mexErrMsgTxt("Only one value was expected."); } ptr=mxGetPr(mxGetField(prhs[2],0,mxGetFieldNameByNumber(prhs[2],tmp))); if (ptr[0]>0) { epsilon=ptr[0]; } else { mexErrMsgTxt("The epsilon value is not acceptable. For more information, type \"help tvl1\""); } } } } if (tau <= 0 || tau > 0.25) { tau = PAR_DEFAULT_TAU; if (verbose) mexPrintf("warning: " "tau changed to %g\n", tau); } if (lambda <= 0) { lambda = PAR_DEFAULT_LAMBDA; if (verbose) mexPrintf("warning: " "lambda changed to %g\n", lambda); } if (theta <= 0) { theta = PAR_DEFAULT_THETA; if (verbose) mexPrintf("warning: " "theta changed to %g\n", theta); } if (nscales <= 0) { nscales = PAR_DEFAULT_NSCALES; if (verbose) mexPrintf("warning: " "nscales changed to %d\n", nscales); } if (zfactor <= 0 || zfactor >= 1) { zfactor = PAR_DEFAULT_ZFACTOR; if (verbose) mexPrintf( "warning: " "zfactor changed to %g\n", zfactor); } if (nwarps <= 0) { nwarps = PAR_DEFAULT_NWARPS; if (verbose) mexPrintf( "warning: " "nwarps changed to %d\n", nwarps); } if (epsilon <= 0) { epsilon = PAR_DEFAULT_EPSILON; if (verbose) mexPrintf("warning: " "epsilon changed to %f\n", epsilon); } int nx = mxGetN(prhs[0]); int ny = mxGetM(prhs[0]); int nx2 = mxGetN(prhs[1]); int ny2 = mxGetM(prhs[1]); float *I0=malloc(nx*ny*sizeof(float)); int tmpx, tmpy; for (tmpx=0; tmpx<nx; tmpx++) for (tmpy=0; tmpy<ny; tmpy++) I0[tmpx+tmpy*nx] = (float)(mxGetPr(prhs[0]))[tmpy+tmpx*ny]; float *I1=malloc(nx2*ny2*sizeof(float)); for (tmpx=0; tmpx<nx2; tmpx++) for (tmpy=0; tmpy<ny2; tmpy++) I1[tmpx+tmpy*nx] = (float)(mxGetPr(prhs[1]))[tmpy+tmpx*ny]; if (nx == nx2 && ny == ny2) { const float N = 1 + log(hypot(nx, ny)/16.0) / log(1/zfactor); if (N < nscales) nscales = N; if (verbose) { mexPrintf( "tau=%f lambda=%f theta=%f nscales=%d " "zfactor=%f nwarps=%d epsilon=%g\n", tau, lambda, theta, nscales, zfactor, nwarps, epsilon); } float *u = xmalloc(2 * nx * ny * sizeof(*u)); float *v = u + nx*ny; Dual_TVL1_optic_flow_multiscale( I0, I1, u, v, nx, ny, tau, lambda, theta, nscales, zfactor, nwarps, epsilon, verbose ); mwSize dim = 3; const mwSize dims[3]={ny,nx,2}; plhs[0]=mxCreateNumericArray(dim, dims,mxDOUBLE_CLASS,mxREAL); double* pointeur=(double*)mxGetPr(plhs[0]); for (tmpy=0; tmpy<ny; tmpy++) for (tmpx=0; tmpx<nx; tmpx++) { pointeur[tmpy+tmpx*ny + 0 ]=(double)u[tmpx+tmpy*nx]; pointeur[tmpy+tmpx*ny + nx*ny]=(double)v[tmpx+tmpy*nx]; } free(I0); free(I1); free(u); } else { mexErrMsgTxt("ERROR: input images size mismatch "); } }
/** * * Main program: * This program reads the following parameters from the console and * then computes the optical flow: * I_1 Previous image to I0 * I0 first image * I1 second image * I0_Smoothed Image for using with function g * out name of the output flow field * outOcc name of the output occlusion map * nprocs number of threads to use (OpenMP library) * tauEta Time step in the primal-dual scheme for eta variable * tauChi Time step in the primal-dual scheme for chi variable * lambda Data term weight parameter * alpha Length term weight parameter (in the occlusion region) * beta Negative divergence data Term * theta tightness parameter * nscales number of scales in the pyramidal structure * zfactor downsampling factor for creating the scales * nwarps number of warps per scales * epsilon stopping criterion threshold for the iterative process * verbose switch on/off messages * */ int main(int argc, char *argv[]) { if (argc < 3) { fprintf(stderr, "Usage: %s I_1 I0 I1 [I0_Smoothed out " // 0 1 2 3 4 5 "outOcc nproc lambda alpha beta theta nscales zfactor nwarps epsilon " // 6 7 8 9 10 11 12 13 14 15 "verbose ]\n", *argv); // 16 return EXIT_FAILURE; } // Variable Declaration double *u1=NULL, *u2=NULL; //field double *chi=NULL; //Occlussion map double *I_1=NULL, *I0=NULL, *I1=NULL; // Previous (I_1), current (I0) and next image (I1) double *filtI0=NULL; //Filtered image used in function g int nx_1, ny_1, nx, ny, nx1, ny1, nxf, nyf; //Image sizes //read the parameters int i = 1; char* image_1_name = argv[i]; i++; //1 char* image1_name = argv[i]; i++; //2 char* image2_name = argv[i]; i++; //3 char* image1_Smooth_name = (argc>i) ? argv[i] : argv[2]; i++; //4 If there is no I0_Smoothed, then it will be I0 const char* outfile = (argc>i)? argv[i]: PAR_DEFAULT_OUTFLOW; i++; //5 const char* outOccFile = (argc>i)? argv[i]: PAR_DEFAULT_OUT_OCC; i++; //6 int nproc = (argc>i)? atoi(argv[i]): PAR_DEFAULT_NPROC; i++; //7 double lambda = (argc>i)? atof(argv[i]): PAR_DEFAULT_LAMBDA; i++; //8 double alpha = (argc>i)? atof(argv[i]): PAR_DEFAULT_ALPHA; i++; //9 double betaW = (argc>i)? atof(argv[i]): PAR_DEFAULT_BETA; i++; //10 double theta = (argc>i)? atof(argv[i]): PAR_DEFAULT_THETA; i++; //11 int nscales = (argc>i)? atoi(argv[i]): PAR_DEFAULT_NSCALES; i++; //12 double zfactor = (argc>i)? atof(argv[i]): PAR_DEFAULT_ZFACTOR; i++; //13 int nwarps = (argc>i)? atoi(argv[i]): PAR_DEFAULT_NWARPS; i++; //14 double epsilon = (argc>i)? atof(argv[i]): PAR_DEFAULT_EPSILON; i++; //15 int verbose = (argc>i)? atoi(argv[i]): PAR_DEFAULT_VERBOSE; i++; //16 //check parameters if (nproc < 0) { nproc = PAR_DEFAULT_NPROC; fprintf(stderr, "warning: " "nproc changed to %d\n", nproc); } if (lambda <= 0) { lambda = PAR_DEFAULT_LAMBDA; fprintf(stderr, "warning: " "lambda changed to %g\n", lambda); } if (alpha <= 0) { alpha = PAR_DEFAULT_ALPHA; fprintf(stderr, "warning: " "alpha changed to %g\n", alpha); } if (betaW <= 0) { betaW = PAR_DEFAULT_BETA; fprintf(stderr, "warning: " "beta changed to %g\n", betaW); } if (theta <= 0) { theta = PAR_DEFAULT_THETA; if (verbose) fprintf(stderr, "warning: " "theta changed to %g\n", theta); } if (nscales <= 0) { nscales = PAR_DEFAULT_NSCALES; fprintf(stderr, "warning: " "nscales changed to %d\n", nscales); } if (zfactor <= 0 || zfactor >= 1) { zfactor = PAR_DEFAULT_ZFACTOR; fprintf(stderr, "warning: " "zfactor changed to %g\n", zfactor); } if (nwarps <= 0) { nwarps = PAR_DEFAULT_NWARPS; fprintf(stderr, "warning: " "nwarps changed to %d\n", nwarps); } if (epsilon <= 0) { epsilon = PAR_DEFAULT_EPSILON; fprintf(stderr, "warning: " "epsilon changed to %f\n", epsilon); } #ifdef _OPENMP if (nproc > 0) omp_set_num_threads(nproc); #endif//DISABLE_OMP // read the input images I_1 = read_image(image_1_name, &nx_1, &ny_1); I0 = read_image(image1_name, &nx, &ny); I1 = read_image(image2_name, &nx1, &ny1); filtI0 = read_image(image1_Smooth_name, &nxf, &nyf); if(nx==nx_1 && nx==nx1 && nx==nxf && ny==ny_1 && ny==ny1 && ny==nyf) { //Set the number of scales according to the size of the //images. The value N is computed to assure that the smaller //images of the pyramid don't have a size smaller than 16x16 const int N = floor(log((float)MIN(nx, ny)/16.0)/log(1./zfactor)) + 1; if (N < nscales) nscales = N; if (verbose) fprintf(stderr, " nproc=%d \n lambda=%f \n alpha=%f \n" " beta=%f \n theta=%f \n nscales=%d \n zfactor=%f\n nwarps=%d \n epsilon=%g\n", nproc, lambda, alpha, betaW, theta, nscales, zfactor, nwarps, epsilon); //allocate memory for the flow u1 = (double *)xmalloc( nx * ny * sizeof(double)); u2 = (double *)xmalloc( nx * ny * sizeof(double)); //and the occlusion map chi = (double *)xmalloc( nx * ny * sizeof(double)); for(int i=0; i<nx*ny; i++) { chi[i] = 0.0; u1[i] = 0.0; u2[i] = 0.0; } //compute the optical flow Dual_TVL1_optic_flow_multiscale( I_1, I0, I1, filtI0, u1, u2, chi, nx, ny, lambda, alpha, betaW, theta, nscales, zfactor, nwarps, epsilon, verbose); //write_flow(u1, u2, nx, ny); //<----Eliminar en la version fina a entregar. Solo esta para propositos de depuraci—n. //save the optical flow float *f = (float *)malloc(sizeof(float) * nx * ny * 2); for (int i = 0; i < nx * ny; i++) { f[2*i] = (float)u1[i]; //Avoid the cast! f[2*i+1] = (float)u2[i]; //Avoid the cast! } iio_save_image_float_vec((char *)outfile, f, nx, ny, 2); free(f); //save the occlusions /* int iv=0; FILE * fid=fopen(outOccFile, "w"); for (int i=0; i<ny; i++) { for (int j=0; j<nx; j++) { fprintf(fid, " %f", chi[iv]); iv++; } fprintf(fid, " \n"); } fclose(fid);*/ //iio_save_image_double((char *)outOccFile, chi, nx, ny); float *fOcc = (float *)malloc(sizeof(float) * nx * ny ); for (int i = 0; i < nx * ny; i++) { fOcc[i] = (float)chi[i]*255; //Avoid the cast! } iio_save_image_float((char *)outOccFile, fOcc, nx, ny); free(fOcc); } //delete allocated memory free(I0); free(I1); free(u1); free(u2); free(filtI0); free(chi); return EXIT_SUCCESS; }