From 1e9d5bc4ad830ff6ddb3cd9fbb8239d7a93b43be Mon Sep 17 00:00:00 2001 From: dkazanc Date: Fri, 13 Dec 2019 17:57:21 +0000 Subject: initial modification of NDF --- Readme.md | 14 ++-- src/Core/regularisers_CPU/Diffusion_core.c | 88 ++++++++++++++++---------- src/Core/regularisers_GPU/NonlDiff_GPU_core.cu | 48 ++++++++++++-- 3 files changed, 104 insertions(+), 46 deletions(-) diff --git a/Readme.md b/Readme.md index 13e182b..077d2f2 100644 --- a/Readme.md +++ b/Readme.md @@ -101,13 +101,13 @@ conda install ccpi-regulariser -c ccpi -c conda-forge #### Python (conda-build) ``` - export CIL_VERSION=19.10 (Unix) / set CIL_VERSION=19.10 (Windows) - conda build recipe/ --numpy 1.15 --python 3.7 - conda install ccpi-regulariser=${CIL_VERSION} --use-local --force-reinstall # doesn't work? - conda install -c file://${CONDA_PREFIX}/conda-bld/ ccpi-regulariser=${CIL_VERSION} --force-reinstall # try this one - cd demos/ - python demo_cpu_regularisers.py # to run CPU demo - python demo_gpu_regularisers.py # to run GPU demo +export CIL_VERSION=19.10.1 (Unix) / set CIL_VERSION=19.10 (Windows) +conda build recipe/ --numpy 1.15 --python 3.7 +conda install ccpi-regulariser=${CIL_VERSION} --use-local --force-reinstall # doesn't work? +conda install -c file://${CONDA_PREFIX}/conda-bld/ ccpi-regulariser=${CIL_VERSION} --force-reinstall # try this one +cd demos/ +python demo_cpu_regularisers.py # to run CPU demo +python demo_gpu_regularisers.py # to run GPU demo ``` #### Python build diff --git a/src/Core/regularisers_CPU/Diffusion_core.c b/src/Core/regularisers_CPU/Diffusion_core.c index f0039c7..1a05c39 100644 --- a/src/Core/regularisers_CPU/Diffusion_core.c +++ b/src/Core/regularisers_CPU/Diffusion_core.c @@ -38,7 +38,7 @@ int signNDFc(float x) { * 3. Edge-preserving parameter (sigma), when sigma equals to zero nonlinear diffusion -> linear diffusion * 4. Number of iterations, for explicit scheme >= 150 is recommended * 5. tau - time-marching step for explicit scheme - * 6. Penalty type: 1 - Huber, 2 - Perona-Malik, 3 - Tukey Biweight + * 6. Penalty type: 1 - Huber, 2 - Perona-Malik, 3 - Tukey Biweight, 4 - Threshold-constrained Linear * 7. eplsilon - tolerance constant * * Output: @@ -60,14 +60,14 @@ float Diffusion_CPU_main(float *Input, float *Output, float *infovector, float l re = 0.0f; re1 = 0.0f; int count = 0; DimTotal = (long)(dimX*dimY*dimZ); - + if (epsil != 0.0f) Output_prev = calloc(DimTotal, sizeof(float)); - + /* copy into output */ copyIm(Input, Output, (long)(dimX), (long)(dimY), (long)(dimZ)); - + for(i=0; i < iterationsNumb; i++) { - + if ((epsil != 0.0f) && (i % 5 == 0)) copyIm(Output, Output_prev, (long)(dimX), (long)(dimY), (long)(dimZ)); if (dimZ == 1) { /* running 2D diffusion iterations */ @@ -93,7 +93,7 @@ float Diffusion_CPU_main(float *Input, float *Output, float *infovector, float l if (count > 3) break; } } - + free(Output_prev); /*adding info into info_vector */ infovector[0] = (float)(i); /*iterations number (if stopped earlier based on tolerance)*/ @@ -109,7 +109,7 @@ float LinearDiff2D(float *Input, float *Output, float lambdaPar, float tau, long { long i,j,i1,i2,j1,j2,index; float e,w,n,s,e1,w1,n1,s1; - + #pragma omp parallel for shared(Input) private(index,i,j,i1,i2,j1,j2,e,w,n,s,e1,w1,n1,s1) for(j=0; j sigmaPar) e1 = signNDFc(e1); else e1 = e1/sigmaPar; - + if (fabs(w1) > sigmaPar) w1 = signNDFc(w1); else w1 = w1/sigmaPar; - + if (fabs(n1) > sigmaPar) n1 = signNDFc(n1); else n1 = n1/sigmaPar; - + if (fabs(s1) > sigmaPar) s1 = signNDFc(s1); else s1 = s1/sigmaPar; } @@ -195,8 +195,18 @@ float NonLinearDiff2D(float *Input, float *Output, float lambdaPar, float sigmaP if (fabs(s1) <= sigmaPar) s1 = s1*powf((1.0f - powf((s1/sigmaPar),2)), 2); else s1 = 0.0f; } + else if (penaltytype == 4) { + /* Threshold-constrained linear diffusion + This means that the linear diffusion will be performed on pixels with + absolute difference less than the threshold. + */ + if (fabs(e1) > sigmaPar) e1 = 0.0f; + if (fabs(w1) > sigmaPar) w1 = 0.0f; + if (fabs(n1) > sigmaPar) n1 = 0.0f; + if (fabs(s1) > sigmaPar) s1 = 0.0f; + } else { - printf("%s \n", "No penalty function selected! Use 1,2 or 3."); + printf("%s \n", "No penalty function selected! Use 1,2,3 or 4."); break; } Output[index] += tau*(lambdaPar*(e1 + w1 + n1 + s1) - (Output[index] - Input[index])); @@ -211,7 +221,7 @@ float LinearDiff3D(float *Input, float *Output, float lambdaPar, float tau, long { long i,j,k,i1,i2,j1,j2,k1,k2,index; float e,w,n,s,u,d,e1,w1,n1,s1,u1,d1; - + #pragma omp parallel for shared(Input) private(index,i,j,i1,i2,j1,j2,e,w,n,s,e1,w1,n1,s1,k,k1,k2,u1,d1,u,d) for(k=0; k sigmaPar) e1 = signNDFc(e1); else e1 = e1/sigmaPar; - + if (fabs(w1) > sigmaPar) w1 = signNDFc(w1); else w1 = w1/sigmaPar; - + if (fabs(n1) > sigmaPar) n1 = signNDFc(n1); else n1 = n1/sigmaPar; - + if (fabs(s1) > sigmaPar) s1 = signNDFc(s1); else s1 = s1/sigmaPar; - + if (fabs(u1) > sigmaPar) u1 = signNDFc(u1); else u1 = u1/sigmaPar; - + if (fabs(d1) > sigmaPar) d1 = signNDFc(d1); else d1 = d1/sigmaPar; } @@ -322,11 +332,23 @@ float NonLinearDiff3D(float *Input, float *Output, float lambdaPar, float sigmaP if (fabs(d1) <= sigmaPar) d1 = d1*powf((1.0f - powf((d1/sigmaPar),2)), 2); else d1 = 0.0f; } + else if (penaltytype == 4) { + /* Threshold-constrained linear diffusion + This means that the linear diffusion will be performed on pixels with + absolute difference less than the threshold. + */ + if (fabs(e1) > sigmaPar) e1 = 0.0f; + if (fabs(w1) > sigmaPar) w1 = 0.0f; + if (fabs(n1) > sigmaPar) n1 = 0.0f; + if (fabs(s1) > sigmaPar) s1 = 0.0f; + if (fabs(u1) > sigmaPar) u1 = 0.0f; + if (fabs(d1) > sigmaPar) d1 = 0.0f; + } else { - printf("%s \n", "No penalty function selected! Use 1,2 or 3."); + printf("%s \n", "No penalty function selected! Use 1,2,3 or 4."); break; } - + Output[index] += tau*(lambdaPar*(e1 + w1 + n1 + s1 + u1 + d1) - (Output[index] - Input[index])); }}} return *Output; diff --git a/src/Core/regularisers_GPU/NonlDiff_GPU_core.cu b/src/Core/regularisers_GPU/NonlDiff_GPU_core.cu index de9abd4..a8876cd 100644 --- a/src/Core/regularisers_GPU/NonlDiff_GPU_core.cu +++ b/src/Core/regularisers_GPU/NonlDiff_GPU_core.cu @@ -32,7 +32,7 @@ limitations under the License. * 3. Edge-preserving parameter (sigma), when sigma equals to zero nonlinear diffusion -> linear diffusion * 4. Number of iterations, for explicit scheme >= 150 is recommended * 5. tau - time-marching step for explicit scheme - * 6. Penalty type: 1 - Huber, 2 - Perona-Malik, 3 - Tukey Biweight + * 6. Penalty type: 1 - Huber, 2 - Perona-Malik, 3 - Tukey Biweight, 4 - Threshold-constrained Linear * 7. eplsilon: tolerance constant * Output: @@ -108,8 +108,8 @@ __global__ void LinearDiff2D_kernel(float *Input, float *Output, float lambdaPar if ((i >= 0) && (i < N) && (j >= 0) && (j < M)) { /* boundary conditions (Neumann reflections) */ - i1 = i+1; if (i1 == N) i1 = i-1; - i2 = i-1; if (i2 < 0) i2 = i+1; + 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; @@ -155,7 +155,32 @@ __global__ void LinearDiff2D_kernel(float *Input, float *Output, float lambdaPar if (abs(s1) <= sigmaPar) s1 = s1*pow((1.0f - pow((s1/sigmaPar),2)), 2); else s1 = 0.0f; } - else printf("%s \n", "No penalty function selected! Use 1,2 or 3."); + else if (penaltytype == 4) { + /* Threshold-constrained linear diffusion + This means that the linear diffusion will be performed on pixels with + absolute difference less than the threshold. + */ + if (abs(e1) <= 1.5f*sigmaPar) { + if (abs(e1) > sigmaPar) e1 = signNDF(e1); + else e1 = e1/sigmaPar;} + else e1 = 0.0f; + + if (abs(w1) <= 1.5f*sigmaPar) { + if (abs(w1) > sigmaPar) w1 = signNDF(w1); + else w1 = w1/sigmaPar;} + else w1 = 0.0f; + + if (abs(n1) <= 1.5f*sigmaPar) { + if (abs(n1) > sigmaPar) n1 = signNDF(n1); + else n1 = n1/sigmaPar; } + else n1 = 0.0f; + + if (abs(s1) <= 1.5f*sigmaPar) { + if (abs(s1) > sigmaPar) s1 = signNDF(s1); + else s1 = s1/sigmaPar; } + else s1 = 0.0f; + } + else printf("%s \n", "No penalty function selected! Use 1,2,3 or 4."); Output[index] += tau*(lambdaPar*(e1 + w1 + n1 + s1) - (Output[index] - Input[index])); } @@ -281,8 +306,19 @@ __global__ void NonLinearDiff3D_kernel(float *Input, float *Output, float lambda 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."); - + else if (penaltytype == 4) { + /* Threshold-constrained linear diffusion + This means that the linear diffusion will be performed on pixels with + absolute difference less than the threshold. + */ + if (abs(e1) > sigmaPar) e1 = 0.0f; + if (abs(w1) > sigmaPar) w1 = 0.0f; + if (abs(n1) > sigmaPar) n1 = 0.0f; + if (abs(s1) > sigmaPar) s1 = 0.0f; + if (abs(u1) > sigmaPar) u1 = 0.0f; + if (abs(d1) > sigmaPar) d1 = 0.0f; + } + else printf("%s \n", "No penalty function selected! Use 1,2,3 or 4."); Output[index] += tau*(lambdaPar*(e1 + w1 + n1 + s1 + u1 + d1) - (Output[index] - Input[index])); } } -- cgit v1.2.3 From a3e360fcac7e1656802deb414fbd7b9d9f7e1038 Mon Sep 17 00:00:00 2001 From: Daniil Kazantsev Date: Sun, 15 Dec 2019 15:29:40 +0000 Subject: methods added --- build/run.sh | 4 +- src/Core/regularisers_CPU/Diffusion_core.c | 70 +++++++++++++++++++++++--- src/Core/regularisers_GPU/NonlDiff_GPU_core.cu | 57 ++++++++++++++++++--- 3 files changed, 117 insertions(+), 14 deletions(-) diff --git a/build/run.sh b/build/run.sh index f0b3d3e..91c5f05 100755 --- a/build/run.sh +++ b/build/run.sh @@ -6,11 +6,11 @@ rm -r ../build_proj mkdir ../build_proj cd ../build_proj/ #make clean -export CIL_VERSION=19.10 +export CIL_VERSION=19.10.1 # install Python modules without CUDA #cmake ../ -DBUILD_PYTHON_WRAPPER=ON -DBUILD_MATLAB_WRAPPER=OFF -DBUILD_CUDA=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./install # install Python modules with CUDA -cmake ../ -DBUILD_PYTHON_WRAPPER=ON -DBUILD_MATLAB_WRAPPER=OFF -DBUILD_CUDA=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./install + cmake ../ -DBUILD_PYTHON_WRAPPER=ON -DBUILD_MATLAB_WRAPPER=OFF -DBUILD_CUDA=ON -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./install # install Matlab modules without CUDA # cmake ../ -DBUILD_PYTHON_WRAPPER=OFF -DMatlab_ROOT_DIR=/dls_sw/apps/matlab/r2014a/ -DBUILD_MATLAB_WRAPPER=ON -DBUILD_CUDA=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=./install # install Matlab modules with CUDA diff --git a/src/Core/regularisers_CPU/Diffusion_core.c b/src/Core/regularisers_CPU/Diffusion_core.c index 1a05c39..fdd60de 100644 --- a/src/Core/regularisers_CPU/Diffusion_core.c +++ b/src/Core/regularisers_CPU/Diffusion_core.c @@ -179,10 +179,10 @@ float NonLinearDiff2D(float *Input, float *Output, float lambdaPar, float sigmaP } else if (penaltytype == 2) { /* Perona-Malik */ - e1 = (e1)/(1.0f + powf((e1/sigmaPar),2)); - w1 = (w1)/(1.0f + powf((w1/sigmaPar),2)); - n1 = (n1)/(1.0f + powf((n1/sigmaPar),2)); - s1 = (s1)/(1.0f + powf((s1/sigmaPar),2)); + e1 /= (1.0f + powf((e1/sigmaPar),2)); + w1 /= (1.0f + powf((w1/sigmaPar),2)); + n1 /= (1.0f + powf((n1/sigmaPar),2)); + s1 /= (1.0f + powf((s1/sigmaPar),2)); } else if (penaltytype == 3) { /* Tukey Biweight */ @@ -205,8 +205,32 @@ float NonLinearDiff2D(float *Input, float *Output, float lambdaPar, float sigmaP if (fabs(n1) > sigmaPar) n1 = 0.0f; if (fabs(s1) > sigmaPar) s1 = 0.0f; } + else if (penaltytype == 5) { + /* + Threshold constrained Huber diffusion + */ + if (fabs(e1) <= 2.0f*sigmaPar) { + if (fabs(e1) > sigmaPar) e1 = signNDFc(e1); + else e1 = e1/sigmaPar; } + else e1 = 0.0f; + + if (fabs(w1) <= 2.0f*sigmaPar) { + if (fabs(w1) > sigmaPar) w1 = signNDFc(w1); + else w1 = w1/sigmaPar; } + else w1 = 0.0f; + + if (fabs(n1) <= 2.0f*sigmaPar) { + if (fabs(n1) > sigmaPar) n1 = signNDFc(n1); + else n1 = n1/sigmaPar; } + else n1 = 0.0f; + + if (fabs(s1) <= 2.0f*sigmaPar) { + if (fabs(s1) > sigmaPar) s1 = signNDFc(s1); + else s1 = s1/sigmaPar; } + else s1 = 0.0f; + } else { - printf("%s \n", "No penalty function selected! Use 1,2,3 or 4."); + printf("%s \n", "No penalty function selected! Use 1,2,3,4 or 5."); break; } Output[index] += tau*(lambdaPar*(e1 + w1 + n1 + s1) - (Output[index] - Input[index])); @@ -344,8 +368,42 @@ float NonLinearDiff3D(float *Input, float *Output, float lambdaPar, float sigmaP if (fabs(u1) > sigmaPar) u1 = 0.0f; if (fabs(d1) > sigmaPar) d1 = 0.0f; } + else if (penaltytype == 5) { + /* + Threshold constrained Huber diffusion + */ + if (fabs(e1) <= 2.0f*sigmaPar) { + if (fabs(e1) > sigmaPar) e1 = signNDFc(e1); + else e1 = e1/sigmaPar; } + else e1 = 0.0f; + + if (fabs(w1) <= 2.0f*sigmaPar) { + if (fabs(w1) > sigmaPar) w1 = signNDFc(w1); + else w1 = w1/sigmaPar; } + else w1 = 0.0f; + + if (fabs(n1) <= 2.0f*sigmaPar) { + if (fabs(n1) > sigmaPar) n1 = signNDFc(n1); + else n1 = n1/sigmaPar; } + else n1 = 0.0f; + + if (fabs(s1) <= 2.0f*sigmaPar) { + if (fabs(s1) > sigmaPar) s1 = signNDFc(s1); + else s1 = s1/sigmaPar; } + else s1 = 0.0f; + + if (fabs(u1) <= 2.0f*sigmaPar) { + if (fabs(u1) > sigmaPar) u1 = signNDFc(u1); + else u1 = u1/sigmaPar; } + else u1 = 0.0f; + + if (fabs(d1) <= 2.0f*sigmaPar) { + if (fabs(d1) > sigmaPar) d1 = signNDFc(d1); + else d1 = d1/sigmaPar; } + else d1 = 0.0f; + } else { - printf("%s \n", "No penalty function selected! Use 1,2,3 or 4."); + printf("%s \n", "No penalty function selected! Use 1,2,3,4 or 5."); break; } diff --git a/src/Core/regularisers_GPU/NonlDiff_GPU_core.cu b/src/Core/regularisers_GPU/NonlDiff_GPU_core.cu index a8876cd..0d34cf8 100644 --- a/src/Core/regularisers_GPU/NonlDiff_GPU_core.cu +++ b/src/Core/regularisers_GPU/NonlDiff_GPU_core.cu @@ -160,27 +160,37 @@ __global__ void LinearDiff2D_kernel(float *Input, float *Output, float lambdaPar This means that the linear diffusion will be performed on pixels with absolute difference less than the threshold. */ - if (abs(e1) <= 1.5f*sigmaPar) { + if (abs(e1) > sigmaPar) e1 = 0.0f; + if (abs(w1) > sigmaPar) w1 = 0.0f; + if (abs(n1) > sigmaPar) n1 = 0.0f; + if (abs(s1) > sigmaPar) s1 = 0.0f; + } + else if (penaltytype == 5) { + /* Threshold-constrained Huber nonlinear diffusion + This means that the linear diffusion will be performed on pixels with + absolute difference less than the threshold. + */ + if (abs(e1) <= 2.0f*sigmaPar) { if (abs(e1) > sigmaPar) e1 = signNDF(e1); else e1 = e1/sigmaPar;} else e1 = 0.0f; - if (abs(w1) <= 1.5f*sigmaPar) { + if (abs(w1) <= 2.0f*sigmaPar) { if (abs(w1) > sigmaPar) w1 = signNDF(w1); else w1 = w1/sigmaPar;} else w1 = 0.0f; - if (abs(n1) <= 1.5f*sigmaPar) { + if (abs(n1) <= 2.0f*sigmaPar) { if (abs(n1) > sigmaPar) n1 = signNDF(n1); else n1 = n1/sigmaPar; } else n1 = 0.0f; - if (abs(s1) <= 1.5f*sigmaPar) { + if (abs(s1) <= 2.0f*sigmaPar) { if (abs(s1) > sigmaPar) s1 = signNDF(s1); else s1 = s1/sigmaPar; } else s1 = 0.0f; } - else printf("%s \n", "No penalty function selected! Use 1,2,3 or 4."); + else printf("%s \n", "No penalty function selected! Use 1,2,3, 4 or 5."); Output[index] += tau*(lambdaPar*(e1 + w1 + n1 + s1) - (Output[index] - Input[index])); } @@ -318,7 +328,42 @@ __global__ void NonLinearDiff3D_kernel(float *Input, float *Output, float lambda if (abs(u1) > sigmaPar) u1 = 0.0f; if (abs(d1) > sigmaPar) d1 = 0.0f; } - else printf("%s \n", "No penalty function selected! Use 1,2,3 or 4."); + else if (penaltytype == 5) { + /* Threshold-constrained Huber nonlinear diffusion + This means that the linear diffusion will be performed on pixels with + absolute difference less than the threshold. + */ + if (abs(e1) <= 2.0f*sigmaPar) { + if (abs(e1) > sigmaPar) e1 = signNDF(e1); + else e1 = e1/sigmaPar;} + else e1 = 0.0f; + + if (abs(w1) <= 2.0f*sigmaPar) { + if (abs(w1) > sigmaPar) w1 = signNDF(w1); + else w1 = w1/sigmaPar;} + else w1 = 0.0f; + + if (abs(n1) <= 2.0f*sigmaPar) { + if (abs(n1) > sigmaPar) n1 = signNDF(n1); + else n1 = n1/sigmaPar; } + else n1 = 0.0f; + + if (abs(s1) <= 2.0f*sigmaPar) { + if (abs(s1) > sigmaPar) s1 = signNDF(s1); + else s1 = s1/sigmaPar; } + else s1 = 0.0f; + + if (abs(u1) <= 2.0f*sigmaPar) { + if (abs(u1) > sigmaPar) u1 = signNDF(u1); + else u1 = u1/sigmaPar; } + else u1 = 0.0f; + + if (abs(d1) <= 2.0f*sigmaPar) { + if (abs(d1) > sigmaPar) d1 = signNDF(d1); + else d1 = d1/sigmaPar; } + else d1 = 0.0f; + } + else printf("%s \n", "No penalty function selected! Use 1,2,3,4, or 5."); Output[index] += tau*(lambdaPar*(e1 + w1 + n1 + s1 + u1 + d1) - (Output[index] - Input[index])); } } -- cgit v1.2.3 From e98f2735ce27925f907e5a32bcd521f578b77dbe Mon Sep 17 00:00:00 2001 From: Daniil Kazantsev Date: Sun, 15 Dec 2019 23:39:45 +0000 Subject: mods --- src/Core/regularisers_CPU/Diffusion_core.c | 2 +- src/Core/regularisers_GPU/NonlDiff_GPU_core.cu | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Core/regularisers_CPU/Diffusion_core.c b/src/Core/regularisers_CPU/Diffusion_core.c index fdd60de..bd23a15 100644 --- a/src/Core/regularisers_CPU/Diffusion_core.c +++ b/src/Core/regularisers_CPU/Diffusion_core.c @@ -38,7 +38,7 @@ int signNDFc(float x) { * 3. Edge-preserving parameter (sigma), when sigma equals to zero nonlinear diffusion -> linear diffusion * 4. Number of iterations, for explicit scheme >= 150 is recommended * 5. tau - time-marching step for explicit scheme - * 6. Penalty type: 1 - Huber, 2 - Perona-Malik, 3 - Tukey Biweight, 4 - Threshold-constrained Linear + * 6. Penalty type: 1 - Huber, 2 - Perona-Malik, 3 - Tukey Biweight, 4 - Threshold-constrained Linear, , 5 - modified Huber with a dead stop on edge * 7. eplsilon - tolerance constant * * Output: diff --git a/src/Core/regularisers_GPU/NonlDiff_GPU_core.cu b/src/Core/regularisers_GPU/NonlDiff_GPU_core.cu index 0d34cf8..d7a6bac 100644 --- a/src/Core/regularisers_GPU/NonlDiff_GPU_core.cu +++ b/src/Core/regularisers_GPU/NonlDiff_GPU_core.cu @@ -32,7 +32,7 @@ limitations under the License. * 3. Edge-preserving parameter (sigma), when sigma equals to zero nonlinear diffusion -> linear diffusion * 4. Number of iterations, for explicit scheme >= 150 is recommended * 5. tau - time-marching step for explicit scheme - * 6. Penalty type: 1 - Huber, 2 - Perona-Malik, 3 - Tukey Biweight, 4 - Threshold-constrained Linear + * 6. Penalty type: 1 - Huber, 2 - Perona-Malik, 3 - Tukey Biweight, 4 - Threshold-constrained Linear, 5 - modified Huber with a dead stop on edge * 7. eplsilon: tolerance constant * Output: -- cgit v1.2.3