diff options
| author | Edoardo Pasca <edo.paskino@gmail.com> | 2017-08-03 16:52:20 +0100 | 
|---|---|---|
| committer | Edoardo Pasca <edo.paskino@gmail.com> | 2017-08-03 16:52:20 +0100 | 
| commit | cf94b779bf8f11128ce0e4535ba1e12ccb2b50a1 (patch) | |
| tree | 52f89f1f79ef628e460d499f43c82111d5ff08f2 /src | |
| parent | 0f40ee8ad7d6e0b3b7059e5e1242d8ab97cd3caf (diff) | |
| download | regularization-cf94b779bf8f11128ce0e4535ba1e12ccb2b50a1.tar.gz regularization-cf94b779bf8f11128ce0e4535ba1e12ccb2b50a1.tar.bz2 regularization-cf94b779bf8f11128ce0e4535ba1e12ccb2b50a1.tar.xz regularization-cf94b779bf8f11128ce0e4535ba1e12ccb2b50a1.zip  | |
added FGP_TV wrapper
Diffstat (limited to 'src')
| -rw-r--r-- | src/Python/fista_module.cpp | 576 | 
1 files changed, 473 insertions, 103 deletions
diff --git a/src/Python/fista_module.cpp b/src/Python/fista_module.cpp index 5344083..2492884 100644 --- a/src/Python/fista_module.cpp +++ b/src/Python/fista_module.cpp @@ -26,12 +26,10 @@ limitations under the License.  #include <boost/python/numpy.hpp>  #include "boost/tuple/tuple.hpp" -// include the regularizers -#include "FGP_TV_core.h" -#include "LLT_model_core.h" -#include "PatchBased_Regul_core.h"  #include "SplitBregman_TV_core.h" -#include "TGV_PD_core.h" +#include "FGP_TV_core.h" + +  #if defined(_WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64)  #include <windows.h> @@ -43,7 +41,6 @@ __if_not_exists(uint16_t) { typedef __int8 uint16_t; }  namespace bp = boost::python;  namespace np = boost::python::numpy; -  /*! in the Matlab implementation this is called as  void mexFunction(  int nlhs, mxArray *plhs[], @@ -56,9 +53,7 @@ nlhs Array of pointers to the OUTPUT mxArrays  plhs int number of OUTPUT mxArrays  *********************************************************** -mxGetData -args: pm Pointer to an mxArray -Returns: Pointer to the first element of the real data. Returns NULL in C (0 in Fortran) if there is no real data. +  ***********************************************************  double mxGetScalar(const mxArray *pm);  args: pm Pointer to an mxArray; cannot be a cell mxArray, a structure mxArray, or an empty mxArray. @@ -92,77 +87,143 @@ double *mxGetPr(const mxArray *pm);  args: pm Pointer to an mxArray of type double  Returns: Pointer to the first element of the real data. Returns NULL in C (0 in Fortran) if there is no real data.  **************************************************************** -mxArray *mxCreateNumericArray(mwSize ndim, const mwSize *dims, mxClassID classid, mxComplexity ComplexFlag); -args:  ndim: Number of dimensions. If you specify a value for ndim that is less than 2, mxCreateNumericArray automatically sets the number of dimensions to 2. -       dims: Dimensions array. Each element in the dimensions array contains the size of the array in that dimension. -	         For example, in C, setting dims[0] to 5 and dims[1] to 7 establishes a 5-by-7 mxArray. Usually there are ndim elements in the dims array. -       classid: Identifier for the class of the array, which determines the way the numerical data is represented in memory. -                For example, specifying mxINT16_CLASS in C causes each piece of numerical data in the mxArray to be represented as a 16-bit signed integer. -       ComplexFlag:  If the mxArray you are creating is to contain imaginary data, set ComplexFlag to mxCOMPLEX in C (1 in Fortran).  -	                 Otherwise, set ComplexFlag to mxREAL in C (0 in Fortran). - +mxArray *mxCreateNumericArray(mwSize ndim, const mwSize *dims, +mxClassID classid, mxComplexity ComplexFlag); +args: ndimNumber of dimensions. If you specify a value for ndim that is less than 2, mxCreateNumericArray automatically sets the number of dimensions to 2. +dims Dimensions array. Each element in the dimensions array contains the size of the array in that dimension. +For example, in C, setting dims[0] to 5 and dims[1] to 7 establishes a 5-by-7 mxArray. Usually there are ndim elements in the dims array. +classid Identifier for the class of the array, which determines the way the numerical data is represented in memory. +For example, specifying mxINT16_CLASS in C causes each piece of numerical data in the mxArray to be represented as a 16-bit signed integer. +ComplexFlag  If the mxArray you are creating is to contain imaginary data, set ComplexFlag to mxCOMPLEX in C (1 in Fortran). Otherwise, set ComplexFlag to mxREAL in C (0 in Fortran).  Returns: Pointer to the created mxArray, if successful. If unsuccessful in a standalone (non-MEX file) application, returns NULL in C (0 in Fortran). -       If unsuccessful in a MEX file, the MEX file terminates and returns control to the MATLAB prompt. The function is unsuccessful when there is not -       enough free heap space to create the mxArray. +If unsuccessful in a MEX file, the MEX file terminates and returns control to the MATLAB prompt. The function is unsuccessful when there is not +enough free heap space to create the mxArray. +*/ + +void mexErrMessageText(char* text) { +	std::cerr << text << std::endl; +} + +/* +double mxGetScalar(const mxArray *pm); +args: pm Pointer to an mxArray; cannot be a cell mxArray, a structure mxArray, or an empty mxArray. +Returns: Pointer to the value of the first real (nonimaginary) element of the mxArray.	In C, mxGetScalar returns a double.  */  template<typename T> -np::ndarray zeros(int dims, int * dim_array, T el) { -	bp::tuple shape = bp::make_tuple(dim_array[0], dim_array[1], dim_array[2]); -	np::dtype dtype = np::dtype::get_builtin<T>(); -	np::ndarray zz = np::zeros(shape, dtype); -	return zz; +double mxGetScalar(const np::ndarray plh) { +	return (double)bp::extract<T>(plh[0]);  } -bp::list SplitBregman_TV(np::ndarray input, double d_mu, , int niterations, double d_epsil, int TV_type) { -	/* C-OMP implementation of Split Bregman - TV denoising-regularization model (2D/3D) -	* -	* Input Parameters: -	* 1. Noisy image/volume -	* 2. lambda - regularization parameter -	* 3. Number of iterations [OPTIONAL parameter] -	* 4. eplsilon - tolerance constant [OPTIONAL parameter] -	* 5. TV-type: 'iso' or 'l1' [OPTIONAL parameter] -	* -	* Output: -	* Filtered/regularized image -	* -	* All sanity checks and default values are set in Python + +template<typename T> +T * mxGetData(const np::ndarray pm) { +	//args: pm Pointer to an mxArray; cannot be a cell mxArray, a structure mxArray, or an empty mxArray. +	//Returns: Pointer to the value of the first real(nonimaginary) element of the mxArray.In C, mxGetScalar returns a double. +	/*Access the numpy array pointer: +	char * get_data() const; +	Returns:	Array’s raw data pointer as a char +	Note:	This returns char so stride math works properly on it.User will have to reinterpret_cast it. +	probably this would work. +	A = reinterpret_cast<float *>(prhs[0]);  	*/ +	return reinterpret_cast<T *>(prhs[0]); +} + + + + +bp::list mexFunction(np::ndarray input) { +	int number_of_dims = input.get_nd(); +	int dim_array[3]; + +	dim_array[0] = input.shape(0); +	dim_array[1] = input.shape(1); +	if (number_of_dims == 2) { +		dim_array[2] = -1; +	} +	else { +		dim_array[2] = input.shape(2); +	} + +	/**************************************************************************/ +	np::ndarray zz = zeros(3, dim_array, (int)0); +	np::ndarray fzz = zeros(3, dim_array, (float)0); +	/**************************************************************************/ + +	int * A = reinterpret_cast<int *>(input.get_data()); +	int * B = reinterpret_cast<int *>(zz.get_data()); +	float * C = reinterpret_cast<float *>(fzz.get_data()); + +	//Copy data and cast +	for (int i = 0; i < dim_array[0]; i++) { +		for (int j = 0; j < dim_array[1]; j++) { +			for (int k = 0; k < dim_array[2]; k++) { +				int index = k + dim_array[2] * j + dim_array[2] * dim_array[1] * i; +				int val = (*(A + index)); +				float fval = (float)val; +				std::memcpy(B + index, &val, sizeof(int)); +				std::memcpy(C + index, &fval, sizeof(float)); +			} +		} +	} + + +	bp::list result; + +	result.append<int>(number_of_dims); +	result.append<int>(dim_array[0]); +	result.append<int>(dim_array[1]); +	result.append<int>(dim_array[2]); +	result.append<np::ndarray>(zz); +	result.append<np::ndarray>(fzz); + +	//result.append<bp::tuple>(tup); +	return result; + +} + +bp::list SplitBregman_TV(np::ndarray input, double d_mu, int iter, double d_epsil, int methTV) { +	 +	// the result is in the following list +	bp::list result; +		  	int number_of_dims, iter, dimX, dimY, dimZ, ll, j, count, methTV; -	const int dim_array[3]; +	const int  *dim_array;  	float *A, *U = NULL, *U_old = NULL, *Dx = NULL, *Dy = NULL, *Dz = NULL, *Bx = NULL, *By = NULL, *Bz = NULL, lambda, mu, epsil, re, re1, re_old; - +	  	//number_of_dims = mxGetNumberOfDimensions(prhs[0]);  	//dim_array = mxGetDimensions(prhs[0]); -	number_of_dims = input.get_nd(); + +	int number_of_dims = input.get_nd(); +	int dim_array[3];  	dim_array[0] = input.shape(0);  	dim_array[1] = input.shape(1);  	if (number_of_dims == 2) { -		dim_array[2] = -11; +		dim_array[2] = -1;  	}  	else {  		dim_array[2] = input.shape(2);  	} -	/*Handling Matlab input data*/ +	// Parameter handling is be done in Python +	///*Handling Matlab input data*/  	//if ((nrhs < 2) || (nrhs > 5)) mexErrMsgTxt("At least 2 parameters is required: Image(2D/3D), Regularization parameter. The full list of parameters: Image(2D/3D), Regularization parameter, iterations number, tolerance, penalty type ('iso' or 'l1')"); -	/*Handling Matlab input data*/ +	///*Handling Matlab input data*/  	//A = (float *)mxGetData(prhs[0]); /*noisy image (2D/3D) */  	A = reinterpret_cast<float *>(input.get_data()); -  	//mu = (float)mxGetScalar(prhs[1]); /* regularization parameter */  	mu = (float)d_mu; +  	//iter = 35; /* default iterations number */ -	iter = niterations; +	  	//epsil = 0.0001; /* default tolerance constant */  	epsil = (float)d_epsil;  	//methTV = 0;  /* default isotropic TV penalty */ -	methTV = TV_type;  	//if ((nrhs == 3) || (nrhs == 4) || (nrhs == 5))  iter = (int)mxGetScalar(prhs[2]); /* iterations number */  	//if ((nrhs == 4) || (nrhs == 5))  epsil = (float)mxGetScalar(prhs[3]); /* tolerance constant */  	//if (nrhs == 5) { @@ -182,34 +243,31 @@ bp::list SplitBregman_TV(np::ndarray input, double d_mu, , int niterations, doub  	if (number_of_dims == 2) {  		dimZ = 1; /*2D case*/ -		/* -		mxArray *mxCreateNumericArray(mwSize ndim, const mwSize *dims, mxClassID classid, mxComplexity ComplexFlag); -args:  ndim: Number of dimensions. If you specify a value for ndim that is less than 2, mxCreateNumericArray automatically sets the number of dimensions to 2. -       dims: Dimensions array. Each element in the dimensions array contains the size of the array in that dimension. -	         For example, in C, setting dims[0] to 5 and dims[1] to 7 establishes a 5-by-7 mxArray. Usually there are ndim elements in the dims array. -       classid: Identifier for the class of the array, which determines the way the numerical data is represented in memory. -                For example, specifying mxINT16_CLASS in C causes each piece of numerical data in the mxArray to be represented as a 16-bit signed integer. -       ComplexFlag:  If the mxArray you are creating is to contain imaginary data, set ComplexFlag to mxCOMPLEX in C (1 in Fortran).  -	                 Otherwise, set ComplexFlag to mxREAL in C (0 in Fortran). - -					 mxCreateNumericArray initializes all its real data elements to 0. -*/ - -/* -		U = (float*)mxGetPr(plhs[0] = mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); -		U_old = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); -		Dx = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); -		Dy = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); -		Bx = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); -		By = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); -*/  		//U = (float*)mxGetPr(plhs[0] = mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); -		U = A = reinterpret_cast<float *>input.get_data(); -		U_old = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); -		Dx = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); -		Dy = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); -		Bx = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); -		By = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		//U_old = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		//Dx = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		//Dy = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		//Bx = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		//By = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		bp::tuple shape = bp::make_tuple(dim_array[0], dim_array[1]); +		np::dtype dtype = np::dtype::get_builtin<float>(); + +		np::ndarray npU     = np::zeros(shape, dtype); +		np::ndarray npU_old = np::zeros(shape, dtype); +		np::ndarray npDx    = np::zeros(shape, dtype); +		np::ndarray npDy    = np::zeros(shape, dtype); +		np::ndarray npBx    = np::zeros(shape, dtype); +		np::ndarray npBy    = np::zeros(shape, dtype); + +		U     = reinterpret_cast<float *>(npU.get_data()); +		U_old = reinterpret_cast<float *>(npU_old.get_data()); +		Dx    = reinterpret_cast<float *>(npDx.get_data()); +		Dy    = reinterpret_cast<float *>(npDy.get_data()); +		Bx    = reinterpret_cast<float *>(npBx.get_data()); +		By    = reinterpret_cast<float *>(npBy.get_data()); + +		 +  		copyIm(A, U, dimX, dimY, dimZ); /*initialize */  										/* begin outer SB iterations */ @@ -245,59 +303,370 @@ args:  ndim: Number of dimensions. If you specify a value for ndim that is less  			/*printf("%f %i %i \n", re, ll, count); */  			/*copyIm(U_old, U, dimX, dimY, dimZ); */ +			result.append<np::ndarray>(npU); +			result.append<int>(ll); +		} +		//printf("SB iterations stopped at iteration: %i\n", ll); +		if (number_of_dims == 3) { +			/*U = (float*)mxGetPr(plhs[0] = mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +			U_old = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +			Dx = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +			Dy = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +			Dz = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +			Bx = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +			By = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +			Bz = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL));*/ +			bp::tuple shape = bp::make_tuple(dim_array[0], dim_array[1], dim_array[2]); +			np::dtype dtype = np::dtype::get_builtin<float>(); + +			np::ndarray npU     = np::zeros(shape, dtype); +			np::ndarray npU_old = np::zeros(shape, dtype); +			np::ndarray npDx    = np::zeros(shape, dtype); +			np::ndarray npDy    = np::zeros(shape, dtype); +			np::ndarray npDz    = np::zeros(shape, dtype); +			np::ndarray npBx    = np::zeros(shape, dtype); +			np::ndarray npBy    = np::zeros(shape, dtype); +			np::ndarray npBz    = np::zeros(shape, dtype); + +			U     = reinterpret_cast<float *>(npU.get_data()); +			U_old = reinterpret_cast<float *>(npU_old.get_data()); +			Dx    = reinterpret_cast<float *>(npDx.get_data()); +			Dy    = reinterpret_cast<float *>(npDy.get_data()); +			Dz    = reinterpret_cast<float *>(npDz.get_data()); +			Bx    = reinterpret_cast<float *>(npBx.get_data()); +			By    = reinterpret_cast<float *>(npBy.get_data()); +			Bz    = reinterpret_cast<float *>(npBz.get_data()); + +			copyIm(A, U, dimX, dimY, dimZ); /*initialize */ + +											/* begin outer SB iterations */ +			for (ll = 0; ll<iter; ll++) { + +				/*storing old values*/ +				copyIm(U, U_old, dimX, dimY, dimZ); + +				/*GS iteration */ +				gauss_seidel3D(U, A, Dx, Dy, Dz, Bx, By, Bz, dimX, dimY, dimZ, lambda, mu); + +				if (methTV == 1) updDxDyDz_shrinkAniso3D(U, Dx, Dy, Dz, Bx, By, Bz, dimX, dimY, dimZ, lambda); +				else updDxDyDz_shrinkIso3D(U, Dx, Dy, Dz, Bx, By, Bz, dimX, dimY, dimZ, lambda); + +				updBxByBz3D(U, Dx, Dy, Dz, Bx, By, Bz, dimX, dimY, dimZ); + +				/* calculate norm to terminate earlier */ +				re = 0.0f; re1 = 0.0f; +				for (j = 0; j<dimX*dimY*dimZ; j++) +				{ +					re += pow(U[j] - U_old[j], 2); +					re1 += pow(U[j], 2); +				} +				re = sqrt(re) / sqrt(re1); +				if (re < epsil)  count++; +				if (count > 4) break; + +				/* check that the residual norm is decreasing */ +				if (ll > 2) { +					if (re > re_old) break; +				} +				/*printf("%f %i %i \n", re, ll, count); */ +				re_old = re; +			} +			//printf("SB iterations stopped at iteration: %i\n", ll); +			result.append<np::ndarray>(npU); +			result.append<int>(ll);  		} -		printf("SB iterations stopped at iteration: %i\n", ll);  	} -	if (number_of_dims == 3) { -		U = (float*)mxGetPr(plhs[0] = mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); -		U_old = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); -		Dx = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); -		Dy = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); -		Dz = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); -		Bx = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); -		By = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); -		Bz = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +	return result; -		copyIm(A, U, dimX, dimY, dimZ); /*initialize */ +} -										/* begin outer SB iterations */ +bp::list FGP_TV(np::ndarray input, double d_mu, int iter, double d_epsil, int methTV) { + +	// the result is in the following list +	bp::list result; + +	int number_of_dims, iter, dimX, dimY, dimZ, ll, j, count, methTV; +	float *A, *D = NULL, *D_old = NULL, *P1 = NULL, *P2 = NULL, *P3 = NULL, *P1_old = NULL, *P2_old = NULL, *P3_old = NULL, *R1 = NULL, *R2 = NULL, *R3 = NULL; +	float lambda, tk, tkp1, re, re1, re_old, epsil, funcval; + +	//number_of_dims = mxGetNumberOfDimensions(prhs[0]); +	//dim_array = mxGetDimensions(prhs[0]); + +	int number_of_dims = input.get_nd(); +	int dim_array[3]; + +	dim_array[0] = input.shape(0); +	dim_array[1] = input.shape(1); +	if (number_of_dims == 2) { +		dim_array[2] = -1; +	} +	else { +		dim_array[2] = input.shape(2); +	} + +	// Parameter handling is be done in Python +	///*Handling Matlab input data*/ +	//if ((nrhs < 2) || (nrhs > 5)) mexErrMsgTxt("At least 2 parameters is required: Image(2D/3D), Regularization parameter. The full list of parameters: Image(2D/3D), Regularization parameter, iterations number, tolerance, penalty type ('iso' or 'l1')"); + +	///*Handling Matlab input data*/ +	//A = (float *)mxGetData(prhs[0]); /*noisy image (2D/3D) */ +	A = reinterpret_cast<float *>(input.get_data()); + +	//mu = (float)mxGetScalar(prhs[1]); /* regularization parameter */ +	mu = (float)d_mu; + +	//iter = 35; /* default iterations number */ + +	//epsil = 0.0001; /* default tolerance constant */ +	epsil = (float)d_epsil; +	//methTV = 0;  /* default isotropic TV penalty */ +	//if ((nrhs == 3) || (nrhs == 4) || (nrhs == 5))  iter = (int)mxGetScalar(prhs[2]); /* iterations number */ +	//if ((nrhs == 4) || (nrhs == 5))  epsil = (float)mxGetScalar(prhs[3]); /* tolerance constant */ +	//if (nrhs == 5) { +	//	char *penalty_type; +	//	penalty_type = mxArrayToString(prhs[4]); /* choosing TV penalty: 'iso' or 'l1', 'iso' is the default */ +	//	if ((strcmp(penalty_type, "l1") != 0) && (strcmp(penalty_type, "iso") != 0)) mexErrMsgTxt("Choose TV type: 'iso' or 'l1',"); +	//	if (strcmp(penalty_type, "l1") == 0)  methTV = 1;  /* enable 'l1' penalty */ +	//	mxFree(penalty_type); +	//} +	//if (mxGetClassID(prhs[0]) != mxSINGLE_CLASS) { mexErrMsgTxt("The input image must be in a single precision"); } + +	//plhs[1] = mxCreateNumericMatrix(1, 1, mxSINGLE_CLASS, mxREAL); +	bp::tuple shape1 = bp::make_tuple(dim_array[0], dim_array[1]); +	np::dtype dtype = np::dtype::get_builtin<float>(); +	np::ndarray out1 = np::zeros(shape1, dtype); +	 +	//float *funcvalA = (float *)mxGetData(plhs[1]); +	float * funcvalA = reinterpret_cast<float *>(out1.get_data()); +	//if (mxGetClassID(prhs[0]) != mxSINGLE_CLASS) { mexErrMsgTxt("The input image must be in a single precision"); } + +	/*Handling Matlab output data*/ +	dimX = dim_array[0]; dimY = dim_array[1]; dimZ = dim_array[2]; + +	tk = 1.0f; +	tkp1 = 1.0f; +	count = 1; +	re_old = 0.0f; + +	if (number_of_dims == 2) { +		dimZ = 1; /*2D case*/ +		/*D = (float*)mxGetPr(plhs[0] = mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		D_old = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		P1 = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		P2 = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		P1_old = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		P2_old = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		R1 = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL)); +		R2 = (float*)mxGetPr(mxCreateNumericArray(2, dim_array, mxSINGLE_CLASS, mxREAL));*/ + +		bp::tuple shape = bp::make_tuple(dim_array[0], dim_array[1]); +		np::dtype dtype = np::dtype::get_builtin<float>(); + + +		np::ndarray npD      = np::zeros(shape, dtype); +		np::ndarray npD_old  = np::zeros(shape, dtype); +		np::ndarray npP1     = np::zeros(shape, dtype); +		np::ndarray npP2     = np::zeros(shape, dtype); +		np::ndarray npP1_old = np::zeros(shape, dtype); +		np::ndarray npP2_old = np::zeros(shape, dtype); +		np::ndarray npR1     = np::zeros(shape, dtype); +		np::ndarray npR2     = zeros(2, dim_array, (float)0); + +		D      = reinterpret_cast<float *>(npD.get_data()); +		D_old  = reinterpret_cast<float *>(npD_old.get_data()); +		P1     = reinterpret_cast<float *>(npP1.get_data()); +		P2     = reinterpret_cast<float *>(npP2.get_data()); +		P1_old = reinterpret_cast<float *>(npP1_old.get_data()); +		P2_old = reinterpret_cast<float *>(npP2_old.get_data()); +		R1     = reinterpret_cast<float *>(npR1.get_data()); +		R2     = reinterpret_cast<float *>(npR2.get_data()); + +		/* begin iterations */  		for (ll = 0; ll<iter; ll++) { -			/*storing old values*/ -			copyIm(U, U_old, dimX, dimY, dimZ); +			/* computing the gradient of the objective function */ +			Obj_func2D(A, D, R1, R2, lambda, dimX, dimY); -			/*GS iteration */ -			gauss_seidel3D(U, A, Dx, Dy, Dz, Bx, By, Bz, dimX, dimY, dimZ, lambda, mu); +			/*Taking a step towards minus of the gradient*/ +			Grad_func2D(P1, P2, D, R1, R2, lambda, dimX, dimY); -			if (methTV == 1) updDxDyDz_shrinkAniso3D(U, Dx, Dy, Dz, Bx, By, Bz, dimX, dimY, dimZ, lambda); -			else updDxDyDz_shrinkIso3D(U, Dx, Dy, Dz, Bx, By, Bz, dimX, dimY, dimZ, lambda); +			/* projection step */ +			Proj_func2D(P1, P2, methTV, dimX, dimY); -			updBxByBz3D(U, Dx, Dy, Dz, Bx, By, Bz, dimX, dimY, dimZ); +			/*updating R and t*/ +			tkp1 = (1.0f + sqrt(1.0f + 4.0f*tk*tk))*0.5f; +			Rupd_func2D(P1, P1_old, P2, P2_old, R1, R2, tkp1, tk, dimX, dimY); -			/* calculate norm to terminate earlier */ +			/* calculate norm */  			re = 0.0f; re1 = 0.0f;  			for (j = 0; j<dimX*dimY*dimZ; j++)  			{ -				re += pow(U[j] - U_old[j], 2); -				re1 += pow(U[j], 2); +				re += pow(D[j] - D_old[j], 2); +				re1 += pow(D[j], 2);  			}  			re = sqrt(re) / sqrt(re1);  			if (re < epsil)  count++; -			if (count > 4) break; +			if (count > 3) { +				Obj_func2D(A, D, P1, P2, lambda, dimX, dimY); +				funcval = 0.0f; +				for (j = 0; j<dimX*dimY*dimZ; j++) funcval += pow(D[j], 2); +				//funcvalA[0] = sqrt(funcval); +				float fv = sqrt(funcval); +				std::memcpy(funcvalA, &fv), sizeof(float)); +				break; +			}  			/* check that the residual norm is decreasing */  			if (ll > 2) { -				if (re > re_old) break; +				if (re > re_old) { +					Obj_func2D(A, D, P1, P2, lambda, dimX, dimY); +					funcval = 0.0f; +					for (j = 0; j<dimX*dimY*dimZ; j++) funcval += pow(D[j], 2); +					//funcvalA[0] = sqrt(funcval); +					float fv = sqrt(funcval); +					std::memcpy(funcvalA, &fv), sizeof(float)); +					break; +				}  			} +			re_old = re;  			/*printf("%f %i %i \n", re, ll, count); */ + +			/*storing old values*/ +			copyIm(D, D_old, dimX, dimY, dimZ); +			copyIm(P1, P1_old, dimX, dimY, dimZ); +			copyIm(P2, P2_old, dimX, dimY, dimZ); +			tk = tkp1; + +			/* calculating the objective function value */ +			if (ll == (iter - 1)) { +				Obj_func2D(A, D, P1, P2, lambda, dimX, dimY); +				funcval = 0.0f; +				for (j = 0; j<dimX*dimY*dimZ; j++) funcval += pow(D[j], 2); +				//funcvalA[0] = sqrt(funcval); +				float fv = sqrt(funcval); +				std::memcpy(funcvalA, &fv), sizeof(float)); +			} +		} +		//printf("FGP-TV iterations stopped at iteration %i with the function value %f \n", ll, funcvalA[0]); +		result.append<np::ndarray>(npD); +		result.append<np::ndarray>(out1); +		result.append<int>(ll); +	} +	if (number_of_dims == 3) { +		/*D = (float*)mxGetPr(plhs[0] = mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +		D_old = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +		P1 = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +		P2 = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +		P3 = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +		P1_old = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +		P2_old = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +		P3_old = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +		R1 = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +		R2 = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL)); +		R3 = (float*)mxGetPr(mxCreateNumericArray(3, dim_array, mxSINGLE_CLASS, mxREAL));*/ +		bp::tuple shape = bp::make_tuple(dim_array[0], dim_array[1], dim_array[2]); +		np::dtype dtype = np::dtype::get_builtin<float>(); +		 +		np::ndarray npD      = np::zeros(shape, dtype); +		np::ndarray npD_old  = np::zeros(shape, dtype); +		np::ndarray npP1     = np::zeros(shape, dtype); +		np::ndarray npP2     = np::zeros(shape, dtype); +		np::ndarray npP3     = np::zeros(shape, dtype); +		np::ndarray npP1_old = np::zeros(shape, dtype); +		np::ndarray npP2_old = np::zeros(shape, dtype); +		np::ndarray npP3_old = np::zeros(shape, dtype); +		np::ndarray npR1     = np::zeros(shape, dtype); +		np::ndarray npR2     = np::zeros(shape, dtype); +		np::ndarray npR3     = np::zeros(shape, dtype); + +		D      = reinterpret_cast<float *>(npD.get_data()); +		D_old  = reinterpret_cast<float *>(npD_old.get_data()); +		P1     = reinterpret_cast<float *>(npP1.get_data()); +		P2     = reinterpret_cast<float *>(npP2.get_data()); +		P3     = reinterpret_cast<float *>(npP3.get_data()); +		P1_old = reinterpret_cast<float *>(npP1_old.get_data()); +		P2_old = reinterpret_cast<float *>(npP2_old.get_data()); +		P3_old = reinterpret_cast<float *>(npP3_old.get_data()); +		R1     = reinterpret_cast<float *>(npR1.get_data()); +		R2     = reinterpret_cast<float *>(npR2.get_data()); +		R2     = reinterpret_cast<float *>(npR3.get_data()); +		/* begin iterations */ +		for (ll = 0; ll<iter; ll++) { + +			/* computing the gradient of the objective function */ +			Obj_func3D(A, D, R1, R2, R3, lambda, dimX, dimY, dimZ); + +			/*Taking a step towards minus of the gradient*/ +			Grad_func3D(P1, P2, P3, D, R1, R2, R3, lambda, dimX, dimY, dimZ); + +			/* projection step */ +			Proj_func3D(P1, P2, P3, dimX, dimY, dimZ); + +			/*updating R and t*/ +			tkp1 = (1.0f + sqrt(1.0f + 4.0f*tk*tk))*0.5f; +			Rupd_func3D(P1, P1_old, P2, P2_old, P3, P3_old, R1, R2, R3, tkp1, tk, dimX, dimY, dimZ); + +			/* calculate norm - stopping rules*/ +			re = 0.0f; re1 = 0.0f; +			for (j = 0; j<dimX*dimY*dimZ; j++) +			{ +				re += pow(D[j] - D_old[j], 2); +				re1 += pow(D[j], 2); +			} +			re = sqrt(re) / sqrt(re1); +			/* stop if the norm residual is less than the tolerance EPS */ +			if (re < epsil)  count++; +			if (count > 3) { +				Obj_func3D(A, D, P1, P2, P3, lambda, dimX, dimY, dimZ); +				funcval = 0.0f; +				for (j = 0; j<dimX*dimY*dimZ; j++) funcval += pow(D[j], 2); +				//funcvalA[0] = sqrt(funcval); +				float fv = sqrt(funcval); +				std::memcpy(funcvalA, &fv), sizeof(float)); +				break; +			} + +			/* check that the residual norm is decreasing */ +			if (ll > 2) { +				if (re > re_old) { +					Obj_func3D(A, D, P1, P2, P3, lambda, dimX, dimY, dimZ); +					funcval = 0.0f; +					for (j = 0; j<dimX*dimY*dimZ; j++) funcval += pow(D[j], 2); +					//funcvalA[0] = sqrt(funcval); +					float fv = sqrt(funcval); +					std::memcpy(funcvalA, &fv), sizeof(float)); +					break; +				} +			} +  			re_old = re; +			/*printf("%f %i %i \n", re, ll, count); */ + +			/*storing old values*/ +			copyIm(D, D_old, dimX, dimY, dimZ); +			copyIm(P1, P1_old, dimX, dimY, dimZ); +			copyIm(P2, P2_old, dimX, dimY, dimZ); +			copyIm(P3, P3_old, dimX, dimY, dimZ); +			tk = tkp1; + +			if (ll == (iter - 1)) { +				Obj_func3D(A, D, P1, P2, P3, lambda, dimX, dimY, dimZ); +				funcval = 0.0f; +				for (j = 0; j<dimX*dimY*dimZ; j++) funcval += pow(D[j], 2); +				//funcvalA[0] = sqrt(funcval); +				float fv = sqrt(funcval); +				std::memcpy(funcvalA, &fv), sizeof(float)); +			} +  		} -		printf("SB iterations stopped at iteration: %i\n", ll); +		//printf("FGP-TV iterations stopped at iteration %i with the function value %f \n", ll, funcvalA[0]); +		result.append<np::ndarray>(npD); +		result.append<np::ndarray>(out1); +		result.append<int>(ll);  	} -	bp::list result; +  	return result;  } -	  BOOST_PYTHON_MODULE(fista)  { @@ -310,6 +679,7 @@ BOOST_PYTHON_MODULE(fista)  	np::dtype dt1 = np::dtype::get_builtin<uint8_t>();  	np::dtype dt2 = np::dtype::get_builtin<uint16_t>(); -	  	def("mexFunction", mexFunction); +	def("SplitBregman_TV", SplitBregman_TV); +	def("FGP_TV", FGP_TV);  }
\ No newline at end of file  | 
