20 #ifdef MATLAB_MEX_FILE
25 #if defined(TVREG_DENOISE) || defined(TVREG_INPAINT)
29 #include "usolve_dct_inc.c"
30 #include "usolve_dft_inc.c"
33 #include "zsolve_inc.c"
98 int TvRestore(num *u,
const num *f,
int Width,
int Height,
int NumChannels,
101 const long NumPixels = ((long)Width) * ((long)Height);
102 const long NumEl = NumPixels * NumChannels;
104 usolver USolveFun = NULL;
105 zsolver ZSolveFun = NULL;
107 int i, Success = 0, DeconvFlag, DctFlag, Iter;
109 if(!u || !f || u == f || Width < 2 || Height < 2 || NumChannels <= 0)
116 &USolveFun, &ZSolveFun, &S.
Opt))
119 #if !defined(TVREG_DENOISE) && !defined(TVREG_INPAINT)
122 if(!S.
Opt.VaryingLambda)
123 fprintf(stderr,
"Please recompile with TVREG_DENOISE "
124 "for denoising problems.\n");
126 fprintf(stderr,
"Please recompile with TVREG_INPAINT "
127 "for inpainting problems.\n");
132 if(S.
Opt.VaryingLambda && (S.
Opt.LambdaWidth != Width
133 || S.
Opt.LambdaHeight != Height))
135 fprintf(stderr,
"Image is %dx%d but lambda is %dx%d.\n",
136 Width, Height, S.
Opt.LambdaWidth, S.
Opt.LambdaHeight);
151 S.z = S.ztilde = NULL;
154 S.A = S.B = S.ATrans = S.BTrans = S.KernelTrans = S.DenomTrans = NULL;
155 S.TransformA = S.TransformB = S.InvTransformA = S.InvTransformB = NULL;
165 if(S.
Opt.NoiseModel != NOISEMODEL_L2)
166 fprintf(stderr,
"Please recompile with TVREG_NONGAUSSIAN "
167 "for non-Gaussian noise models.\n");
169 fprintf(stderr,
"Please recompile with TVREG_DECONV and "
170 "TVREG_INPAINT for deconvolution-inpainting problems.\n");
176 if(!(S.z = (num *)
Malloc(
sizeof(num)*NumEl))
177 || !(S.ztilde = (num *)
Malloc(
sizeof(num)*NumEl)))
181 memcpy(S.z, S.
u,
sizeof(num)*NumEl);
182 memcpy(S.ztilde, S.
u,
sizeof(num)*NumEl);
191 fprintf(stderr,
"Please recompile with TVREG_DECONV "
192 "for deconvolution problems.\n");
198 if(!(S.ATrans = (num *)FFT(malloc)(
sizeof(num)*NumEl))
199 || !(S.BTrans = (num *)FFT(malloc)(
sizeof(num)*NumEl))
200 || !(S.A = (num *)FFT(malloc)(
sizeof(num)*NumEl))
201 || !(S.B = (num *)FFT(malloc)(
sizeof(num)*NumEl))
202 || !(S.KernelTrans = (num *)FFT(malloc)(
sizeof(num)*NumPixels))
203 || !(S.DenomTrans = (num *)
Malloc(
sizeof(num)*NumPixels))
204 || !InitDeconvDct(&S))
209 long NumTransPixels, NumTransEl, PadNumEl;
215 NumTransPixels = ((long)TransWidth) * ((long)S.
PadHeight);
216 NumTransEl = NumTransPixels * NumChannels;
219 if(!(S.ATrans = (num *)FFT(malloc)(
sizeof(
numcomplex)*NumTransEl))
220 || !(S.BTrans = (num *)FFT(malloc)(
sizeof(
numcomplex)*NumTransEl))
221 || !(S.A = (num *)FFT(malloc)(
sizeof(num)*PadNumEl))
222 || !(S.B = (num *)FFT(malloc)(
sizeof(num)*PadNumEl))
223 || !(S.KernelTrans = (num *)
224 FFT(malloc)(
sizeof(
numcomplex)*NumTransPixels))
225 || !(S.DenomTrans = (num *)
Malloc(
sizeof(num)*NumTransPixels))
226 || !InitDeconvFourier(&S))
234 for(i = 0, S.
fNorm = 0; i < NumEl; i++)
235 S.
fNorm += f[i] * f[i];
241 memcpy(u, f,
sizeof(num)*NumEl);
247 for(i = 0; i < NumEl; i++)
248 S.
d[i].
x = S.
d[i].
y = 0;
250 for(i = 0; i < NumEl; i++)
253 DiffNorm = (S.
Opt.Tol > 0) ? 1000*S.
Opt.Tol : 1000;
256 if(S.
Opt.PlotFun && !S.
Opt.PlotFun(0, 0, DiffNorm,
257 u, Width, Height, NumChannels, S.
Opt.PlotParam))
261 for(Iter = 1; Iter <= S.
Opt.MaxIter; Iter++)
267 DiffNorm = USolveFun(&S);
269 if(Iter >= 2 + S.
UseZ && DiffNorm < S.
Opt.Tol)
278 if(S.
Opt.PlotFun && !(S.
Opt.PlotFun(0, Iter, DiffNorm, u,
279 Width, Height, NumChannels, S.
Opt.PlotParam)))
284 Success = (Iter <= S.
Opt.MaxIter) ? 1 : 2;
287 S.
Opt.PlotFun(Success, (Iter <= S.
Opt.MaxIter) ? Iter : S.
Opt.MaxIter,
288 DiffNorm, u, Width, Height, NumChannels, S.
Opt.PlotParam);
307 FFT(free)(S.KernelTrans);
317 FFT(destroy_plan)(S.InvTransformB);
318 FFT(destroy_plan)(S.TransformB);
319 FFT(destroy_plan)(S.InvTransformA);
320 FFT(destroy_plan)(S.TransformA);
329 static int IsSymmetric(
const num *Kernel,
int KernelWidth,
int KernelHeight)
333 if(KernelWidth % 2 == 0 || KernelHeight % 2 == 0)
336 for(y = 0, yr = KernelHeight - 1; y < KernelHeight; y++, yr--)
337 for(x = 0, xr = KernelWidth - 1; x < KernelWidth; x++, xr--)
338 if(Kernel[x + KernelWidth*y] != Kernel[xr + KernelWidth*y]
339 || Kernel[x + KernelWidth*y] != Kernel[x + KernelWidth*yr])
348 usolver *USolveFun, zsolver *ZSolveFun,
const tvregopt *Opt)
355 *UseZ = (Opt->NoiseModel != NOISEMODEL_L2);
360 switch(Opt->NoiseModel)
363 *ZSolveFun = ZSolveL2;
366 *ZSolveFun = ZSolveL1;
368 case NOISEMODEL_POISSON:
369 *ZSolveFun = ZSolvePoisson;
381 if(Opt->VaryingLambda)
387 Opt->KernelWidth, Opt->KernelHeight);
390 *DeconvFlag = *DctFlag = 0;
394 #if defined(TVREG_DENOISE) || defined(TVREG_INPAINT)
395 *USolveFun = (!Opt->VaryingLambda) ?
403 *USolveFun = (*DctFlag) ? UDeconvDctZ : UDeconvFourierZ;
406 *USolveFun = (*DctFlag) ? UDeconvDct : UDeconvFourier;