Total Variation Deconvolution using Split Bregman
usolve_dct_inc.c
Go to the documentation of this file.
1 
14 #include <string.h>
15 #include "util_deconv.h"
16 
17 
29 static void AdjBlurDct(num *ATrans, FFT(plan) TransformA,
30  const num *KernelTrans,
31  int Width, int Height, int NumChannels, num Alpha)
32 {
33  const long NumPixels = ((long)Width) * ((long)Height);
34  long i;
35  int k;
36 
37  /* Compute ATrans = DCT[A] */
38  FFT(execute)(TransformA);
39 
40  /* Compute ATrans = Alpha . KernelTrans . ATrans */
41  for(k = 0; k < NumChannels; k++, ATrans += NumPixels)
42  for(i = 0; i < NumPixels; i++)
43  ATrans[i] = Alpha * KernelTrans[i] * ATrans[i];
44 }
45 
46 
58 static int InitDeconvDct(tvregsolver *S)
59 {
60  num *KernelTrans = S->KernelTrans;
61  num *DenomTrans = S->DenomTrans;
62  num *B = S->B;
63  const num *Kernel = S->Opt.Kernel;
64  const int KernelWidth = S->Opt.KernelWidth;
65  const int KernelHeight = S->Opt.KernelHeight;
66  const int Width = S->Width;
67  const int Height = S->Height;
68  const num Alpha = S->Alpha;
69  const long NumPixels = ((long)Width) * ((long)Height);
70  const long PadNumPixels = ((long)Width + 1) * ((long)Height + 1);
71  FFT(plan) Plan = NULL;
72  FFT(r2r_kind) Kind[2];
73  long i;
74  int x0, y0, x, y, xi, yi, Size[2];
75 
76  for(i = 0; i < PadNumPixels; i++)
77  B[i] = 0;
78 
79  x0 = -KernelWidth/2;
80  y0 = -KernelHeight/2;
81 
82  /* Pad Kernel to size Width by Height. If Kernel
83  happens to be larger, it is folded. */
84  for(y = 0; y < y0 + KernelHeight; y++)
85  {
86  yi = WSymExtension(Height + 1, y);
87 
88  for(x = 0; x < x0 + KernelWidth; x++)
89  {
90  xi = WSymExtension(Width + 1, x);
91  B[xi + (Width + 1)*yi] += Kernel[(x - x0) + KernelWidth*(y - y0)];
92  }
93  }
94 
95  /* Compute the DCT-I transform of the padded Kernel */
96  if(!(Plan = FFT(plan_r2r_2d)(Height + 1, Width + 1, B, KernelTrans,
97  FFTW_REDFT00, FFTW_REDFT00, FFTW_ESTIMATE | FFTW_DESTROY_INPUT)))
98  return 0;
99 
100  FFT(execute)(Plan);
101  FFT(destroy_plan)(Plan);
102 
103  /* Cut last row and column from KernelTrans */
104  for(y = 1, i = Width; y < Height; y++, i += Width)
105  memmove(KernelTrans + i, KernelTrans + i + y, sizeof(num)*Width);
106 
107  /* Precompute the denominator that will be used in the u-subproblem. */
108  for(y = 0, i = 0; y < Height; y++)
109  for(x = 0; x < Width; x++, i++)
110  DenomTrans[i] =
111  (num)(4*NumPixels*(Alpha*KernelTrans[i]*KernelTrans[i]
112  + 2*(2 - cos(x*M_PI/Width) - cos(y*M_PI/Height))));
113 
114  /* Plan DCT-II transforms */
115  Size[1] = Width;
116  Size[0] = Height;
117  Kind[0] = Kind[1] = FFTW_REDFT10;
118 
119  if(!(S->TransformA = FFT(plan_many_r2r)(2, Size, S->NumChannels,
120  S->A, NULL, 1, NumPixels, S->ATrans, NULL, 1, NumPixels, Kind,
121  FFTW_ESTIMATE | FFTW_DESTROY_INPUT))
122  || !(S->TransformB = FFT(plan_many_r2r)(2, Size, S->NumChannels,
123  S->B, NULL, 1, NumPixels, S->BTrans, NULL, 1, NumPixels, Kind,
124  FFTW_ESTIMATE | FFTW_DESTROY_INPUT)))
125  return 0;
126 
127  /* Plan inverse DCT-II transforms (DCT-III) */
128  Kind[0] = Kind[1] = FFTW_REDFT01;
129 
130  if(!(S->InvTransformA = FFT(plan_many_r2r)(2, Size, S->NumChannels,
131  S->ATrans, NULL, 1, NumPixels, S->A, NULL, 1, NumPixels, Kind,
132  FFTW_ESTIMATE | FFTW_DESTROY_INPUT))
133  || !(S->InvTransformB = FFT(plan_many_r2r)(2, Size, S->NumChannels,
134  S->BTrans, NULL, 1, NumPixels, S->B, NULL, 1, NumPixels, Kind,
135  FFTW_ESTIMATE | FFTW_DESTROY_INPUT)))
136  return 0;
137 
138  /* Compute ATrans = Alpha . KernelTrans . DCT[f] */
139  if(!S->UseZ)
140  {
141  memcpy(S->A, S->f, sizeof(num)*NumPixels*S->NumChannels);
142  AdjBlurDct(S->ATrans, S->TransformA,
143  KernelTrans, Width, Height, S->NumChannels, Alpha);
144  }
145 
146  S->Ku = S->A;
147  return 1;
148 }
149 
150 
157 static void UTransSolveDct(num *BTrans, num *B, FFT(plan) TransformB,
158  num *ATrans, const numvec2 *dtilde,
159  const num *DenomTrans, int Width, int Height, int NumChannels)
160 {
161  const long NumPixels = ((long)Width) * ((long)Height);
162  long i;
163  int k;
164 
165  /* Compute B = div(dtilde) */
166  Divergence(B, Width, Height, dtilde, Width, Height, NumChannels);
167 
168  /* Compute BTrans = DCT[B] */
169  FFT(execute)(TransformB);
170 
171  /* Compute BTrans = ( ATrans - BTrans ) / DenomTrans */
172  for(k = 0; k < NumChannels; k++, ATrans += NumPixels, BTrans += NumPixels)
173  for(i = 0; i < NumPixels; i++)
174  BTrans[i] = (ATrans[i] - BTrans[i]) / DenomTrans[i];
175 }
176 
177 
196 static num UDeconvDct(tvregsolver *S)
197 {
198  /* BTrans = ( ATrans - DCT[div(dtilde)] ) / DenomTrans */
199  UTransSolveDct(S->BTrans, S->B, S->TransformB, S->ATrans, S->dtilde,
200  S->DenomTrans, S->Width, S->Height, S->NumChannels);
201  /* B = IDCT[BTrans] */
202  FFT(execute)(S->InvTransformB);
203  /* Compute ||B - u||, and assign u = B */
204  return UUpdate(S);
205 }
206 
207 
208 #if defined(TVREG_USEZ) || defined(DOXYGEN)
209 
221 static num UDeconvDctZ(tvregsolver *S)
222 {
223  num *ATrans = S->ATrans;
224  num *BTrans = S->BTrans;
225  const num *KernelTrans = S->KernelTrans;
226  const int NumChannels = S->NumChannels;
227  const long NumPixels = ((long)S->Width) * ((long)S->Height);
228  long i;
229  int k;
230 
231  /* Compute ATrans = Alpha . KernelTrans . DCT[ztilde] */
232  memcpy(S->A, S->ztilde, sizeof(num)*NumPixels*NumChannels);
233  AdjBlurDct(ATrans, S->TransformA, KernelTrans,
234  S->Width, S->Height, NumChannels, S->Alpha);
235  /* BTrans = ( ATrans - DCT[div(dtilde)] ) / DenomTrans */
236  UTransSolveDct(BTrans, S->B, S->TransformB, ATrans, S->dtilde,
237  S->DenomTrans, S->Width, S->Height, NumChannels);
238 
239  /* Compute ATrans = KernelTrans . BTrans */
240  for(k = 0; k < NumChannels; k++, ATrans += NumPixels, BTrans += NumPixels)
241  for(i = 0; i < NumPixels; i++)
242  ATrans[i] = KernelTrans[i] * BTrans[i];
243 
244  /* A = IDCT[ATrans] = new Ku */
245  FFT(execute)(S->InvTransformA);
246  /* B = IDCT[BTrans] = new u */
247  FFT(execute)(S->InvTransformB);
248 
249  /* Compute ||B - u||, and assign u = B */
250  return UUpdate(S);
251 }
252 #endif