Total Variation Deconvolution using Split Bregman
zsolve_inc.c
Go to the documentation of this file.
1 
48 static void ZSolveL1(tvregsolver *S);
63 static void ZSolveL2(tvregsolver *S);
74 static void ZSolvePoisson(tvregsolver *S);
75 
76 #ifndef DOXYGEN
77 #ifndef _FIDELITY
78 /* Recursively include file 3 times to define different z solvers */
79 #define _FIDELITY 1
80 #include __FILE__ /* Define ZSolveL1 */
81 #define _FIDELITY 2
82 #include __FILE__ /* Define ZSolveL2 */
83 #define _FIDELITY 3
84 #include __FILE__ /* Define ZSolvePoisson */
85 #else /* if _FIDELITY is defined */
86 
87 #include "tvregopt.h"
88 
89 #if _FIDELITY == 1
90 static void ZSolveL1(tvregsolver *S)
91 #elif _FIDELITY == 2
92 static void ZSolveL2(tvregsolver *S)
93 #elif _FIDELITY == 3
94 static void ZSolvePoisson(tvregsolver *S)
95 #endif
96 {
97  num *z = S->z;
98  num *ztilde = S->ztilde;
99  const num *Ku = S->Ku;
100  const num *f = S->f;
101  const num *VaryingLambda = S->Opt.VaryingLambda;
102  const num Gamma2 = S->Opt.Gamma2;
103  const int Width = S->Width;
104  const int Height = S->Height;
105  const int NumChannels = S->NumChannels;
106  const int PadWidth = S->PadWidth;
107  const int PadHeight = S->PadHeight;
108 
109  const long PadJump = ((long)PadWidth)*(PadHeight - Height);
110  num znew;
111  long k;
112  int x, y;
113 
114  if(!VaryingLambda) /* Constant fidelity weight */
115  {
116  const num Beta = S->Opt.Lambda / Gamma2;
117 
118  for(k = 0; k < NumChannels; k++, Ku += PadJump)
119  for(y = 0; y < Height; y++,
120  z += Width, ztilde += Width, f += Width, Ku += PadWidth)
121  {
122  for(x = 0; x < Width; x++)
123  {
124 # if _FIDELITY == 1 /* L1 fidelity */
125  znew = Ku[x] - f[x] + z[x] - ztilde[x];
126 
127  if(znew > Beta)
128  znew += f[x] - Beta;
129  else if(znew < -Beta)
130  znew += f[x] + Beta;
131  else
132  znew = f[x];
133 # elif _FIDELITY == 2 /* L2 fidelity */
134  znew = (Ku[x] + z[x] - ztilde[x] + Beta*f[x])
135  / (1 + Beta);
136 # elif _FIDELITY == 3 /* Poisson fidelity */
137  znew = (Ku[x] + z[x] - ztilde[x] - Beta)/2;
138  znew = znew + (num)sqrt(znew*znew + Beta*f[x]);
139 # endif
140 
141  ztilde[x] += 2*znew - z[x] - Ku[x];
142  z[x] = znew;
143  }
144  }
145  }
146  else /* Spatially varying fidelity weight */
147  {
148  const num *LambdaPtr;
149  num Beta;
150 
151  for(k = 0; k < NumChannels; k++, Ku += PadJump)
152  for(y = 0, LambdaPtr = VaryingLambda; y < Height; y++,
153  z += Width, ztilde += Width, f += Width, Ku += PadWidth)
154  {
155  for(x = 0; x < Width; x++)
156  {
157  Beta = LambdaPtr[x] / Gamma2;
158 
159 # if _FIDELITY == 1 /* L1 fidelity */
160  znew = Ku[x] - f[x] + z[x] - ztilde[x];
161 
162  if(znew > Beta)
163  znew += f[x] - Beta;
164  else if(znew < -Beta)
165  znew += f[x] + Beta;
166  else
167  znew = f[x];
168 # elif _FIDELITY == 2 /* L2 fidelity */
169  znew = (Ku[x] + z[x] - ztilde[x] + Beta*f[x])
170  / (1 + Beta);
171 # elif _FIDELITY == 3 /* Poisson fidelity */
172  znew = (Ku[x] + z[x] - ztilde[x] - Beta)/2;
173  znew = znew + (num)sqrt(znew*znew + Beta*f[x]);
174 # endif
175 
176  ztilde[x] += 2*znew - z[x] - Ku[x];
177  z[x] = znew;
178  }
179 
180  LambdaPtr += Width;
181  }
182  }
183 }
184 #undef _FIDELITY
185 #endif /* _FIDELITY */
186 #endif /* DOXYGEN */