diff options
author | algol <dkazanc@hotmail.com> | 2018-04-19 13:24:30 +0100 |
---|---|---|
committer | algol <dkazanc@hotmail.com> | 2018-04-19 13:24:30 +0100 |
commit | b1b26855c4cd5a3e2624b280b64adeda6793b4d7 (patch) | |
tree | f3fbf76cfd2350c8794163845dc94c012c04a3a8 | |
parent | 0e9b9afa6a4c3ddb7afa1437204846c515386d15 (diff) | |
download | regularization-b1b26855c4cd5a3e2624b280b64adeda6793b4d7.tar.gz regularization-b1b26855c4cd5a3e2624b280b64adeda6793b4d7.tar.bz2 regularization-b1b26855c4cd5a3e2624b280b64adeda6793b4d7.tar.xz regularization-b1b26855c4cd5a3e2624b280b64adeda6793b4d7.zip |
Anisotropic Diffusion modules added for 2D/3D CPU/GPU
-rw-r--r-- | Core/CMakeLists.txt | 2 | ||||
-rw-r--r-- | Core/regularisers_CPU/Diffusion_core.c | 22 | ||||
-rw-r--r-- | Core/regularisers_GPU/NonlDiff_GPU_core.cu | 155 | ||||
-rw-r--r-- | Wrappers/Matlab/demos/demoMatlab_3Ddenoise.m | 8 | ||||
-rw-r--r-- | Wrappers/Python/ccpi/filters/regularisers.py | 23 | ||||
-rw-r--r-- | Wrappers/Python/demos/demo_cpu_regularisers.py | 106 | ||||
-rw-r--r-- | Wrappers/Python/demos/demo_cpu_vs_gpu_regularisers.py | 91 | ||||
-rw-r--r-- | Wrappers/Python/demos/demo_gpu_regularisers.py | 114 | ||||
-rw-r--r-- | Wrappers/Python/setup-regularisers.py.in | 1 | ||||
-rw-r--r-- | Wrappers/Python/src/cpu_regularisers.pyx | 46 | ||||
-rw-r--r-- | Wrappers/Python/src/gpu_regularisers.pyx | 67 |
11 files changed, 594 insertions, 41 deletions
diff --git a/Core/CMakeLists.txt b/Core/CMakeLists.txt index 4142ed9..61986dc 100644 --- a/Core/CMakeLists.txt +++ b/Core/CMakeLists.txt @@ -85,6 +85,7 @@ message("Adding regularisers as a shared library") add_library(cilreg SHARED ${CMAKE_CURRENT_SOURCE_DIR}/regularisers_CPU/FGP_TV_core.c ${CMAKE_CURRENT_SOURCE_DIR}/regularisers_CPU/SB_TV_core.c + ${CMAKE_CURRENT_SOURCE_DIR}/regularisers_CPU/Diffusion_core.c #${CMAKE_CURRENT_SOURCE_DIR}/regularisers_CPU/LLT_model_core.c #${CMAKE_CURRENT_SOURCE_DIR}/regularisers_CPU/PatchBased_Regul_core.c #${CMAKE_CURRENT_SOURCE_DIR}/regularisers_CPU/TGV_PD_core.c @@ -133,6 +134,7 @@ if (CUDA_FOUND) ${CMAKE_CURRENT_SOURCE_DIR}/regularisers_GPU/TV_FGP_GPU_core.cu ${CMAKE_CURRENT_SOURCE_DIR}/regularisers_GPU/TV_SB_GPU_core.cu ${CMAKE_CURRENT_SOURCE_DIR}/regularisers_GPU/dTV_FGP_GPU_core.cu + ${CMAKE_CURRENT_SOURCE_DIR}/regularisers_GPU/NonlDiff_GPU_core.cu ) if (UNIX) message ("I'd install into ${CMAKE_INSTALL_PREFIX}/lib") diff --git a/Core/regularisers_CPU/Diffusion_core.c b/Core/regularisers_CPU/Diffusion_core.c index 7ad07cd..51d0a57 100644 --- a/Core/regularisers_CPU/Diffusion_core.c +++ b/Core/regularisers_CPU/Diffusion_core.c @@ -25,7 +25,7 @@ #define MIN(x, y) (((x) < (y)) ? (x) : (y)) /*sign function*/ -int sign(float x) { +int signNDFc(float x) { return (x > 0) - (x < 0); } @@ -139,16 +139,16 @@ float NonLinearDiff2D(float *Input, float *Output, float lambdaPar, float sigmaP if (penaltytype == 1){ /* Huber penalty */ - if (fabs(e1) > sigmaPar) e1 = sign(e1); + if (fabs(e1) > sigmaPar) e1 = signNDFc(e1); else e1 = e1/sigmaPar; - if (fabs(w1) > sigmaPar) w1 = sign(w1); + if (fabs(w1) > sigmaPar) w1 = signNDFc(w1); else w1 = w1/sigmaPar; - if (fabs(n1) > sigmaPar) n1 = sign(n1); + if (fabs(n1) > sigmaPar) n1 = signNDFc(n1); else n1 = n1/sigmaPar; - if (fabs(s1) > sigmaPar) s1 = sign(s1); + if (fabs(s1) > sigmaPar) s1 = signNDFc(s1); else s1 = s1/sigmaPar; } else if (penaltytype == 2) { @@ -254,22 +254,22 @@ for(k=0; k<dimZ; k++) { if (penaltytype == 1){ /* Huber penalty */ - if (fabs(e1) > sigmaPar) e1 = sign(e1); + if (fabs(e1) > sigmaPar) e1 = signNDFc(e1); else e1 = e1/sigmaPar; - if (fabs(w1) > sigmaPar) w1 = sign(w1); + if (fabs(w1) > sigmaPar) w1 = signNDFc(w1); else w1 = w1/sigmaPar; - if (fabs(n1) > sigmaPar) n1 = sign(n1); + if (fabs(n1) > sigmaPar) n1 = signNDFc(n1); else n1 = n1/sigmaPar; - if (fabs(s1) > sigmaPar) s1 = sign(s1); + if (fabs(s1) > sigmaPar) s1 = signNDFc(s1); else s1 = s1/sigmaPar; - if (fabs(u1) > sigmaPar) u1 = sign(u1); + if (fabs(u1) > sigmaPar) u1 = signNDFc(u1); else u1 = u1/sigmaPar; - if (fabs(d1) > sigmaPar) d1 = sign(d1); + if (fabs(d1) > sigmaPar) d1 = signNDFc(d1); else d1 = d1/sigmaPar; } else if (penaltytype == 2) { diff --git a/Core/regularisers_GPU/NonlDiff_GPU_core.cu b/Core/regularisers_GPU/NonlDiff_GPU_core.cu index 7968c8e..be9f5f1 100644 --- a/Core/regularisers_GPU/NonlDiff_GPU_core.cu +++ b/Core/regularisers_GPU/NonlDiff_GPU_core.cu @@ -38,7 +38,6 @@ limitations under the License. * [2] Black, M.J., Sapiro, G., Marimont, D.H. and Heeger, D., 1998. Robust anisotropic diffusion. IEEE Transactions on image processing, 7(3), pp.421-432. */ - #define CHECK(call) \ { \ const cudaError_t error = call; \ @@ -64,7 +63,7 @@ limitations under the License. #define MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y)) -__host__ __device__ int sign (float x) +__host__ __device__ int signNDF (float x) { return (x > 0) - (x < 0); } @@ -132,16 +131,16 @@ __global__ void LinearDiff2D_kernel(float *Input, float *Output, float lambdaPar if (penaltytype == 1){ /* Huber penalty */ - if (abs(e1) > sigmaPar) e1 = sign(e1); + if (abs(e1) > sigmaPar) e1 = signNDF(e1); else e1 = e1/sigmaPar; - if (abs(w1) > sigmaPar) w1 = sign(w1); + if (abs(w1) > sigmaPar) w1 = signNDF(w1); else w1 = w1/sigmaPar; - if (abs(n1) > sigmaPar) n1 = sign(n1); + if (abs(n1) > sigmaPar) n1 = signNDF(n1); else n1 = n1/sigmaPar; - if (abs(s1) > sigmaPar) s1 = sign(s1); + if (abs(s1) > sigmaPar) s1 = signNDF(s1); else s1 = s1/sigmaPar; } else if (penaltytype == 2) { @@ -171,6 +170,129 @@ __global__ void LinearDiff2D_kernel(float *Input, float *Output, float lambdaPar /***************************3D Functions*****************************/ /********************************************************************/ +__global__ void LinearDiff3D_kernel(float *Input, float *Output, float lambdaPar, float tau, int N, int M, int Z) + { + int i1,i2,j1,j2,k1,k2; + float e,w,n,s,u,d,e1,w1,n1,s1,u1,d1; + int i = blockDim.x * blockIdx.x + threadIdx.x; + int j = blockDim.y * blockIdx.y + threadIdx.y; + int k = blockDim.z * blockIdx.z + threadIdx.z; + + int index = (N*M)*k + i + N*j; + + if ((i >= 0) && (i < N) && (j >= 0) && (j < M) && (k >= 0) && (k < Z)) { + + /* boundary conditions (Neumann reflections) */ + i1 = i+1; if (i1 == N) i1 = i-1; + i2 = i-1; if (i2 < 0) i2 = i+1; + j1 = j+1; if (j1 == M) j1 = j-1; + j2 = j-1; if (j2 < 0) j2 = j+1; + k1 = k+1; if (k1 == Z) k1 = k-1; + k2 = k-1; if (k2 < 0) k2 = k+1; + + e = Output[(N*M)*k + i1 + N*j]; + w = Output[(N*M)*k + i2 + N*j]; + n = Output[(N*M)*k + i + N*j1]; + s = Output[(N*M)*k + i + N*j2]; + u = Output[(N*M)*k1 + i + N*j]; + d = Output[(N*M)*k2 + i + N*j]; + + e1 = e - Output[index]; + w1 = w - Output[index]; + n1 = n - Output[index]; + s1 = s - Output[index]; + u1 = u - Output[index]; + d1 = d - Output[index]; + + Output[index] += tau*(lambdaPar*(e1 + w1 + n1 + s1 + u1 + d1) - (Output[index] - Input[index])); + } + } + +__global__ void NonLinearDiff3D_kernel(float *Input, float *Output, float lambdaPar, float sigmaPar, float tau, int penaltytype, int N, int M, int Z) + { + int i1,i2,j1,j2,k1,k2; + float e,w,n,s,u,d,e1,w1,n1,s1,u1,d1; + int i = blockDim.x * blockIdx.x + threadIdx.x; + int j = blockDim.y * blockIdx.y + threadIdx.y; + int k = blockDim.z * blockIdx.z + threadIdx.z; + + int index = (N*M)*k + i + N*j; + + if ((i >= 0) && (i < N) && (j >= 0) && (j < M) && (k >= 0) && (k < Z)) { + + /* boundary conditions (Neumann reflections) */ + i1 = i+1; if (i1 == N) i1 = i-1; + i2 = i-1; if (i2 < 0) i2 = i+1; + j1 = j+1; if (j1 == M) j1 = j-1; + j2 = j-1; if (j2 < 0) j2 = j+1; + k1 = k+1; if (k1 == Z) k1 = k-1; + k2 = k-1; if (k2 < 0) k2 = k+1; + + e = Output[(N*M)*k + i1 + N*j]; + w = Output[(N*M)*k + i2 + N*j]; + n = Output[(N*M)*k + i + N*j1]; + s = Output[(N*M)*k + i + N*j2]; + u = Output[(N*M)*k1 + i + N*j]; + d = Output[(N*M)*k2 + i + N*j]; + + e1 = e - Output[index]; + w1 = w - Output[index]; + n1 = n - Output[index]; + s1 = s - Output[index]; + u1 = u - Output[index]; + d1 = d - Output[index]; + + + if (penaltytype == 1){ + /* Huber penalty */ + if (abs(e1) > sigmaPar) e1 = signNDF(e1); + else e1 = e1/sigmaPar; + + if (abs(w1) > sigmaPar) w1 = signNDF(w1); + else w1 = w1/sigmaPar; + + if (abs(n1) > sigmaPar) n1 = signNDF(n1); + else n1 = n1/sigmaPar; + + if (abs(s1) > sigmaPar) s1 = signNDF(s1); + else s1 = s1/sigmaPar; + + if (abs(u1) > sigmaPar) u1 = signNDF(u1); + else u1 = u1/sigmaPar; + + if (abs(d1) > sigmaPar) d1 = signNDF(d1); + else d1 = d1/sigmaPar; + } + else if (penaltytype == 2) { + /* Perona-Malik */ + e1 = (e1)/(1.0f + pow((e1/sigmaPar),2)); + w1 = (w1)/(1.0f + pow((w1/sigmaPar),2)); + n1 = (n1)/(1.0f + pow((n1/sigmaPar),2)); + s1 = (s1)/(1.0f + pow((s1/sigmaPar),2)); + u1 = (u1)/(1.0f + pow((u1/sigmaPar),2)); + d1 = (d1)/(1.0f + pow((d1/sigmaPar),2)); + } + else if (penaltytype == 3) { + /* Tukey Biweight */ + if (abs(e1) <= sigmaPar) e1 = e1*pow((1.0f - pow((e1/sigmaPar),2)), 2); + else e1 = 0.0f; + if (abs(w1) <= sigmaPar) w1 = w1*pow((1.0f - pow((w1/sigmaPar),2)), 2); + else w1 = 0.0f; + if (abs(n1) <= sigmaPar) n1 = n1*pow((1.0f - pow((n1/sigmaPar),2)), 2); + else n1 = 0.0f; + if (abs(s1) <= sigmaPar) s1 = s1*pow((1.0f - pow((s1/sigmaPar),2)), 2); + else s1 = 0.0f; + if (abs(u1) <= sigmaPar) u1 = u1*pow((1.0f - pow((u1/sigmaPar),2)), 2); + else u1 = 0.0f; + if (abs(d1) <= sigmaPar) d1 = d1*pow((1.0f - pow((d1/sigmaPar),2)), 2); + else d1 = 0.0f; + } + else printf("%s \n", "No penalty function selected! Use 1,2 or 3."); + + Output[index] += tau*(lambdaPar*(e1 + w1 + n1 + s1 + u1 + d1) - (Output[index] - Input[index])); + } + } + ///////////////////////////////////////////////// // HOST FUNCTION extern "C" void NonlDiff_GPU_main(float *Input, float *Output, float lambdaPar, float sigmaPar, int iterationsNumb, float tau, int penaltytype, int N, int M, int Z) @@ -182,14 +304,15 @@ extern "C" void NonlDiff_GPU_main(float *Input, float *Output, float lambdaPar, float sigmaPar2; sigmaPar2 = sigmaPar/sqrt(2.0f); - if (Z == 1) { - /*2D case */ CHECK(cudaMalloc((void**)&d_input,N*M*Z*sizeof(float))); CHECK(cudaMalloc((void**)&d_output,N*M*Z*sizeof(float))); CHECK(cudaMemcpy(d_input,Input,N*M*Z*sizeof(float),cudaMemcpyHostToDevice)); CHECK(cudaMemcpy(d_output,Input,N*M*Z*sizeof(float),cudaMemcpyHostToDevice)); + if (Z == 1) { + /*2D case */ + dim3 dimBlock(BLKXSIZE2D,BLKYSIZE2D); dim3 dimGrid(idivup(N,BLKXSIZE2D), idivup(M,BLKYSIZE2D)); @@ -208,8 +331,22 @@ extern "C" void NonlDiff_GPU_main(float *Input, float *Output, float lambdaPar, } else { /*3D case*/ - } + dim3 dimBlock(BLKXSIZE,BLKYSIZE,BLKZSIZE); + dim3 dimGrid(idivup(N,BLKXSIZE), idivup(M,BLKYSIZE),idivup(Z,BLKZSIZE)); + for(int n=0; n < iterationsNumb; n++) { + if (sigmaPar == 0.0f) { + /* linear diffusion (heat equation) */ + LinearDiff3D_kernel<<<dimGrid,dimBlock>>>(d_input, d_output, lambdaPar, tau, N, M, Z); + CHECK(cudaDeviceSynchronize()); + } + else { + /* nonlinear diffusion */ + NonLinearDiff3D_kernel<<<dimGrid,dimBlock>>>(d_input, d_output, lambdaPar, sigmaPar2, tau, penaltytype, N, M, Z); + CHECK(cudaDeviceSynchronize()); + } + } + } CHECK(cudaMemcpy(Output,d_output,N*M*Z*sizeof(float),cudaMemcpyDeviceToHost)); CHECK(cudaFree(d_input)); CHECK(cudaFree(d_output)); diff --git a/Wrappers/Matlab/demos/demoMatlab_3Ddenoise.m b/Wrappers/Matlab/demos/demoMatlab_3Ddenoise.m index 502b6bd..973d060 100644 --- a/Wrappers/Matlab/demos/demoMatlab_3Ddenoise.m +++ b/Wrappers/Matlab/demos/demoMatlab_3Ddenoise.m @@ -62,6 +62,14 @@ tau_param = 0.025; % time-marching constant tic; u_diff = NonlDiff(single(vol3D), lambda_regDiff, sigmaPar, iter_diff, tau_param, 'Huber'); toc; figure; imshow(u_diff(:,:,15), [0 1]); title('Diffusion denoised volume (CPU)'); %% +% fprintf('Denoise a volume using Nonlinear-Diffusion model (GPU) \n'); +% iter_diff = 300; % number of diffusion iterations +% lambda_regDiff = 0.06; % regularisation for the diffusivity +% sigmaPar = 0.04; % edge-preserving parameter +% tau_param = 0.025; % time-marching constant +% tic; u_diff_g = NonlDiff_GPU(single(vol3D), lambda_regDiff, sigmaPar, iter_diff, tau_param, 'Huber'); toc; +% figure; imshow(u_diff_g(:,:,15), [0 1]); title('Diffusion denoised volume (GPU)'); +%% %>>>>>>>>>>>>>> MULTI-CHANNEL priors <<<<<<<<<<<<<<< % fprintf('Denoise a volume using the FGP-dTV model (CPU) \n'); diff --git a/Wrappers/Python/ccpi/filters/regularisers.py b/Wrappers/Python/ccpi/filters/regularisers.py index e6814e8..eec8c4d 100644 --- a/Wrappers/Python/ccpi/filters/regularisers.py +++ b/Wrappers/Python/ccpi/filters/regularisers.py @@ -2,8 +2,8 @@ script which assigns a proper device core function based on a flag ('cpu' or 'gpu') """ -from ccpi.filters.cpu_regularisers_cython import TV_ROF_CPU, TV_FGP_CPU, TV_SB_CPU, dTV_FGP_CPU, TNV_CPU -from ccpi.filters.gpu_regularisers import TV_ROF_GPU, TV_FGP_GPU, TV_SB_GPU, dTV_FGP_GPU +from ccpi.filters.cpu_regularisers_cython import TV_ROF_CPU, TV_FGP_CPU, TV_SB_CPU, dTV_FGP_CPU, TNV_CPU, NDF_CPU +from ccpi.filters.gpu_regularisers import TV_ROF_GPU, TV_FGP_GPU, TV_SB_GPU, dTV_FGP_GPU, NDF_GPU def ROF_TV(inputData, regularisation_parameter, iterations, time_marching_parameter,device='cpu'): @@ -91,3 +91,22 @@ def TNV(inputData, regularisation_parameter, iterations, tolerance_param): regularisation_parameter, iterations, tolerance_param) +def NDF(inputData, regularisation_parameter, edge_parameter, iterations, + time_marching_parameter, penalty_type, device='cpu'): + if device == 'cpu': + return NDF_CPU(inputData, + regularisation_parameter, + edge_parameter, + iterations, + time_marching_parameter, + penalty_type) + elif device == 'gpu': + return NDF_GPU(inputData, + regularisation_parameter, + edge_parameter, + iterations, + time_marching_parameter, + penalty_type) + else: + raise ValueError('Unknown device {0}. Expecting gpu or cpu'\ + .format(device)) diff --git a/Wrappers/Python/demos/demo_cpu_regularisers.py b/Wrappers/Python/demos/demo_cpu_regularisers.py index 7443b83..3567f91 100644 --- a/Wrappers/Python/demos/demo_cpu_regularisers.py +++ b/Wrappers/Python/demos/demo_cpu_regularisers.py @@ -12,7 +12,7 @@ import matplotlib.pyplot as plt import numpy as np import os import timeit -from ccpi.filters.regularisers import ROF_TV, FGP_TV, SB_TV, FGP_dTV, TNV +from ccpi.filters.regularisers import ROF_TV, FGP_TV, SB_TV, FGP_dTV, TNV, NDF from qualitymetrics import rmse ############################################################################### def printParametersToString(pars): @@ -190,11 +190,58 @@ plt.title('{}'.format('CPU results')) print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") -print ("_____________FGP-dTV (2D)__________________") +print ("________________NDF (2D)___________________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot fig = plt.figure(4) +plt.suptitle('Performance of NDF regulariser using the CPU') +a=fig.add_subplot(1,2,1) +a.set_title('Noisy Image') +imgplot = plt.imshow(u0,cmap="gray") + +# set parameters +pars = {'algorithm' : NDF, \ + 'input' : u0,\ + 'regularisation_parameter':0.06, \ + 'edge_parameter':0.04,\ + 'number_of_iterations' :1000 ,\ + 'time_marching_parameter':0.025,\ + 'penalty_type':1 + } + +print ("#############NDF CPU################") +start_time = timeit.default_timer() +ndf_cpu = NDF(pars['input'], + pars['regularisation_parameter'], + pars['edge_parameter'], + pars['number_of_iterations'], + pars['time_marching_parameter'], + pars['penalty_type'],'cpu') + +rms = rmse(Im, ndf_cpu) +pars['rmse'] = rms + +txtstr = printParametersToString(pars) +txtstr += "%s = %.3fs" % ('elapsed time',timeit.default_timer() - start_time) +print (txtstr) +a=fig.add_subplot(1,2,2) + +# these are matplotlib.patch.Patch properties +props = dict(boxstyle='round', facecolor='wheat', alpha=0.75) +# place a text box in upper left in axes coords +a.text(0.15, 0.25, txtstr, transform=a.transAxes, fontsize=14, + verticalalignment='top', bbox=props) +imgplot = plt.imshow(ndf_cpu, cmap="gray") +plt.title('{}'.format('CPU results')) + + +print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") +print ("_____________FGP-dTV (2D)__________________") +print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") + +## plot +fig = plt.figure(5) plt.suptitle('Performance of FGP-dTV regulariser using the CPU') a=fig.add_subplot(1,2,1) a.set_title('Noisy Image') @@ -247,7 +294,7 @@ print ("__________Total nuclear Variation__________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot -fig = plt.figure(5) +fig = plt.figure(6) plt.suptitle('Performance of TNV regulariser using the CPU') a=fig.add_subplot(1,2,1) a.set_title('Noisy Image') @@ -321,7 +368,7 @@ print ("_______________ROF-TV (3D)_________________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot -fig = plt.figure(6) +fig = plt.figure(7) plt.suptitle('Performance of ROF-TV regulariser using the CPU') a=fig.add_subplot(1,2,1) a.set_title('Noisy 15th slice of a volume') @@ -361,7 +408,7 @@ print ("_______________FGP-TV (3D)__________________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot -fig = plt.figure(7) +fig = plt.figure(8) plt.suptitle('Performance of FGP-TV regulariser using the CPU') a=fig.add_subplot(1,2,1) a.set_title('Noisy Image') @@ -410,7 +457,7 @@ print ("_______________SB-TV (3D)_________________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot -fig = plt.figure(8) +fig = plt.figure(9) plt.suptitle('Performance of SB-TV regulariser using the CPU') a=fig.add_subplot(1,2,1) a.set_title('Noisy Image') @@ -451,13 +498,58 @@ a.text(0.15, 0.25, txtstr, transform=a.transAxes, fontsize=14, imgplot = plt.imshow(sb_cpu3D[10,:,:], cmap="gray") plt.title('{}'.format('Recovered volume on the CPU using SB-TV')) +print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") +print ("________________NDF (3D)___________________") +print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") + +## plot +fig = plt.figure(10) +plt.suptitle('Performance of NDF regulariser using the CPU') +a=fig.add_subplot(1,2,1) +a.set_title('Noisy volume') +imgplot = plt.imshow(noisyVol[10,:,:],cmap="gray") + +# set parameters +pars = {'algorithm' : NDF, \ + 'input' : noisyVol,\ + 'regularisation_parameter':0.06, \ + 'edge_parameter':0.04,\ + 'number_of_iterations' :1000 ,\ + 'time_marching_parameter':0.025,\ + 'penalty_type': 1 + } + +print ("#############NDF CPU################") +start_time = timeit.default_timer() +ndf_cpu3D = NDF(pars['input'], + pars['regularisation_parameter'], + pars['edge_parameter'], + pars['number_of_iterations'], + pars['time_marching_parameter'], + pars['penalty_type']) + +rms = rmse(idealVol, ndf_cpu3D) +pars['rmse'] = rms + +txtstr = printParametersToString(pars) +txtstr += "%s = %.3fs" % ('elapsed time',timeit.default_timer() - start_time) +print (txtstr) +a=fig.add_subplot(1,2,2) + +# these are matplotlib.patch.Patch properties +props = dict(boxstyle='round', facecolor='wheat', alpha=0.75) +# place a text box in upper left in axes coords +a.text(0.15, 0.25, txtstr, transform=a.transAxes, fontsize=14, + verticalalignment='top', bbox=props) +imgplot = plt.imshow(ndf_cpu3D[10,:,:], cmap="gray") +plt.title('{}'.format('Recovered volume on the CPU using NDF iterations')) print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print ("_______________FGP-dTV (3D)__________________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot -fig = plt.figure(9) +fig = plt.figure(11) plt.suptitle('Performance of FGP-dTV regulariser using the CPU') a=fig.add_subplot(1,2,1) a.set_title('Noisy Image') diff --git a/Wrappers/Python/demos/demo_cpu_vs_gpu_regularisers.py b/Wrappers/Python/demos/demo_cpu_vs_gpu_regularisers.py index d8e2da7..05db23e 100644 --- a/Wrappers/Python/demos/demo_cpu_vs_gpu_regularisers.py +++ b/Wrappers/Python/demos/demo_cpu_vs_gpu_regularisers.py @@ -12,7 +12,7 @@ import matplotlib.pyplot as plt import numpy as np import os import timeit -from ccpi.filters.regularisers import ROF_TV, FGP_TV, SB_TV, FGP_dTV +from ccpi.filters.regularisers import ROF_TV, FGP_TV, SB_TV, FGP_dTV, NDF from qualitymetrics import rmse ############################################################################### def printParametersToString(pars): @@ -306,11 +306,98 @@ else: print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") -print ("____________FGP-dTV bench___________________") +print ("_______________NDF bench___________________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot fig = plt.figure(4) +plt.suptitle('Comparison of NDF regulariser using CPU and GPU implementations') +a=fig.add_subplot(1,4,1) +a.set_title('Noisy Image') +imgplot = plt.imshow(u0,cmap="gray") + +# set parameters +pars = {'algorithm' : NDF, \ + 'input' : u0,\ + 'regularisation_parameter':0.06, \ + 'edge_parameter':0.04,\ + 'number_of_iterations' :1000 ,\ + 'time_marching_parameter':0.025,\ + 'penalty_type': 1 + } + +print ("#############NDF CPU####################") +start_time = timeit.default_timer() +ndf_cpu = NDF(pars['input'], + pars['regularisation_parameter'], + pars['edge_parameter'], + pars['number_of_iterations'], + pars['time_marching_parameter'], + pars['penalty_type'],'cpu') + +rms = rmse(Im, ndf_cpu) +pars['rmse'] = rms + +txtstr = printParametersToString(pars) +txtstr += "%s = %.3fs" % ('elapsed time',timeit.default_timer() - start_time) +print (txtstr) +a=fig.add_subplot(1,4,2) + +# these are matplotlib.patch.Patch properties +props = dict(boxstyle='round', facecolor='wheat', alpha=0.75) +# place a text box in upper left in axes coords +a.text(0.15, 0.25, txtstr, transform=a.transAxes, fontsize=14, + verticalalignment='top', bbox=props) +imgplot = plt.imshow(ndf_cpu, cmap="gray") +plt.title('{}'.format('CPU results')) + + +print ("##############NDF GPU##################") +start_time = timeit.default_timer() +ndf_gpu = NDF(pars['input'], + pars['regularisation_parameter'], + pars['edge_parameter'], + pars['number_of_iterations'], + pars['time_marching_parameter'], + pars['penalty_type'],'gpu') + +rms = rmse(Im, ndf_gpu) +pars['rmse'] = rms +pars['algorithm'] = NDF +txtstr = printParametersToString(pars) +txtstr += "%s = %.3fs" % ('elapsed time',timeit.default_timer() - start_time) +print (txtstr) +a=fig.add_subplot(1,4,3) + +# these are matplotlib.patch.Patch properties +props = dict(boxstyle='round', facecolor='wheat', alpha=0.75) +# place a text box in upper left in axes coords +a.text(0.15, 0.25, txtstr, transform=a.transAxes, fontsize=14, + verticalalignment='top', bbox=props) +imgplot = plt.imshow(ndf_gpu, cmap="gray") +plt.title('{}'.format('GPU results')) + +print ("--------Compare the results--------") +tolerance = 1e-05 +diff_im = np.zeros(np.shape(rof_cpu)) +diff_im = abs(ndf_cpu - ndf_gpu) +diff_im[diff_im > tolerance] = 1 +a=fig.add_subplot(1,4,4) +imgplot = plt.imshow(diff_im, vmin=0, vmax=1, cmap="gray") +plt.title('{}'.format('Pixels larger threshold difference')) +if (diff_im.sum() > 1): + print ("Arrays do not match!") +else: + print ("Arrays match") + + + +print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") +print ("____________FGP-dTV bench___________________") +print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") + +## plot +fig = plt.figure(5) plt.suptitle('Comparison of FGP-dTV regulariser using CPU and GPU implementations') a=fig.add_subplot(1,4,1) a.set_title('Noisy Image') diff --git a/Wrappers/Python/demos/demo_gpu_regularisers.py b/Wrappers/Python/demos/demo_gpu_regularisers.py index 25d8d85..b873700 100644 --- a/Wrappers/Python/demos/demo_gpu_regularisers.py +++ b/Wrappers/Python/demos/demo_gpu_regularisers.py @@ -12,7 +12,7 @@ import matplotlib.pyplot as plt import numpy as np import os import timeit -from ccpi.filters.regularisers import ROF_TV, FGP_TV, SB_TV, FGP_dTV +from ccpi.filters.regularisers import ROF_TV, FGP_TV, SB_TV, FGP_dTV, NDF from qualitymetrics import rmse ############################################################################### def printParametersToString(pars): @@ -50,7 +50,7 @@ u0 = u0.astype('float32') u_ref = u_ref.astype('float32') print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") -print ("____________ROF-TV bench___________________") +print ("____________ROF-TV regulariser_____________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot @@ -92,7 +92,7 @@ plt.title('{}'.format('GPU results')) print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") -print ("____________FGP-TV bench___________________") +print ("____________FGP-TV regulariser_____________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot @@ -141,7 +141,7 @@ plt.title('{}'.format('GPU results')) print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") -print ("____________SB-TV bench___________________") +print ("____________SB-TV regulariser______________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot @@ -186,12 +186,60 @@ a.text(0.15, 0.25, txtstr, transform=a.transAxes, fontsize=14, imgplot = plt.imshow(sb_gpu, cmap="gray") plt.title('{}'.format('GPU results')) + print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") -print ("____________FGP-dTV bench___________________") +print ("_______________NDF regulariser_____________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot fig = plt.figure(4) +plt.suptitle('Performance of the NDF regulariser using the GPU') +a=fig.add_subplot(1,2,1) +a.set_title('Noisy Image') +imgplot = plt.imshow(u0,cmap="gray") + +# set parameters +pars = {'algorithm' : NDF, \ + 'input' : u0,\ + 'regularisation_parameter':0.06, \ + 'edge_parameter':0.04,\ + 'number_of_iterations' :1000 ,\ + 'time_marching_parameter':0.025,\ + 'penalty_type': 1 + } + +print ("##############NDF GPU##################") +start_time = timeit.default_timer() +ndf_gpu = NDF(pars['input'], + pars['regularisation_parameter'], + pars['edge_parameter'], + pars['number_of_iterations'], + pars['time_marching_parameter'], + pars['penalty_type'],'gpu') + +rms = rmse(Im, ndf_gpu) +pars['rmse'] = rms +pars['algorithm'] = NDF +txtstr = printParametersToString(pars) +txtstr += "%s = %.3fs" % ('elapsed time',timeit.default_timer() - start_time) +print (txtstr) +a=fig.add_subplot(1,2,2) + +# these are matplotlib.patch.Patch properties +props = dict(boxstyle='round', facecolor='wheat', alpha=0.75) +# place a text box in upper left in axes coords +a.text(0.15, 0.25, txtstr, transform=a.transAxes, fontsize=14, + verticalalignment='top', bbox=props) +imgplot = plt.imshow(ndf_gpu, cmap="gray") +plt.title('{}'.format('GPU results')) + + +print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") +print ("____________FGP-dTV bench___________________") +print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") + +## plot +fig = plt.figure(5) plt.suptitle('Performance of the FGP-dTV regulariser using the GPU') a=fig.add_subplot(1,2,1) a.set_title('Noisy Image') @@ -266,7 +314,7 @@ print ("_______________ROF-TV (3D)_________________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot -fig = plt.figure(5) +fig = plt.figure(6) plt.suptitle('Performance of ROF-TV regulariser using the GPU') a=fig.add_subplot(1,2,1) a.set_title('Noisy 15th slice of a volume') @@ -306,7 +354,7 @@ print ("_______________FGP-TV (3D)__________________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot -fig = plt.figure(6) +fig = plt.figure(7) plt.suptitle('Performance of FGP-TV regulariser using the GPU') a=fig.add_subplot(1,2,1) a.set_title('Noisy Image') @@ -354,7 +402,7 @@ print ("_______________SB-TV (3D)__________________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot -fig = plt.figure(7) +fig = plt.figure(8) plt.suptitle('Performance of SB-TV regulariser using the GPU') a=fig.add_subplot(1,2,1) a.set_title('Noisy Image') @@ -395,12 +443,60 @@ a.text(0.15, 0.25, txtstr, transform=a.transAxes, fontsize=14, imgplot = plt.imshow(sb_gpu3D[10,:,:], cmap="gray") plt.title('{}'.format('Recovered volume on the GPU using SB-TV')) + +print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") +print ("_______________NDF-TV (3D)_________________") +print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") + +## plot +fig = plt.figure(9) +plt.suptitle('Performance of NDF regulariser using the GPU') +a=fig.add_subplot(1,2,1) +a.set_title('Noisy Image') +imgplot = plt.imshow(noisyVol[10,:,:],cmap="gray") + +# set parameters +pars = {'algorithm' : NDF, \ + 'input' : noisyVol,\ + 'regularisation_parameter':0.06, \ + 'edge_parameter':0.04,\ + 'number_of_iterations' :1000 ,\ + 'time_marching_parameter':0.025,\ + 'penalty_type': 1 + } + +print ("#############NDF GPU####################") +start_time = timeit.default_timer() +ndf_gpu3D = NDF(pars['input'], + pars['regularisation_parameter'], + pars['edge_parameter'], + pars['number_of_iterations'], + pars['time_marching_parameter'], + pars['penalty_type'],'gpu') + +rms = rmse(idealVol, ndf_gpu3D) +pars['rmse'] = rms + +txtstr = printParametersToString(pars) +txtstr += "%s = %.3fs" % ('elapsed time',timeit.default_timer() - start_time) +print (txtstr) +a=fig.add_subplot(1,2,2) + +# these are matplotlib.patch.Patch properties +props = dict(boxstyle='round', facecolor='wheat', alpha=0.75) +# place a text box in upper left in axes coords +a.text(0.15, 0.25, txtstr, transform=a.transAxes, fontsize=14, + verticalalignment='top', bbox=props) +imgplot = plt.imshow(ndf_gpu3D[10,:,:], cmap="gray") +plt.title('{}'.format('Recovered volume on the GPU using NDF')) + + print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print ("_______________FGP-dTV (3D)________________") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") ## plot -fig = plt.figure(8) +fig = plt.figure(10) plt.suptitle('Performance of FGP-dTV regulariser using the GPU') a=fig.add_subplot(1,2,1) a.set_title('Noisy Image') diff --git a/Wrappers/Python/setup-regularisers.py.in b/Wrappers/Python/setup-regularisers.py.in index 0681cc4..b900efe 100644 --- a/Wrappers/Python/setup-regularisers.py.in +++ b/Wrappers/Python/setup-regularisers.py.in @@ -37,6 +37,7 @@ extra_include_dirs += [os.path.join(".." , ".." , "Core"), os.path.join(".." , ".." , "Core", "regularisers_GPU" , "TV_FGP" ) , os.path.join(".." , ".." , "Core", "regularisers_GPU" , "TV_ROF" ) , os.path.join(".." , ".." , "Core", "regularisers_GPU" , "TV_SB" ) , + os.path.join(".." , ".." , "Core", "regularisers_GPU" , "NDF" ) , os.path.join(".." , ".." , "Core", "regularisers_GPU" , "dTV_FGP" ) , "."] diff --git a/Wrappers/Python/src/cpu_regularisers.pyx b/Wrappers/Python/src/cpu_regularisers.pyx index abbf3b0..7ed8fa1 100644 --- a/Wrappers/Python/src/cpu_regularisers.pyx +++ b/Wrappers/Python/src/cpu_regularisers.pyx @@ -21,10 +21,10 @@ cimport numpy as np cdef extern float TV_ROF_CPU_main(float *Input, float *Output, float lambdaPar, int iterationsNumb, float tau, int dimX, int dimY, int dimZ); cdef extern float TV_FGP_CPU_main(float *Input, float *Output, float lambdaPar, int iterationsNumb, float epsil, int methodTV, int nonneg, int printM, int dimX, int dimY, int dimZ); cdef extern float SB_TV_CPU_main(float *Input, float *Output, float lambdaPar, int iterationsNumb, float epsil, int methodTV, int printM, int dimX, int dimY, int dimZ); +cdef extern float Diffusion_CPU_main(float *Input, float *Output, float lambdaPar, float sigmaPar, int iterationsNumb, float tau, int penaltytype, int dimX, int dimY, int dimZ); cdef extern float TNV_CPU_main(float *Input, float *u, float lambdaPar, int maxIter, float tol, int dimX, int dimY, int dimZ); cdef extern float dTV_FGP_CPU_main(float *Input, float *InputRef, float *Output, float lambdaPar, int iterationsNumb, float epsil, float eta, int methodTV, int nonneg, int printM, int dimX, int dimY, int dimZ); - #****************************************************************# #********************** Total-variation ROF *********************# #****************************************************************# @@ -275,3 +275,47 @@ def TNV_3D(np.ndarray[np.float32_t, ndim=3, mode="c"] inputData, # Run TNV iterations for 3D (X,Y,Channels) data TNV_CPU_main(&inputData[0,0,0], &outputData[0,0,0], regularisation_parameter, iterationsNumb, tolerance_param, dims[2], dims[1], dims[0]) return outputData +#****************************************************************# +#***************Nonlinear (Isotropic) Diffusion******************# +#****************************************************************# +def NDF_CPU(inputData, regularisation_parameter, edge_parameter, iterationsNumb,time_marching_parameter, penalty_type): + if inputData.ndim == 2: + return NDF_2D(inputData, regularisation_parameter, edge_parameter, iterationsNumb, time_marching_parameter, penalty_type) + elif inputData.ndim == 3: + return NDF_3D(inputData, regularisation_parameter, edge_parameter, iterationsNumb, time_marching_parameter, penalty_type) + +def NDF_2D(np.ndarray[np.float32_t, ndim=2, mode="c"] inputData, + float regularisation_parameter, + float edge_parameter, + int iterationsNumb, + float time_marching_parameter, + int penalty_type): + cdef long dims[2] + dims[0] = inputData.shape[0] + dims[1] = inputData.shape[1] + + cdef np.ndarray[np.float32_t, ndim=2, mode="c"] outputData = \ + np.zeros([dims[0],dims[1]], dtype='float32') + + # Run Nonlinear Diffusion iterations for 2D data + Diffusion_CPU_main(&inputData[0,0], &outputData[0,0], regularisation_parameter, edge_parameter, iterationsNumb, time_marching_parameter, penalty_type, dims[0], dims[1], 1) + return outputData + +def NDF_3D(np.ndarray[np.float32_t, ndim=3, mode="c"] inputData, + float regularisation_parameter, + float edge_parameter, + int iterationsNumb, + float time_marching_parameter, + int penalty_type): + cdef long dims[3] + dims[0] = inputData.shape[0] + dims[1] = inputData.shape[1] + dims[2] = inputData.shape[2] + + cdef np.ndarray[np.float32_t, ndim=3, mode="c"] outputData = \ + np.zeros([dims[0],dims[1],dims[2]], dtype='float32') + + # Run Nonlinear Diffusion iterations for 3D data + Diffusion_CPU_main(&inputData[0,0,0], &outputData[0,0,0], regularisation_parameter, edge_parameter, iterationsNumb, time_marching_parameter, penalty_type, dims[2], dims[1], dims[0]) + + return outputData diff --git a/Wrappers/Python/src/gpu_regularisers.pyx b/Wrappers/Python/src/gpu_regularisers.pyx index 36eec95..b0775054 100644 --- a/Wrappers/Python/src/gpu_regularisers.pyx +++ b/Wrappers/Python/src/gpu_regularisers.pyx @@ -21,6 +21,7 @@ cimport numpy as np cdef extern void TV_ROF_GPU_main(float* Input, float* Output, float lambdaPar, int iter, float tau, int N, int M, int Z); cdef extern void TV_FGP_GPU_main(float *Input, float *Output, float lambdaPar, int iter, float epsil, int methodTV, int nonneg, int printM, int N, int M, int Z); cdef extern void TV_SB_GPU_main(float *Input, float *Output, float lambdaPar, int iter, float epsil, int methodTV, int printM, int N, int M, int Z); +cdef extern void NonlDiff_GPU_main(float *Input, float *Output, float lambdaPar, float sigmaPar, int iterationsNumb, float tau, int penaltytype, int N, int M, int Z); cdef extern void dTV_FGP_GPU_main(float *Input, float *InputRef, float *Output, float lambdaPar, int iterationsNumb, float epsil, float eta, int methodTV, int nonneg, int printM, int N, int M, int Z); # Total-variation Rudin-Osher-Fatemi (ROF) @@ -114,6 +115,27 @@ def dTV_FGP_GPU(inputData, methodTV, nonneg, printM) +# Nonlocal Isotropic Diffusion (NDF) +def NDF_GPU(inputData, + regularisation_parameter, + edge_parameter, + iterations, + time_marching_parameter, + penalty_type): + if inputData.ndim == 2: + return NDF_GPU_2D(inputData, + regularisation_parameter, + edge_parameter, + iterations, + time_marching_parameter, + penalty_type) + elif inputData.ndim == 3: + return NDF_GPU_3D(inputData, + regularisation_parameter, + edge_parameter, + iterations, + time_marching_parameter, + penalty_type) #****************************************************************# #********************** Total-variation ROF *********************# #****************************************************************# @@ -336,3 +358,48 @@ def FGPdTV3D(np.ndarray[np.float32_t, ndim=3, mode="c"] inputData, printM, dims[2], dims[1], dims[0]); return outputData + +#****************************************************************# +#***************Nonlinear (Isotropic) Diffusion******************# +#****************************************************************# +def NDF_GPU_2D(np.ndarray[np.float32_t, ndim=2, mode="c"] inputData, + float regularisation_parameter, + float edge_parameter, + int iterationsNumb, + float time_marching_parameter, + int penalty_type): + cdef long dims[2] + dims[0] = inputData.shape[0] + dims[1] = inputData.shape[1] + + cdef np.ndarray[np.float32_t, ndim=2, mode="c"] outputData = \ + np.zeros([dims[0],dims[1]], dtype='float32') + + #rangecheck = penalty_type < 1 and penalty_type > 3 + #if not rangecheck: +# raise ValueError('Choose penalty type as 1 for Huber, 2 - Perona-Malik, 3 - Tukey Biweight') + + # Run Nonlinear Diffusion iterations for 2D data + # Running CUDA code here + NonlDiff_GPU_main(&inputData[0,0], &outputData[0,0], regularisation_parameter, edge_parameter, iterationsNumb, time_marching_parameter, penalty_type, dims[0], dims[1], 1) + return outputData + +def NDF_GPU_3D(np.ndarray[np.float32_t, ndim=3, mode="c"] inputData, + float regularisation_parameter, + float edge_parameter, + int iterationsNumb, + float time_marching_parameter, + int penalty_type): + cdef long dims[3] + dims[0] = inputData.shape[0] + dims[1] = inputData.shape[1] + dims[2] = inputData.shape[2] + + cdef np.ndarray[np.float32_t, ndim=3, mode="c"] outputData = \ + np.zeros([dims[0],dims[1],dims[2]], dtype='float32') + + # Run Nonlinear Diffusion iterations for 3D data + # Running CUDA code here + NonlDiff_GPU_main(&inputData[0,0,0], &outputData[0,0,0], regularisation_parameter, edge_parameter, iterationsNumb, time_marching_parameter, penalty_type, dims[2], dims[1], dims[0]) + + return outputData |